rust_gomoku/
lib.rs

1mod utils;
2
3use wasm_bindgen::prelude::*;
4use std::cmp::{max};
5
6#[cfg(feature = "wee_alloc")]
7#[global_allocator]
8static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;
9
10#[wasm_bindgen]
11#[repr(u8)]
12#[derive(Clone, Copy, Debug, PartialEq, Eq)]
13pub enum Cell {
14    None = 0,
15    Black = 1,
16    White = 2,
17}
18
19#[wasm_bindgen]
20#[repr(u8)]
21#[derive(Clone, Copy, Debug, PartialEq, Eq)]
22pub enum Direction {
23    Horizontal = 0,
24    Vertical = 1,
25    Diagonal = 2,
26}
27
28
29#[wasm_bindgen]
30pub struct Universe {
31    width: u32,
32    height: u32,
33    turn: u32,
34    cells: Vec<Cell>,
35}
36
37#[wasm_bindgen]
38impl Universe {
39
40    fn next_turn(&mut self){
41        self.turn = self.turn.clone() + 1;
42    }
43
44    pub fn toggle(&mut self, row: u32, col: u32) {
45        
46        let turn = if self.turn % 2 == 0 { Cell::Black } else { Cell::White };
47
48        self.set_cell(row, col, turn);
49        
50        self.next_turn();
51
52    }
53
54    fn get_index(&self, row: u32, column: u32) -> usize {
55        (row * self.width + column) as usize
56    }
57
58    fn direction_count(&self, color: Cell, direction: Direction ,row: u32, column: u32) -> u32 {
59        
60        if row <=14 && column <= 14 && color != Cell::None{
61            let mut count = 1;
62
63            let cells = self.get_cells();
64
65            if cells[self.get_index(row, column)] == color {
66                match direction {
67                    Direction::Horizontal => count += self.direction_count(color,direction,row,column+1),
68                    Direction::Vertical => count += self.direction_count(color,direction,row+1,column),
69                    Direction::Diagonal => count += max(self.direction_count(color,direction,row+1,column+1),self.direction_count(color,direction,row+1,column-1)),
70                }
71                count
72            }else{
73                0
74            }
75        }else{
76            0
77        }
78    }
79
80    pub fn is_win(&mut self) -> Cell{
81        
82        for row in 0..self.height{
83            for col in 0..self.width {
84                
85                let idx = self.get_index(row, col);
86                let cell = self.cells[idx];
87
88                if self.direction_count(cell, Direction::Horizontal, row, col) == 5 || 
89                   self.direction_count(cell, Direction::Vertical, row, col) == 5 || 
90                   self.direction_count(cell, Direction::Diagonal, row, col) == 5 
91                {
92                    return cell;
93                }
94            }
95        }
96
97        Cell::None
98    }
99
100    pub fn new() -> Universe {
101        let width = 15;
102        let height = 15;
103        let turn = 0;
104
105        let cells = (0..width * height)
106            .map(|_i| {
107                Cell::None
108            })
109            .collect();
110
111        Universe {
112            width,
113            height,
114            turn,
115            cells,
116        }
117    }
118
119    fn get_cells(&self) -> &[Cell] {
120        &self.cells
121    }
122
123    pub fn set_cell(&mut self, row: u32, column: u32, cell: Cell) {
124        
125        if row <=14 && column <= 14 {
126            let index = self.get_index(row, column);
127            self.cells[index] = cell;
128        }
129        
130    }
131    pub fn width(&self) -> u32 {
132        self.width
133    }
134
135    pub fn height(&self) -> u32 {
136        self.height
137    }
138
139    pub fn cells(&self) -> *const Cell {
140        self.cells.as_ptr()
141    }
142
143    pub fn is_non(&self, row: u32, col: u32) -> bool {
144        let index = self.get_index(row, col);
145        self.cells[index] == Cell::None
146    }
147
148}
149
150#[cfg(test)]
151mod tests {
152
153    use super::*;
154
155    #[test]
156    fn universe_get_index() {
157        
158        let sut = Universe::new();
159        
160        assert_eq!(0,sut.get_index(0,0));
161        assert_eq!(35,sut.get_index(2,5));
162        assert_eq!(209,sut.get_index(13,14));
163
164    }
165
166    #[test]
167    fn universe_get_cell(){
168
169        let sut = Universe::new();
170
171        let cells = sut.get_cells();
172
173        let index = sut.get_index(10,10);
174
175        assert_eq!(Cell::None, cells[index]);
176
177    }
178
179    #[test]
180    fn univsese_set_cell(){
181
182        let mut sut = Universe::new();
183
184        sut.set_cell(10,10,Cell::White);
185
186        let cells = sut.get_cells();
187
188        assert_eq!(Cell::White, cells[sut.get_index(10,10)]);
189
190    }
191
192    #[test]
193    fn universe_direction_count_horizontal(){
194
195        let mut sut = Universe::new();
196
197        sut.set_cell(10,5,Cell::Black);
198        sut.set_cell(10,6,Cell::Black);
199        sut.set_cell(10,7,Cell::Black);
200
201        assert_eq!(0,sut.direction_count(Cell::White, Direction::Horizontal , 10, 5));
202        assert_eq!(3,sut.direction_count(Cell::Black, Direction::Horizontal , 10, 5));
203        
204    }
205
206    #[test]
207    fn universe_direction_count_out_of_bound(){
208
209        let mut sut = Universe::new();
210
211        sut.set_cell(14,14,Cell::Black);
212        
213        assert_eq!(1,sut.direction_count(Cell::Black, Direction::Horizontal , 14, 14));
214    }
215
216
217    #[test]
218    fn universe_direction_count_vertical(){
219
220        let mut sut = Universe::new();
221
222        sut.set_cell(9,5,Cell::Black);
223        sut.set_cell(10,5,Cell::Black);
224        sut.set_cell(11,5,Cell::Black);
225        sut.set_cell(12,5,Cell::Black);
226        sut.set_cell(13,5,Cell::Black);
227        
228
229        assert_eq!(5,sut.direction_count(Cell::Black, Direction::Vertical , 9, 5));
230
231    }
232
233    #[test]
234    fn universe_direction_count_diagonal(){
235
236        let mut sut = Universe::new();
237
238        sut.set_cell(5,5,Cell::Black);
239        sut.set_cell(6,6,Cell::Black);
240        sut.set_cell(7,7,Cell::Black);
241        sut.set_cell(8,8,Cell::Black);
242        sut.set_cell(9,9,Cell::Black);
243
244        assert_eq!(5,sut.direction_count(Cell::Black, Direction::Diagonal , 5, 5));
245
246    }
247
248    #[test]
249    fn universe_direction_count_not_none(){
250
251        let sut = Universe::new();
252
253        assert_eq!(0,sut.direction_count(Cell::None, Direction::Diagonal , 5, 5));
254
255    }
256
257    #[test]
258    fn universe_not_win(){
259
260        let mut sut = Universe::new();
261
262        assert_eq!(Cell::None, sut.is_win());
263    }
264
265    #[test]
266    fn universe_black_win(){
267
268        let mut sut = Universe::new();
269
270        sut.set_cell(5,5,Cell::Black);
271        sut.set_cell(6,6,Cell::Black);
272        sut.set_cell(7,7,Cell::Black);
273        sut.set_cell(8,8,Cell::Black);
274        sut.set_cell(9,9,Cell::Black);
275        
276        assert_eq!(Cell::Black, sut.is_win());
277        
278    }
279
280    #[test]
281    fn universe_white_win(){
282
283        let mut sut = Universe::new();
284
285        sut.set_cell(5,5,Cell::White);
286        sut.set_cell(5,6,Cell::White);
287        sut.set_cell(5,7,Cell::White);
288        sut.set_cell(5,8,Cell::White);
289        sut.set_cell(5,9,Cell::White);
290        
291        assert_eq!(Cell::White, sut.is_win());
292
293    }    
294
295    #[test]
296    fn universe_toggle_cell(){
297
298        let mut sut = Universe::new();
299
300        sut.toggle(4, 4);
301        sut.toggle(8, 5);
302        sut.toggle(1, 7);
303        sut.toggle(4, 2);
304        sut.toggle(10, 4);
305        
306        
307        let cells = sut.get_cells();
308
309        assert_eq!(Cell::Black, cells[sut.get_index(4, 4)]);
310        assert_eq!(Cell::White, cells[sut.get_index(8, 5)]);
311        assert_eq!(Cell::Black, cells[sut.get_index(1, 7)]);
312        assert_eq!(Cell::White, cells[sut.get_index(4, 2)]);
313        assert_eq!(Cell::Black, cells[sut.get_index(10, 4)]);
314        
315    }
316
317    #[test]
318    fn universe_not_none_cell(){
319
320        let sut = Universe::new();
321
322        assert_eq!(true,sut.is_non(10,10));
323
324    }
325
326}