diff --git a/src/board/tictactoe.rs b/src/board/tictactoe.rs index 20957216f28b9f2e76eb3282a2debf8f1f3a11bc..b5a44a390c77b6df58ddc90bea46246baf0a0a6f 100644 --- a/src/board/tictactoe.rs +++ b/src/board/tictactoe.rs @@ -6,6 +6,23 @@ pub enum Player { Circle, } +impl Default for Player { + fn default() -> Self { + Player::Cross + } +} + +impl std::ops::Not for Player { + type Output = Player; + + fn not(self) -> Self::Output { + match self { + Player::Cross => Player::Circle, + Player::Circle => Player::Cross, + } + } +} + impl std::fmt::Display for Player { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { @@ -50,9 +67,24 @@ pub enum Move { C3 = 8, } -// impl std::fmt::FromStr for Move { - -// } +impl FromStr for Move { + type Err = String; + + fn from_str(s: &str) -> Result<Self, Self::Err> { + match s { + "A1" => Ok(Move::A1), + "B1" => Ok(Move::B1), + "C1" => Ok(Move::C1), + "A2" => Ok(Move::A2), + "B2" => Ok(Move::B2), + "C2" => Ok(Move::C2), + "A3" => Ok(Move::A3), + "B3" => Ok(Move::B3), + "C3" => Ok(Move::C3), + _ => Err(format!("Illegal move {}", s)) + } + } +} impl Board { /// Creates a new empty board diff --git a/src/main.rs b/src/main.rs index 4fd4a6b492981a6264ec004eac8bd7548dc03148..6c0d36e2c41d289e2828e335b1970151bde36f9c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,11 +1,51 @@ mod board; use board::tictactoe::Board as TicTacToe; - +use board::Board; +use std::io; +use std::io::prelude::*; + +fn prompt<Player>(turn: Player) +where + Player: std::fmt::Display, +{ + print!("{}>", turn); + io::stdout().flush().unwrap(); +} + +fn play<Game, Move, Player>(mut board: Game) +where + Game: Board<Move, Player> + std::fmt::Display, + Player: Copy + std::fmt::Display + Default + std::ops::Not<Output = Player>, + Move: std::str::FromStr, +{ + let mut stdin = std::io::stdin().lock(); + let mut player = Player::default(); + + println!("Let start"); + println!("{board}"); + prompt(player); + + loop { + let mut input = String::default(); + stdin.read_line(&mut input).unwrap(); + let str_move = input.trim_end(); + if let Ok(m) = str_move.parse() { + board.do_move(player, &m); + println!("{board}"); + if board.has_won(player) { + println!("Victory!"); + return; + } + player = !player; + } + prompt(player); + } +} + fn main() { let board = TicTacToe::new(); - - board.display(); + play(board); } // Will only be build in 'test' configuration