use std::io;
struct TicTacToe {
board: [[char; 3]; 3],
turn: bool,
}
impl TicTacToe {
fn new() -> Self {
Self {
board: [['.'; 3]; 3],
turn: true,
}
}
fn print(&self) {
println!();
for row in &self.board {
for &cell in row {
print!("{} ", cell);
}
println!();
}
}
fn make_move(&mut self, row: usize, col: usize) -> bool {
if row >= 3 || col >= 3 || self.board[row][col] != '.' {
return false;
}
self.board[row][col] = if self.turn { 'X' } else { 'O' };
self.turn = !self.turn;
true
}
fn check_win(&self) -> bool {
for row in &self.board {
if row[0] != '.' && row[0] == row[1] && row[1] == row[2] {
return true;
}
}
for col in 0..3 {
if self.board[0][col] != '.' && self.board[0][col] == self.board[1][col]
&& self.board[1][col] == self.board[2][col] {
return true;
}
}
if self.board[1][1] != '.' {
if (self.board[0][0] == self.board[1][1] && self.board[1][1] == self.board[2][2]) ||
(self.board[0][2] == self.board[1][1] && self.board[1][1] == self.board[2][0]) {
return true;
}
}
false
}
fn is_full(&self) -> bool {
for row in &self.board {
for &cell in row {
if cell == '.' {
return false;
}
}
}
true
}
}
pub fn play() {
let mut game = TicTacToe::new();
println!("\nTic-Tac-Toe - Enter row col (0-2), ex. \"0 0\"");
loop {
game.print();
println!("Player {} turn", if game.turn { 'X' } else { 'O' });
let mut input = String::new();
io::stdin().read_line(&mut input).unwrap();
let parts: Vec<&str> = input.trim().split_whitespace().collect();
if parts.len() != 2 {
continue;
}
let row: usize = match parts[0].parse() {
Ok(n) => n,
Err(_) => continue,
};
let col: usize = match parts[1].parse() {
Ok(n) => n,
Err(_) => continue,
};
if !game.make_move(row, col) {
println!("Invalid move!");
continue;
}
if game.check_win() {
game.print();
match game.turn{
true => println!("O's win!"),
false => println!("X's win!")
}
break;
}
if game.is_full() {
game.print();
println!("Draw!");
break;
}
}
}