Advertisement
Guest User

Rust Command-line Tic-Tac-Toe

a guest
Apr 24th, 2017
70
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Rust 6.72 KB | None | 0 0
  1. use std::io;
  2. use std::io::Write;
  3.  
  4. #[derive(PartialEq, Eq, Copy, Clone)]
  5. enum BoardRow {
  6.     One,
  7.     Two,
  8.     Three
  9. }
  10.  
  11. impl BoardRow {
  12.     fn from_char(c: char) -> Option<BoardRow> {
  13.         match c {
  14.             '1' => Some(BoardRow::One),
  15.             '2' => Some(BoardRow::Two),
  16.             '3' => Some(BoardRow::Three),
  17.             _ => None
  18.         }
  19.     }
  20. }
  21.  
  22. #[derive(PartialEq, Eq, Copy, Clone)]
  23. enum BoardColumn {
  24.     A,
  25.     B,
  26.     C
  27. }
  28.  
  29. impl BoardColumn {
  30.     fn from_char(c: char) -> Option<BoardColumn> {
  31.         match c {
  32.             'A' => Some(BoardColumn::A),
  33.             'B' => Some(BoardColumn::B),
  34.             'C' => Some(BoardColumn::C),
  35.             _ => None
  36.         }
  37.     }
  38. }
  39.  
  40. #[derive(PartialEq, Eq, Copy, Clone)]
  41. struct BoardLocation(BoardRow, BoardColumn);
  42.  
  43. impl BoardLocation {
  44.     fn parse_from_string(s: &str) -> Option<BoardLocation> {
  45.         let input = &s.to_uppercase();
  46.  
  47.         let board_rows = input.chars().filter_map(&BoardRow::from_char).collect::<Vec<_>>();
  48.         let board_columns = input.chars().filter_map(&BoardColumn::from_char).collect::<Vec<_>>();
  49.  
  50.         if board_rows.len() != 1 || board_columns.len() != 1 {
  51.             None
  52.         } else {
  53.             Some(BoardLocation(board_rows[0], board_columns[0]))
  54.         }
  55.     }
  56. }
  57.  
  58. #[derive(PartialEq, Eq, Copy, Clone)]
  59. enum Player {
  60.     X,
  61.     O
  62. }
  63.  
  64. #[derive(PartialEq, Eq, Copy, Clone)]
  65. struct Board {
  66.     board: [[Option<Player>; 3]; 3]
  67. }
  68.  
  69. impl Board {
  70.     fn new() -> Board {
  71.         Board {board: [[None; 3]; 3]}
  72.     }
  73.  
  74.     fn display(&self) {
  75.         fn print_horizontal_rule() {
  76.             println!("-+-+-+-");
  77.         }
  78.  
  79.         println!(" |A|B|C");
  80.         print_horizontal_rule();
  81.  
  82.         let mut row_printed = false;
  83.         let mut vertical_key_row_num = 1;
  84.         for row in self.board.iter() {
  85.             if row_printed {
  86.                 print_horizontal_rule();
  87.             }
  88.  
  89.             print!("{}|", vertical_key_row_num);
  90.             vertical_key_row_num += 1;
  91.  
  92.             let mut space_printed = false;
  93.             for space in row.iter() {
  94.                 if space_printed {
  95.                     print!("|");
  96.                 }
  97.                 match *space {
  98.                     None => print!(" "),
  99.                     Some(Player::X) => print!("X"),
  100.                     Some(Player::O) => print!("O")
  101.                 }
  102.                 space_printed = true;
  103.             }
  104.             println!("");
  105.  
  106.             row_printed = true;
  107.         }
  108.     }
  109.  
  110.     fn get_winner(&self) -> Option<Player> {
  111.         let winning_space: Option<Player>;
  112.         if self.board[0][0] == self.board[0][1] && self.board[0][1] == self.board[0][2] {
  113.             winning_space = self.board[0][0];
  114.         } else if self.board[1][0] == self.board[1][1] && self.board[1][1] == self.board[1][2] {
  115.             winning_space = self.board[1][0];
  116.         } else if self.board[2][0] == self.board[2][1] && self.board[2][1] == self.board[2][2] {
  117.             winning_space = self.board[2][0];
  118.         } else if self.board[0][0] == self.board[1][0] && self.board[1][0] == self.board[2][0] {
  119.             winning_space = self.board[0][0];
  120.         } else if self.board[0][1] == self.board[1][1] && self.board[1][1] == self.board[2][1] {
  121.             winning_space = self.board[0][1];
  122.         } else if self.board[0][2] == self.board[1][2] && self.board[1][2] == self.board[2][2] {
  123.             winning_space = self.board[0][2];
  124.         } else if self.board[0][0] == self.board[1][1] && self.board[1][1] == self.board[2][2] {
  125.             winning_space = self.board[0][0];
  126.         } else if self.board[0][2] == self.board[1][1] && self.board[1][1] == self.board[2][0] {
  127.             winning_space = self.board[0][2];
  128.         } else {
  129.             winning_space = None;
  130.         }
  131.  
  132.         winning_space
  133.     }
  134.  
  135.     fn is_stalemated(&self) -> bool {
  136.         match self.get_winner() {
  137.             Some(_) => false,
  138.             None => {
  139.                 for row in self.board.iter() {
  140.                     for cell in row.iter() {
  141.                         if *cell == None {
  142.                             return false
  143.                         }
  144.                     }
  145.                 }
  146.                 true
  147.             }
  148.         }
  149.     }
  150.  
  151.     fn make_move(&mut self, player: Player, location: BoardLocation) {
  152.         let BoardLocation(row, column) = location;
  153.         let row_index: usize;
  154.         let column_index: usize;
  155.        
  156.         match row {
  157.             BoardRow::One => row_index = 0,
  158.             BoardRow::Two => row_index = 1,
  159.             BoardRow::Three => row_index = 2
  160.         }
  161.         match column {
  162.             BoardColumn::A => column_index = 0,
  163.             BoardColumn::B => column_index = 1,
  164.             BoardColumn::C => column_index = 2
  165.         }
  166.        
  167.         self.board[row_index][column_index] = Some(player);
  168.     }
  169. }
  170.  
  171. fn main() {
  172.     let mut board = Board::new();
  173.     board.display();
  174.  
  175.     let mut current_player = Player::X;
  176.     loop {
  177.         match current_player {
  178.             Player::X => print!("X, enter a location: "),
  179.             Player::O => print!("O, enter a location: ")
  180.         }
  181.         io::stdout().flush().unwrap();
  182.  
  183.         let mut response = String::new();
  184.         match io::stdin().read_line(&mut response) {
  185.             Ok(_) => {
  186.                 match BoardLocation::parse_from_string(&response) {
  187.                     Some(location) => {
  188.                         board.make_move(current_player, location);
  189.                         board.display();
  190.                         match board.get_winner() {
  191.                             Some(winning_player) => {
  192.                                 match winning_player {
  193.                                     Player::X => println!("X wins!"),
  194.                                     Player::O => println!("O wins!")
  195.                                 }
  196.                                 break;
  197.                             }
  198.                             None => {
  199.                                 if board.is_stalemated() {
  200.                                     println!("Nobody wins!");
  201.                                     break;
  202.                                 }
  203.                             }
  204.                         }
  205.                         match current_player {
  206.                             Player::X => current_player = Player::O,
  207.                             Player::O => current_player = Player::X
  208.                         }
  209.                     }
  210.                     None => {
  211.                         println!("That's not a location!");
  212.                     }
  213.                 }
  214.             }
  215.             Err(error) => {
  216.                 println!("Error: {}", error);
  217.                 break;
  218.             }
  219.         }
  220.     }
  221. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement