tictactoe_rust/board/
mod.rs

1pub enum BoardSize {
2    Small,
3    Big,
4}
5
6use std::fmt;
7impl fmt::Display for BoardSize {
8    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
9        write!(
10            f,
11            "{}",
12            match &self {
13                BoardSize::Small => "Small",
14                BoardSize::Big => "Big",
15            }
16        )
17    }
18}
19
20use super::game::Players;
21pub struct Board {
22    pub board: [Option<Players>; 9],
23    matches: Matches,
24}
25
26impl Default for Board {
27    fn default() -> Board {
28        Board {
29            board: [None; 9],
30            matches: Default::default(),
31        }
32    }
33}
34
35impl Board {
36    pub fn clear(&mut self) {
37        self.board = [None; 9];
38        self.matches = Default::default();
39    }
40    pub fn set_coordinate(
41        &mut self,
42        x: usize,
43        y: usize,
44        player: Players,
45    ) -> Result<(), &'static str> {
46        if x < 3 && y < 3 {
47            let cell = &mut self.board[3 * y + x];
48            if cell.is_some() {
49                Err("Already occupied")
50            } else {
51                *cell = Some(player);
52                Ok(())
53            }
54        } else {
55            Err("Index out of range.")
56        }
57    }
58
59    pub fn get_coordinate(&mut self, x: usize, y: usize) -> Result<Option<Players>, &'static str> {
60        if x < 3 && y < 3 {
61            Ok(self.board[3 * y + x])
62        } else {
63            Err("Index out of range.")
64        }
65    }
66
67    pub fn has_match_line(&self) -> Option<Players> {
68        match self.matches.has_match_line() {
69            Some(i) => self.board[i],
70            None => None,
71        }
72    }
73
74    pub fn print_matches(&self, num_of_spaces: usize) {
75        self.matches.print_matches(num_of_spaces);
76    }
77
78    pub fn is_full(&self) -> bool {
79        for i in self.board.iter() {
80            if i.is_none() {
81                return false;
82            }
83        }
84        true
85    }
86
87    pub fn update_matches(&mut self) {
88        if self.board[0] != None && self.board[1] == self.board[0] && self.board[2] == self.board[0]
89        {
90            self.matches.rows.0 = true;
91        }
92        if self.board[3] != None && self.board[4] == self.board[3] && self.board[5] == self.board[3]
93        {
94            self.matches.rows.1 = true;
95        }
96        if self.board[6] != None && self.board[7] == self.board[6] && self.board[8] == self.board[6]
97        {
98            self.matches.rows.2 = true;
99        }
100        if self.board[0] != None && self.board[3] == self.board[0] && self.board[6] == self.board[0]
101        {
102            self.matches.cols.0 = true;
103        }
104        if self.board[1] != None && self.board[4] == self.board[1] && self.board[7] == self.board[1]
105        {
106            self.matches.cols.1 = true;
107        }
108        if self.board[2] != None && self.board[5] == self.board[2] && self.board[8] == self.board[2]
109        {
110            self.matches.cols.2 = true;
111        }
112        if self.board[0] != None && self.board[4] == self.board[0] && self.board[8] == self.board[0]
113        {
114            self.matches.diags.0 = true;
115        }
116        if self.board[2] != None && self.board[4] == self.board[2] && self.board[6] == self.board[2]
117        {
118            self.matches.diags.1 = true;
119        }
120    }
121}
122
123struct Matches {
124    rows: (bool, bool, bool),
125    cols: (bool, bool, bool),
126    diags: (bool, bool),
127}
128
129impl Default for Matches {
130    fn default() -> Matches {
131        Matches {
132            rows: (false, false, false),
133            cols: (false, false, false),
134            diags: (false, false),
135        }
136    }
137}
138
139impl Matches {
140    fn has_match_line(&self) -> Option<usize> {
141        if self.rows.0 {
142            Some(0)
143        } else if self.rows.1 {
144            Some(3)
145        } else if self.rows.2 {
146            Some(6)
147        } else if self.cols.0 {
148            Some(0)
149        } else if self.cols.1 {
150            Some(1)
151        } else if self.cols.2 {
152            Some(2)
153        } else if self.diags.0 {
154            Some(0)
155        } else if self.diags.1 {
156            Some(2)
157        } else {
158            None
159        }
160    }
161
162    fn print_matches(&self, num_of_spaces: usize) {
163        let spaces = " ".repeat(num_of_spaces);
164        println!("Matches:");
165        if self.rows.0 {
166            println!("{}row 0", spaces)
167        };
168        if self.rows.1 {
169            println!("{}row 1", spaces)
170        };
171        if self.rows.2 {
172            println!("{}row 2", spaces)
173        };
174        if self.cols.0 {
175            println!("{}column 0", spaces)
176        };
177        if self.cols.1 {
178            println!("{}column 1", spaces)
179        };
180        if self.cols.2 {
181            println!("{}column 2", spaces)
182        };
183        if self.diags.0 {
184            println!("{}Top-left-bottom-right diagonal", spaces)
185        };
186        if self.diags.1 {
187            println!("{}Bottom-left-top-right diagonal", spaces)
188        };
189    }
190}
191
192#[cfg(test)]
193mod tests;