1use prettytable::{cell, table, Table};
2
3use std::io;
4use std::io::Write;
5use std::str::FromStr;
6
7const CROSS: &'static str = "X";
8const EMPTY: &'static str = " ";
9const ROUND: &'static str = "O";
10
11fn main() {
12 let mut table = table![
13 [EMPTY, EMPTY, EMPTY],
14 [EMPTY, EMPTY, EMPTY],
15 [EMPTY, EMPTY, EMPTY]
16 ];
17 let mut height = table.print_tty(false).unwrap();
18 let stdin = io::stdin();
19 let mut stdout = io::stdout();
20 let mut current = CROSS;
21 let mut terminal = term::stdout().unwrap();
22 loop {
23 let mut line = String::new();
24 print!("{} plays > ", current);
25 height += 1;
26 stdout.flush().unwrap();
27 stdin.read_line(&mut line).expect("Cannot read input");
28 let i = match usize::from_str(line.trim()) {
29 Ok(i) => i,
30 _ => {
31 println!("Bad input");
32 height += 1;
33 continue;
34 }
35 };
36 if i < 1 || i > 9 {
37 println!("Bad input, should be between 1 and 9");
38 height += 1;
39 continue;
40 }
41 let x = (i - 1) % 3;
42 let y = (i - 1) / 3;
43 {
44 let row = table.get_mut_row(y).unwrap();
45 if row.get_cell(x).unwrap().to_string() != EMPTY {
46 println!("There's already someone there");
47 height += 1;
48 continue;
49 }
50 row.set_cell(cell!(current), x).unwrap();
51 }
52 for _ in 0..height {
53 terminal.cursor_up().unwrap();
54 terminal.delete_line().unwrap();
55 }
56 height = table.print_tty(false).unwrap();
57 if check(&table) {
58 return;
59 }
60 if current == CROSS {
61 current = ROUND;
62 } else {
63 current = CROSS;
64 }
65 }
66}
67
68fn get(table: &Table, x: usize, y: usize) -> String {
69 match table.get_row(y) {
70 Some(r) => match r.get_cell(x) {
71 Some(c) => c.to_string(),
72 _ => EMPTY.to_string(),
73 },
74 _ => EMPTY.to_string(),
75 }
76}
77
78fn is(table: &Table, s: &str, x: usize, y: usize) -> bool {
79 get(table, x, y).as_str() == s
80}
81
82fn check(table: &Table) -> bool {
83 let mut full = true;
84 for y in 0..3 {
85 for x in 0..3 {
86 if is(table, EMPTY, x, y) {
87 full = false;
88 continue;
89 }
90 let current = get(table, x, y);
91 let c = current.as_str();
92 if is(table, c, x + 1, y) && is(table, c, x + 2, y)
93 || is(table, c, x + 1, y + 1) && is(table, c, x + 2, y + 2)
94 || x >= 2 && is(table, c, x - 1, y + 1) && is(table, c, x - 2, y + 2)
95 || is(table, c, x, y + 1) && is(table, c, x, y + 2)
96 {
97 println!("Game is over. {} is the winner", current);
98 return true;
99 }
100 }
101 }
102 if full {
103 println!("Game is over. It's a draw");
104 }
105 full
106}