mirror of
https://github.com/Noratrieb/minmax.git
synced 2026-01-14 23:35:04 +01:00
slowly working
This commit is contained in:
parent
b666c4a0cb
commit
43d39fba30
7 changed files with 227 additions and 34 deletions
66
build.rs
66
build.rs
|
|
@ -1,11 +1,18 @@
|
|||
use std::{fs::File, io::Write, path::PathBuf};
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
enum Player {
|
||||
X,
|
||||
O,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
enum State {
|
||||
Winner(Player),
|
||||
InProgress,
|
||||
Draw,
|
||||
}
|
||||
|
||||
impl Player {
|
||||
fn from_u8(num: u8) -> Option<Self> {
|
||||
match num {
|
||||
|
|
@ -15,14 +22,6 @@ impl Player {
|
|||
_ => panic!("Invalid value {num}"),
|
||||
}
|
||||
}
|
||||
|
||||
fn as_u8(this: Option<Player>) -> u8 {
|
||||
match this {
|
||||
Some(Player::X) => 0,
|
||||
Some(Player::O) => 1,
|
||||
None => 2,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
|
|
@ -42,16 +41,42 @@ impl Board {
|
|||
Some(Self(num))
|
||||
}
|
||||
|
||||
fn get(&self, index: usize) -> Option<Player> {
|
||||
fn validate(&self) {
|
||||
let board = self.0;
|
||||
for i in 0..16 {
|
||||
let next_step = board >> (i * 2);
|
||||
let mask = 0b11;
|
||||
let pos = next_step & mask;
|
||||
if pos >= 3 {
|
||||
panic!("Invalid bits, self: {board:0X}, bits: {pos:0X}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get(&self, index: usize) -> Option<Player> {
|
||||
self.validate();
|
||||
debug_assert!(index < 9);
|
||||
|
||||
let shifted = self.0 >> (index * 2);
|
||||
let board = self.0;
|
||||
|
||||
let shifted = board >> (index * 2);
|
||||
let masked = shifted & 0b11;
|
||||
|
||||
Player::from_u8(masked as u8)
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> impl Iterator<Item = Option<Player>> {
|
||||
let mut i = 0;
|
||||
let this = self.clone();
|
||||
std::iter::from_fn(move || {
|
||||
let result = (i < 8).then(|| this.get(i));
|
||||
i += 1;
|
||||
result
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn winner(board: Board) -> Option<Player> {
|
||||
fn result(board: Board) -> State {
|
||||
fn won_row(a: Option<Player>, b: Option<Player>, c: Option<Player>) -> Option<Player> {
|
||||
if a == Some(Player::X) && b == Some(Player::X) && c == Some(Player::X) {
|
||||
Some(Player::X)
|
||||
|
|
@ -65,12 +90,16 @@ fn winner(board: Board) -> Option<Player> {
|
|||
macro_rules! test_row {
|
||||
($a:literal, $b:literal, $c:literal) => {
|
||||
match won_row(board.get($a), board.get($b), board.get($c)) {
|
||||
Some(player) => return Some(player),
|
||||
Some(player) => return State::Winner(player),
|
||||
None => {}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
if board.iter().all(|x| x.is_some()) {
|
||||
return State::Draw;
|
||||
}
|
||||
|
||||
test_row!(0, 1, 2);
|
||||
test_row!(3, 4, 5);
|
||||
test_row!(6, 7, 8);
|
||||
|
|
@ -81,15 +110,20 @@ fn winner(board: Board) -> Option<Player> {
|
|||
|
||||
test_row!(0, 4, 8);
|
||||
test_row!(2, 4, 6);
|
||||
None
|
||||
State::InProgress
|
||||
}
|
||||
|
||||
fn calculate_win_table(file: &mut impl Write) {
|
||||
for board in 0..(2u32.pow(18)) {
|
||||
let byte = match Board::new(board) {
|
||||
Some(board) => {
|
||||
let winner = winner(board);
|
||||
Player::as_u8(winner)
|
||||
let winner = result(board);
|
||||
match winner {
|
||||
State::Winner(Player::X) => 0,
|
||||
State::Winner(Player::O) => 1,
|
||||
State::InProgress => 2,
|
||||
State::Draw => 3,
|
||||
}
|
||||
}
|
||||
None => 0,
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue