Skip to content

Commit f3953c7

Browse files
committed
add Board struct
1 parent 0e3d6ed commit f3953c7

File tree

1 file changed

+96
-95
lines changed

1 file changed

+96
-95
lines changed

src/lib.rs

+96-95
Original file line numberDiff line numberDiff line change
@@ -6,33 +6,50 @@ enum Turn {
66
White,
77
}
88

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],
1411
}
1512

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+
}
2233
}
34+
return board;
2335
}
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');
3243
}
33-
as_str.push('\n');
44+
return as_str;
3445
}
35-
return as_str;
46+
}
47+
48+
#[wasm_bindgen]
49+
struct Checkers {
50+
turn: Turn,
51+
board: Board,
52+
in_step: Option<(i8, i8)>,
3653
}
3754

3855
#[wasm_bindgen]
@@ -57,19 +74,19 @@ impl Checkers {
5774
fn from(s: Vec<&str>, t: Turn) -> Checkers {
5875
let ch = Checkers {
5976
turn: t,
60-
board: make_board(s),
77+
board: Board::from_strings(s),
6178
in_step: None,
6279
};
6380

6481
return ch;
6582
}
6683

6784
#[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) {
7087
return '?';
7188
}
72-
return self.board[i as usize][j as usize];
89+
return self.board.get(i, j);
7390
}
7491

7592
#[wasm_bindgen]
@@ -80,46 +97,38 @@ impl Checkers {
8097
};
8198
}
8299

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) {
85102
return false;
86103
}
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',
92108
};
93109
}
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) {
96112
return false;
97113
}
98-
let i = i as usize;
99-
let j = j as usize;
100-
return vboard[i][j] == '.';
114+
return self.board.get(i, j) == '.';
101115
}
102116

103117
#[wasm_bindgen]
104118
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);
106120
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);
111125
if s.capture.is_some() {
112126
let jump_i = s.capture.unwrap().0;
113127
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, '.');
121130
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 {
123132
// No further jumps are possible. Switch turn.
124133
self.in_step = None;
125134
self.turn = match self.turn {
@@ -138,12 +147,12 @@ impl Checkers {
138147
match piece {
139148
'w' => {
140149
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');
142151
}
143152
}
144153
'b' => {
145154
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');
147156
}
148157
}
149158
_ => {}
@@ -152,7 +161,7 @@ impl Checkers {
152161

153162
// Return all steps for a position.
154163
#[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> {
156165
// Check if any piece can capture.
157166
let mut other_has_capture = false;
158167
'outer: for oi in 0..8 {
@@ -178,8 +187,8 @@ impl Checkers {
178187
}
179188

180189
// 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);
183192

184193
// Ensure piece matches turn.
185194
match self.turn {
@@ -197,7 +206,7 @@ impl Checkers {
197206

198207
match self.in_step {
199208
Some(in_step) => {
200-
if in_step != (i as u8, j as u8) {
209+
if in_step != (i, j) {
201210
// If in a jump sequence, only the piece that made the jump can make the next step.
202211
return vec![];
203212
}
@@ -206,16 +215,14 @@ impl Checkers {
206215
}
207216

208217
let mut steps = Vec::<Step>::new();
209-
let i: isize = i as isize;
210-
let j: isize = j as isize;
211218

212219
if self.in_step.is_none() {
213220
// 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) {
216223
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),
219226
capture: None,
220227
});
221228
}
@@ -243,22 +250,16 @@ impl Checkers {
243250
}
244251
}
245252

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+
};
262263

263264
match piece {
264265
'b' => {
@@ -304,36 +305,36 @@ impl Checkers {
304305
#[wasm_bindgen]
305306
#[derive(Debug, PartialEq, Clone, Copy)]
306307
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)>,
310311
}
311312

312313
#[wasm_bindgen]
313314
impl Step {
314315
#[wasm_bindgen(getter)]
315-
pub fn src_i(&self) -> u8 {
316+
pub fn src_i(&self) -> i8 {
316317
return self.src.0;
317318
}
318319
#[wasm_bindgen(getter)]
319-
pub fn src_j(&self) -> u8 {
320+
pub fn src_j(&self) -> i8 {
320321
return self.src.1;
321322
}
322323
#[wasm_bindgen(getter)]
323-
pub fn dst_i(&self) -> u8 {
324+
pub fn dst_i(&self) -> i8 {
324325
return self.dst.0;
325326
}
326327
#[wasm_bindgen(getter)]
327-
pub fn dst_j(&self) -> u8 {
328+
pub fn dst_j(&self) -> i8 {
328329
return self.dst.1;
329330
}
330331
}
331332

332333
impl std::fmt::Display for Checkers {
333334
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))?;
337338
}
338339
write!(f, "\n")?;
339340
}
@@ -347,16 +348,16 @@ mod tests {
347348

348349
macro_rules! assert_boardequal {
349350
($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();
352353
assert_eq!(a_str, b_str, "\n{}!=\n{}", a_str, b_str);
353354
};
354355
}
355356

356357
#[test]
357358
fn can_display_board() {
358359
let c = Checkers::new();
359-
let expect = make_board(vec![
360+
let expect = Board::from_strings(vec![
360361
".w.w.w.w", //
361362
"w.w.w.w.", //
362363
".w.w.w.w", //
@@ -515,7 +516,7 @@ mod tests {
515516
capture: None,
516517
});
517518

518-
let expect = make_board(vec![
519+
let expect = Board::from_strings(vec![
519520
"..", //
520521
"w.", //
521522
]);
@@ -540,7 +541,7 @@ mod tests {
540541
capture: Some((1, 2)),
541542
});
542543

543-
let expect = make_board(vec![
544+
let expect = Board::from_strings(vec![
544545
"....", //
545546
"....", //
546547
"...w", //
@@ -592,7 +593,7 @@ mod tests {
592593
capture: Some((1, 2)),
593594
});
594595

595-
let expect = make_board(vec![
596+
let expect = Board::from_strings(vec![
596597
"....", //
597598
"....", //
598599
"...w", //
@@ -620,7 +621,7 @@ mod tests {
620621
capture: None,
621622
});
622623

623-
let expect = make_board(vec![
624+
let expect = Board::from_strings(vec![
624625
".B", //
625626
"..", //
626627
]);

0 commit comments

Comments
 (0)