@@ -6,33 +6,50 @@ enum Turn {
6
6
White ,
7
7
}
8
8
9
- #[ wasm_bindgen]
10
- struct Checkers {
11
- turn : Turn ,
12
- board : [ [ char ; 8 ] ; 8 ] ,
13
- in_step : Option < ( u8 , u8 ) > ,
9
+ struct Board {
10
+ data : [ [ char ; 8 ] ; 8 ] ,
14
11
}
15
12
16
- fn make_board ( s : Vec < & str > ) -> [ [ char ; 8 ] ; 8 ] {
17
- let mut board = [ [ '.' ; 8 ] ; 8 ] ;
18
-
19
- for i in 0 ..s. len ( ) {
20
- for j in 0 ..s[ i] . len ( ) {
21
- board[ i] [ j] = s[ i] . chars ( ) . nth ( j) . unwrap ( ) ;
13
+ impl Board {
14
+ fn get ( & self , i : i8 , j : i8 ) -> char {
15
+ assert ! ( Self :: contains( i, j) ) ;
16
+ return self . data [ i as usize ] [ j as usize ] ;
17
+ }
18
+ fn set ( & mut self , i : i8 , j : i8 , v : char ) {
19
+ assert ! ( Self :: contains( i, j) ) ;
20
+ self . data [ i as usize ] [ j as usize ] = v;
21
+ }
22
+ fn contains ( i : i8 , j : i8 ) -> bool {
23
+ return i >= 0 && i <= 7 && j >= 0 && j <= 7 ;
24
+ }
25
+ fn from_strings ( s : Vec < & str > ) -> Board {
26
+ let mut board = Board {
27
+ data : [ [ '.' ; 8 ] ; 8 ] ,
28
+ } ;
29
+ for i in 0 ..s. len ( ) {
30
+ for j in 0 ..s[ i] . len ( ) {
31
+ board. data [ i] [ j] = s[ i] . chars ( ) . nth ( j) . unwrap ( ) ;
32
+ }
22
33
}
34
+ return board;
23
35
}
24
- return board;
25
- }
26
-
27
- fn board_to_string ( b : & [ [ char ; 8 ] ; 8 ] ) -> String {
28
- let mut as_str = String :: new ( ) ;
29
- for row in b {
30
- for square in row {
31
- as_str. push ( * square) ;
36
+ fn to_string ( & self ) -> String {
37
+ let mut as_str = String :: new ( ) ;
38
+ for row in self . data {
39
+ for square in row {
40
+ as_str. push ( square) ;
41
+ }
42
+ as_str. push ( '\n' ) ;
32
43
}
33
- as_str. push ( '\n' ) ;
44
+ return as_str;
34
45
}
35
- return as_str;
46
+ }
47
+
48
+ #[ wasm_bindgen]
49
+ struct Checkers {
50
+ turn : Turn ,
51
+ board : Board ,
52
+ in_step : Option < ( i8 , i8 ) > ,
36
53
}
37
54
38
55
#[ wasm_bindgen]
@@ -57,19 +74,19 @@ impl Checkers {
57
74
fn from ( s : Vec < & str > , t : Turn ) -> Checkers {
58
75
let ch = Checkers {
59
76
turn : t,
60
- board : make_board ( s) ,
77
+ board : Board :: from_strings ( s) ,
61
78
in_step : None ,
62
79
} ;
63
80
64
81
return ch;
65
82
}
66
83
67
84
#[ wasm_bindgen]
68
- pub fn at ( & self , i : isize , j : isize ) -> char {
69
- if i < 0 || j < 0 || i > 7 || j > 7 {
85
+ pub fn at ( & self , i : i8 , j : i8 ) -> char {
86
+ if ! Board :: contains ( i , j ) {
70
87
return '?' ;
71
88
}
72
- return self . board [ i as usize ] [ j as usize ] ;
89
+ return self . board . get ( i , j ) ;
73
90
}
74
91
75
92
#[ wasm_bindgen]
@@ -80,46 +97,38 @@ impl Checkers {
80
97
} ;
81
98
}
82
99
83
- fn is_opponent ( turn : Turn , vboard : & [ [ char ; 8 ] ; 8 ] , i : isize , j : isize ) -> bool {
84
- if i < 0 || j < 0 || i > 7 || j > 7 {
100
+ fn is_opponent ( & self , i : i8 , j : i8 ) -> bool {
101
+ if ! Board :: contains ( i , j ) {
85
102
return false ;
86
103
}
87
- let i = i as usize ;
88
- let j = j as usize ;
89
- return match turn {
90
- Turn :: Black => vboard[ i] [ j] == 'w' || vboard[ i] [ j] == 'W' ,
91
- Turn :: White => vboard[ i] [ j] == 'b' || vboard[ i] [ j] == 'B' ,
104
+ let square = self . board . get ( i, j) ;
105
+ return match self . turn {
106
+ Turn :: Black => square == 'w' || square == 'W' ,
107
+ Turn :: White => square == 'b' || square == 'B' ,
92
108
} ;
93
109
}
94
- fn is_empty ( vboard : & [ [ char ; 8 ] ; 8 ] , i : isize , j : isize ) -> bool {
95
- if i < 0 || j < 0 || i > 7 || j > 7 {
110
+ fn is_empty ( & self , i : i8 , j : i8 ) -> bool {
111
+ if ! Board :: contains ( i , j ) {
96
112
return false ;
97
113
}
98
- let i = i as usize ;
99
- let j = j as usize ;
100
- return vboard[ i] [ j] == '.' ;
114
+ return self . board . get ( i, j) == '.' ;
101
115
}
102
116
103
117
#[ wasm_bindgen]
104
118
pub fn make_step ( & mut self , s : Step ) {
105
- let steps = self . get_steps ( s. src . 0 as usize , s. src . 1 as usize ) ;
119
+ let steps = self . get_steps ( s. src . 0 , s. src . 1 ) ;
106
120
assert ! ( steps. contains( & s) ) ;
107
- let piece = self . board [ s. src . 0 as usize ] [ s. src . 1 as usize ] ;
108
- self . board [ s. src . 0 as usize ] [ s. src . 1 as usize ] = '.' ;
109
- assert_eq ! ( self . board[ s. dst. 0 as usize ] [ s. dst. 1 as usize ] , '.' ) ;
110
- self . board [ s. dst . 0 as usize ] [ s. dst . 1 as usize ] = piece;
121
+ let piece = self . board . get ( s. src . 0 , s. src . 1 ) ;
122
+ self . board . set ( s. src . 0 , s. src . 1 , '.' ) ;
123
+ assert_eq ! ( self . board. get ( s. dst. 0 , s. dst. 1 ) , '.' ) ;
124
+ self . board . set ( s. dst . 0 , s. dst . 1 , piece) ;
111
125
if s. capture . is_some ( ) {
112
126
let jump_i = s. capture . unwrap ( ) . 0 ;
113
127
let jump_j = s. capture . unwrap ( ) . 1 ;
114
- assert ! ( Self :: is_opponent(
115
- self . turn,
116
- & self . board,
117
- jump_i as isize ,
118
- jump_j as isize
119
- ) ) ;
120
- self . board [ jump_i as usize ] [ jump_j as usize ] = '.' ;
128
+ assert ! ( self . is_opponent( jump_i, jump_j) ) ;
129
+ self . board . set ( jump_i, jump_j, '.' ) ;
121
130
self . in_step = Some ( ( s. dst . 0 , s. dst . 1 ) ) ;
122
- if self . get_steps ( s. dst . 0 as usize , s. dst . 1 as usize ) . len ( ) == 0 {
131
+ if self . get_steps ( s. dst . 0 , s. dst . 1 ) . len ( ) == 0 {
123
132
// No further jumps are possible. Switch turn.
124
133
self . in_step = None ;
125
134
self . turn = match self . turn {
@@ -138,12 +147,12 @@ impl Checkers {
138
147
match piece {
139
148
'w' => {
140
149
if s. dst . 0 == 7 {
141
- self . board [ s. dst . 0 as usize ] [ s. dst . 1 as usize ] = 'W' ;
150
+ self . board . set ( s. dst . 0 , s. dst . 1 , 'W' ) ;
142
151
}
143
152
}
144
153
'b' => {
145
154
if s. dst . 0 == 0 {
146
- self . board [ s. dst . 0 as usize ] [ s. dst . 1 as usize ] = 'B' ;
155
+ self . board . set ( s. dst . 0 , s. dst . 1 , 'B' ) ;
147
156
}
148
157
}
149
158
_ => { }
@@ -152,7 +161,7 @@ impl Checkers {
152
161
153
162
// Return all steps for a position.
154
163
#[ wasm_bindgen]
155
- pub fn get_steps ( & self , i : usize , j : usize ) -> Vec < Step > {
164
+ pub fn get_steps ( & self , i : i8 , j : i8 ) -> Vec < Step > {
156
165
// Check if any piece can capture.
157
166
let mut other_has_capture = false ;
158
167
' outer: for oi in 0 ..8 {
@@ -178,8 +187,8 @@ impl Checkers {
178
187
}
179
188
180
189
// Does not account other pieces capturing.
181
- fn get_steps_local ( & self , i : usize , j : usize ) -> Vec < Step > {
182
- let piece = self . board [ i ] [ j ] ;
190
+ fn get_steps_local ( & self , i : i8 , j : i8 ) -> Vec < Step > {
191
+ let piece = self . board . get ( i , j ) ;
183
192
184
193
// Ensure piece matches turn.
185
194
match self . turn {
@@ -197,7 +206,7 @@ impl Checkers {
197
206
198
207
match self . in_step {
199
208
Some ( in_step) => {
200
- if in_step != ( i as u8 , j as u8 ) {
209
+ if in_step != ( i, j) {
201
210
// If in a jump sequence, only the piece that made the jump can make the next step.
202
211
return vec ! [ ] ;
203
212
}
@@ -206,16 +215,14 @@ impl Checkers {
206
215
}
207
216
208
217
let mut steps = Vec :: < Step > :: new ( ) ;
209
- let i: isize = i as isize ;
210
- let j: isize = j as isize ;
211
218
212
219
if self . in_step . is_none ( ) {
213
220
// Check for ordinary move.
214
- let mut maybe_step = |src_i : isize , src_j : isize , dst_i : isize , dst_j : isize | {
215
- if Self :: is_empty ( & self . board , dst_i, dst_j) {
221
+ let mut maybe_step = |src_i : i8 , src_j : i8 , dst_i : i8 , dst_j : i8 | {
222
+ if self . is_empty ( dst_i, dst_j) {
216
223
steps. push ( Step {
217
- src : ( src_i as u8 , src_j as u8 ) ,
218
- dst : ( dst_i as u8 , dst_j as u8 ) ,
224
+ src : ( src_i, src_j) ,
225
+ dst : ( dst_i, dst_j) ,
219
226
capture : None ,
220
227
} ) ;
221
228
}
@@ -243,22 +250,16 @@ impl Checkers {
243
250
}
244
251
}
245
252
246
- let mut maybe_jump = |src_i : isize ,
247
- src_j : isize ,
248
- jump_i : isize ,
249
- jump_j : isize ,
250
- dst_i : isize ,
251
- dst_j : isize | {
252
- if Self :: is_opponent ( self . turn , & self . board , jump_i, jump_j)
253
- && Self :: is_empty ( & self . board , dst_i, dst_j)
254
- {
255
- steps. push ( Step {
256
- src : ( src_i as u8 , src_j as u8 ) ,
257
- dst : ( dst_i as u8 , dst_j as u8 ) ,
258
- capture : Some ( ( jump_i as u8 , jump_j as u8 ) ) ,
259
- } ) ;
260
- }
261
- } ;
253
+ let mut maybe_jump =
254
+ |src_i : i8 , src_j : i8 , jump_i : i8 , jump_j : i8 , dst_i : i8 , dst_j : i8 | {
255
+ if self . is_opponent ( jump_i, jump_j) && self . is_empty ( dst_i, dst_j) {
256
+ steps. push ( Step {
257
+ src : ( src_i, src_j) ,
258
+ dst : ( dst_i, dst_j) ,
259
+ capture : Some ( ( jump_i, jump_j) ) ,
260
+ } ) ;
261
+ }
262
+ } ;
262
263
263
264
match piece {
264
265
'b' => {
@@ -304,36 +305,36 @@ impl Checkers {
304
305
#[ wasm_bindgen]
305
306
#[ derive( Debug , PartialEq , Clone , Copy ) ]
306
307
struct Step {
307
- src : ( u8 , u8 ) ,
308
- dst : ( u8 , u8 ) ,
309
- capture : Option < ( u8 , u8 ) > ,
308
+ src : ( i8 , i8 ) ,
309
+ dst : ( i8 , i8 ) ,
310
+ capture : Option < ( i8 , i8 ) > ,
310
311
}
311
312
312
313
#[ wasm_bindgen]
313
314
impl Step {
314
315
#[ wasm_bindgen( getter) ]
315
- pub fn src_i ( & self ) -> u8 {
316
+ pub fn src_i ( & self ) -> i8 {
316
317
return self . src . 0 ;
317
318
}
318
319
#[ wasm_bindgen( getter) ]
319
- pub fn src_j ( & self ) -> u8 {
320
+ pub fn src_j ( & self ) -> i8 {
320
321
return self . src . 1 ;
321
322
}
322
323
#[ wasm_bindgen( getter) ]
323
- pub fn dst_i ( & self ) -> u8 {
324
+ pub fn dst_i ( & self ) -> i8 {
324
325
return self . dst . 0 ;
325
326
}
326
327
#[ wasm_bindgen( getter) ]
327
- pub fn dst_j ( & self ) -> u8 {
328
+ pub fn dst_j ( & self ) -> i8 {
328
329
return self . dst . 1 ;
329
330
}
330
331
}
331
332
332
333
impl std:: fmt:: Display for Checkers {
333
334
fn fmt ( & self , f : & mut std:: fmt:: Formatter ) -> std:: fmt:: Result {
334
- for i in 0 ..self . board . len ( ) {
335
- for j in 0 ..self . board [ i ] . len ( ) {
336
- write ! ( f, "{}" , self . board[ i ] [ j ] as char ) ?;
335
+ for i in 0 ..8 {
336
+ for j in 0 ..8 {
337
+ write ! ( f, "{}" , self . board. get ( i , j ) ) ?;
337
338
}
338
339
write ! ( f, "\n " ) ?;
339
340
}
@@ -347,16 +348,16 @@ mod tests {
347
348
348
349
macro_rules! assert_boardequal {
349
350
( $a: expr, $b: expr) => {
350
- let a_str = board_to_string ( $a ) ;
351
- let b_str = board_to_string ( $b ) ;
351
+ let a_str = $a . to_string ( ) ;
352
+ let b_str = $b . to_string ( ) ;
352
353
assert_eq!( a_str, b_str, "\n {}!=\n {}" , a_str, b_str) ;
353
354
} ;
354
355
}
355
356
356
357
#[ test]
357
358
fn can_display_board ( ) {
358
359
let c = Checkers :: new ( ) ;
359
- let expect = make_board ( vec ! [
360
+ let expect = Board :: from_strings ( vec ! [
360
361
".w.w.w.w" , //
361
362
"w.w.w.w." , //
362
363
".w.w.w.w" , //
@@ -515,7 +516,7 @@ mod tests {
515
516
capture : None ,
516
517
} ) ;
517
518
518
- let expect = make_board ( vec ! [
519
+ let expect = Board :: from_strings ( vec ! [
519
520
".." , //
520
521
"w." , //
521
522
] ) ;
@@ -540,7 +541,7 @@ mod tests {
540
541
capture : Some ( ( 1 , 2 ) ) ,
541
542
} ) ;
542
543
543
- let expect = make_board ( vec ! [
544
+ let expect = Board :: from_strings ( vec ! [
544
545
"...." , //
545
546
"...." , //
546
547
"...w" , //
@@ -592,7 +593,7 @@ mod tests {
592
593
capture : Some ( ( 1 , 2 ) ) ,
593
594
} ) ;
594
595
595
- let expect = make_board ( vec ! [
596
+ let expect = Board :: from_strings ( vec ! [
596
597
"...." , //
597
598
"...." , //
598
599
"...w" , //
@@ -620,7 +621,7 @@ mod tests {
620
621
capture : None ,
621
622
} ) ;
622
623
623
- let expect = make_board ( vec ! [
624
+ let expect = Board :: from_strings ( vec ! [
624
625
".B" , //
625
626
".." , //
626
627
] ) ;
0 commit comments