mirror of
https://github.com/Noratrieb/minmax.git
synced 2026-01-14 15:25:08 +01:00
board works
This commit is contained in:
parent
b4badd4290
commit
6c3bf8dddb
1 changed files with 100 additions and 7 deletions
|
|
@ -4,10 +4,14 @@ use crate::{Player, State};
|
|||
|
||||
type Position = Option<Player>;
|
||||
|
||||
const BOARD_WIDTH: usize = 7;
|
||||
const BOARD_HEIGHT: usize = 4;
|
||||
const BOARD_POSITIONS: usize = BOARD_WIDTH * BOARD_HEIGHT;
|
||||
const WIDTH: usize = 7;
|
||||
const HEIGTH: usize = 4;
|
||||
const BOARD_POSITIONS: usize = WIDTH * HEIGTH;
|
||||
|
||||
/// 0 1 2 3 4 5 6
|
||||
/// 7 8 9 10 11 12 13
|
||||
/// 14 15 16 17 18 19 20
|
||||
/// 21 22 23 24 25 26 27
|
||||
pub struct Board {
|
||||
positions: [Position; BOARD_POSITIONS],
|
||||
}
|
||||
|
|
@ -20,7 +24,14 @@ impl Board {
|
|||
}
|
||||
|
||||
pub fn result(&self) -> State {
|
||||
self.check_board()
|
||||
match self.check_board() {
|
||||
State::Winner(winner) => State::Winner(winner),
|
||||
State::InProgress if self.positions.iter().all(|position| position.is_some()) => {
|
||||
State::Draw
|
||||
}
|
||||
State::InProgress => State::InProgress,
|
||||
State::Draw => unreachable!("check_board cannot tell a draw"),
|
||||
}
|
||||
}
|
||||
|
||||
fn check_board(&self) -> State {
|
||||
|
|
@ -30,15 +41,15 @@ impl Board {
|
|||
}
|
||||
|
||||
fn check_columns(&self) -> State {
|
||||
for i in 0..BOARD_WIDTH {
|
||||
self.check_four(i, i + BOARD_WIDTH, i + 2 * BOARD_WIDTH, i + 3 * BOARD_WIDTH)?;
|
||||
for i in 0..WIDTH {
|
||||
self.check_four(i, i + WIDTH, i + 2 * WIDTH, i + 3 * WIDTH)?;
|
||||
}
|
||||
|
||||
State::InProgress
|
||||
}
|
||||
|
||||
fn check_rows(&self) -> State {
|
||||
for row_start in 0..BOARD_HEIGHT {
|
||||
for row_start in 0..HEIGTH {
|
||||
for offset in 0..4 {
|
||||
let start = row_start + offset;
|
||||
self.check_four(start, start + 1, start + 2, start + 3)?;
|
||||
|
|
@ -49,6 +60,17 @@ impl Board {
|
|||
}
|
||||
|
||||
fn check_diagonals(&self) -> State {
|
||||
// */*
|
||||
for start in 3..WIDTH {
|
||||
const DIFF: usize = WIDTH - 1;
|
||||
self.check_four(start, start + DIFF, start + 2 * DIFF, start + 3 * DIFF)?;
|
||||
}
|
||||
|
||||
// *\*
|
||||
for start in 0..4 {
|
||||
const DIFF: usize = WIDTH + 1;
|
||||
self.check_four(start, start + DIFF, start + 2 * DIFF, start + 3 * DIFF)?;
|
||||
}
|
||||
State::InProgress
|
||||
}
|
||||
|
||||
|
|
@ -73,3 +95,74 @@ impl Index<usize> for Board {
|
|||
&self.positions[index]
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{Player, State};
|
||||
|
||||
use super::Board;
|
||||
|
||||
fn parse_board(board: &str) -> Board {
|
||||
let positions = board
|
||||
.chars()
|
||||
.filter(|char| !char.is_whitespace())
|
||||
.map(|char| match char {
|
||||
'X' => Some(Player::X),
|
||||
'O' => Some(Player::O),
|
||||
'_' => None,
|
||||
char => panic!("Invalid char in board: `{char}`"),
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.try_into()
|
||||
.expect(&format!(
|
||||
"not enough positions provided: {}",
|
||||
board.chars().filter(|c| !c.is_whitespace()).count()
|
||||
));
|
||||
|
||||
Board { positions }
|
||||
}
|
||||
|
||||
fn test(board: &str, state: State) {
|
||||
let board = parse_board(board);
|
||||
assert_eq!(board.result(), state);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn draw() {
|
||||
test(
|
||||
"
|
||||
XOOOXOX
|
||||
XOOOXOX
|
||||
OXXXOXO
|
||||
XOOOXXX
|
||||
",
|
||||
State::Draw,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn full_winner() {
|
||||
test(
|
||||
"
|
||||
XOOOXOX
|
||||
XOOOXOX
|
||||
OXXXOXO
|
||||
XOOOXOX
|
||||
",
|
||||
State::Winner(Player::O),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn three_rows() {
|
||||
test(
|
||||
"
|
||||
XXX_OOO
|
||||
_XXX___
|
||||
X_OOO__
|
||||
OOO____
|
||||
",
|
||||
State::InProgress,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue