slowly working

This commit is contained in:
nora 2022-10-31 15:45:56 +01:00
parent b666c4a0cb
commit 43d39fba30
No known key found for this signature in database
7 changed files with 227 additions and 34 deletions

View file

@ -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,
};