1#[derive(Clone)]
3pub enum CellKind {
4 Mine,
5 Free,
6 Uninitialized,
7}
8
9#[derive(Clone)]
11pub enum CellState {
12 Closed,
13 Flagged,
14 Opened,
15}
16
17#[derive(Clone)]
19pub struct Cell {
20 pub kind: CellKind,
21 pub state: CellState,
22}
23
24pub trait SweeperCell {
26 fn open(&mut self) -> &CellKind;
27
28 fn flag(&mut self) -> &CellState;
29}
30
31impl SweeperCell for Cell {
33 fn open(&mut self) -> &CellKind {
34 if let CellState::Closed = self.state {
35 self.state = CellState::Opened
36 }
37 &self.kind
38 }
39
40 fn flag(&mut self) -> &CellState {
41 match self.state {
42 CellState::Closed => self.state = CellState::Flagged,
43 CellState::Flagged => self.state = CellState::Closed,
44 _ => (),
45 }
46 &self.state
47 }
48}
49
50#[cfg(test)]
51mod tests {
52 use super::*;
53
54 macro_rules! test_board_cell_trait {
55 ($func_name:ident, $state:expr, $func:ident, $expected:pat) => {
56 #[test]
57 fn $func_name() {
58 let mut cell = Cell {
59 kind: CellKind::Free,
60 state: $state,
61 };
62 cell.$func();
63 assert!(matches!(cell.state, $expected));
64 }
65 };
66 }
67
68 test_board_cell_trait!(open_closed, CellState::Closed, open, CellState::Opened);
69 test_board_cell_trait!(open_flagged, CellState::Flagged, open, CellState::Flagged);
70 test_board_cell_trait!(open_opened, CellState::Opened, open, CellState::Opened);
71 test_board_cell_trait!(flag_closed, CellState::Closed, flag, CellState::Flagged);
72 test_board_cell_trait!(flag_flagged, CellState::Flagged, flag, CellState::Closed);
73 test_board_cell_trait!(flag_opened, CellState::Opened, flag, CellState::Opened);
74}