rust-cli-arcade 0.1.0

A collection of classic CLI games: Tic-Tac-Toe, Connect Four, Hangman, and Rock Paper Scissors
use std::io;

struct C4Board {
    board: Vec<Vec<char>>,
    turn: bool,
}

impl C4Board {
    fn new() -> Self {
        Self {
            board: vec![vec!['.'; 7]; 6],
            turn: true,
        }
    }

    fn print(&self) {
        for row in &self.board {
            for &cell in row {
                print!("{} ", cell);
            }
            println!();
        }
        println!("0 1 2 3 4 5 6");
    }

    fn drop(&mut self, col: usize) -> bool {
        if col >= 7 { return false; }

        for row in (0..6).rev() {
            if self.board[row][col] == '.' {
                self.board[row][col] = if self.turn { 'X' } else { 'O' };
                self.turn = !self.turn;
                return true;
            }
        }
        false
    }

    fn check_win(&self) -> bool {
        // Horizontal
        for row in 0..6 {
            for col in 0..4 {
                let c = self.board[row][col];
                if c != '.' && c == self.board[row][col+1] && 
                   c == self.board[row][col+2] && c == self.board[row][col+3] {
                    return true;
                }
            }
        }

        // Vertical
        for row in 0..3 {
            for col in 0..7 {
                let c = self.board[row][col];
                if c != '.' && c == self.board[row+1][col] && 
                   c == self.board[row+2][col] && c == self.board[row+3][col] {
                    return true;
                }
            }
        }

        // Diagonal down-right
        for row in 0..3 {
            for col in 0..4 {
                let c = self.board[row][col];
                if c != '.' && c == self.board[row+1][col+1] && 
                   c == self.board[row+2][col+2] && c == self.board[row+3][col+3] {
                    return true;
                }
            }
        }

        // Diagonal down-left
        for row in 0..3 {
            for col in 3..7 {
                let c = self.board[row][col];
                if c != '.' && c == self.board[row+1][col-1] && 
                   c == self.board[row+2][col-2] && c == self.board[row+3][col-3] {
                    return true;
                }
            }
        }

        false
    }

    fn is_full(&self) -> bool {
        for &cell in &self.board[0] {
            if cell == '.' {
                return false;
            }
        }
        true
    }
}

pub fn play() {
    let mut board = C4Board::new();
    
    println!("\nConnect Four - Enter column (0-6)");

    loop {
        board.print();

        let current_player = if board.turn { 'X' } else { 'O' };
        println!("Player {} - Enter column: ", current_player);

        let mut input = String::new();
        io::stdin().read_line(&mut input).unwrap();

        let col: usize = match input.trim().parse() {
            Ok(n) => n,
            Err(_) => continue,
        };

        if !board.drop(col) {
            println!("Invalid move!");
            continue;
        }

        if board.check_win() {
            board.print();
            match board.turn{
                true => println!("O's win!"),
                false => println!("X's win!")
            }
            break;
        }
        
        if board.is_full() {
            board.print();
            println!("Draw!");
            break;
        }
    }
}