#[cfg(test)]
mod tests;
pub const SQUARE_SIZE: usize = 3;
pub const BOARD_SIZE: usize = SQUARE_SIZE * SQUARE_SIZE;
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub struct Board {
cells: [[u16; BOARD_SIZE]; BOARD_SIZE],
}
impl Board {
#[inline]
pub fn get_cell(&self, x: usize, y: usize) -> u8 {
self.get_cell_as_mask(x, y).trailing_zeros() as u8
}
#[doc(hidden)]
#[inline]
pub(crate) fn get_cell_as_mask(&self, x: usize, y: usize) -> u16 {
self.cells[y][x]
}
#[doc(hidden)]
#[inline]
pub(crate) fn set_cell_as_mask(&mut self, x: usize, y: usize, value: u16) {
self.cells[y][x] = value;
}
#[inline]
pub fn set_cell(&mut self, x: usize, y: usize, value: u8) {
self.set_cell_as_mask(x, y, 1 << value);
}
}
impl From<&[[u8; BOARD_SIZE]; BOARD_SIZE]> for Board {
fn from(array_2d: &[[u8; BOARD_SIZE]; BOARD_SIZE]) -> Self {
let mut board = Board::default();
for (y, row) in array_2d.iter().enumerate() {
for (x, item) in row.iter().enumerate() {
board.set_cell(x, y, *item);
}
}
board
}
}
impl Default for Board {
fn default() -> Self {
Board {
cells: [[0b00_0000_0001; BOARD_SIZE]; BOARD_SIZE],
}
}
}
impl std::fmt::Display for Board {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut s = String::new();
for y in 0..BOARD_SIZE {
if y != 0 {
s.push('\n');
}
for x in 0..BOARD_SIZE {
if x != 0 {
s.push(' ');
}
let v = self.get_cell(x, y);
s.push(if v != 0 {
char::from_digit(v as u32, 10).unwrap()
} else {
'-'
});
}
}
write!(f, "{}", s)
}
}