135 lines
3.6 KiB
Rust
135 lines
3.6 KiB
Rust
|
const GRID_LENGTH: u8 = 15;
|
||
|
const TRAY_LENGTH: u8 = 7;
|
||
|
const ALL_LETTERS_BONUS: u32 = 50;
|
||
|
|
||
|
#[derive(Debug)]
|
||
|
enum Letter {
|
||
|
FixedLetter{text: char, points: u32},
|
||
|
Blank(char)
|
||
|
}
|
||
|
|
||
|
#[derive(Debug)]
|
||
|
enum CellType {
|
||
|
Normal,
|
||
|
DoubleWord,
|
||
|
DoubleLetter,
|
||
|
TripleLetter,
|
||
|
TripleWord,
|
||
|
Start,
|
||
|
}
|
||
|
|
||
|
#[derive(Debug)]
|
||
|
struct Cell {
|
||
|
value: Option<Letter>,
|
||
|
cell_type: CellType,
|
||
|
}
|
||
|
|
||
|
#[derive(Debug)]
|
||
|
struct Board {
|
||
|
cells: Vec<Cell>,
|
||
|
}
|
||
|
|
||
|
|
||
|
impl Board {
|
||
|
fn new() -> Self {
|
||
|
let mut cells = Vec::new();
|
||
|
|
||
|
|
||
|
/// Since the board is symmetrical in both directions for the purposes of our logic we can keep our coordinates in one corner
|
||
|
///
|
||
|
/// # Arguments
|
||
|
///
|
||
|
/// * `x`: A coordinate
|
||
|
///
|
||
|
/// returns: u8 The coordinate mapped onto the lower-half
|
||
|
fn map_to_corner(x: u8) -> u8 {
|
||
|
return if x > GRID_LENGTH / 2 {
|
||
|
GRID_LENGTH - x - 1
|
||
|
} else {
|
||
|
x
|
||
|
}
|
||
|
}
|
||
|
|
||
|
for i in 0..GRID_LENGTH {
|
||
|
let i = map_to_corner(i);
|
||
|
for j in 0..GRID_LENGTH {
|
||
|
let j = map_to_corner(j);
|
||
|
|
||
|
let mut typee = CellType::Normal;
|
||
|
|
||
|
// double word scores are diagonals
|
||
|
if i == j {
|
||
|
typee = CellType::DoubleWord;
|
||
|
}
|
||
|
|
||
|
// Triple letters
|
||
|
if (i % 4 == 1) && j % 4 == 1 && !(i == 1 && j == 1) {
|
||
|
typee = CellType::TripleLetter;
|
||
|
}
|
||
|
|
||
|
// Double letters
|
||
|
if (i % 4 == 2) && (j % 4 == 2) && !(
|
||
|
i == 2 && j == 2
|
||
|
) {
|
||
|
typee = CellType::DoubleLetter;
|
||
|
}
|
||
|
if (i.min(j) == 0 && i.max(j) == 3) || (i.min(j)==3 && i.max(j) == 7) {
|
||
|
typee = CellType::DoubleLetter;
|
||
|
}
|
||
|
|
||
|
// Triple word scores
|
||
|
if (i % 7 == 0) && (j % 7 == 0) {
|
||
|
typee = CellType::TripleWord;
|
||
|
}
|
||
|
|
||
|
// Start
|
||
|
if i == 7 && j == 7 {
|
||
|
typee = CellType::Start;
|
||
|
}
|
||
|
|
||
|
cells.push(Cell {
|
||
|
cell_type: typee,
|
||
|
value: None,
|
||
|
})
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
Board {cells}
|
||
|
}
|
||
|
|
||
|
fn get_cell(&self, x: u8, y: u8) -> Result<&Cell, &str> {
|
||
|
if x >= GRID_LENGTH || y >= GRID_LENGTH {
|
||
|
Err("x & y must be within the board's coordinates")
|
||
|
} else {
|
||
|
let coord = (x + GRID_LENGTH*y) as usize;
|
||
|
Ok(self.cells.get(coord).unwrap())
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
#[cfg(test)]
|
||
|
mod tests {
|
||
|
use super::*;
|
||
|
|
||
|
#[test]
|
||
|
fn test_cell_types() {
|
||
|
let board = Board::new();
|
||
|
|
||
|
assert!(matches!(board.get_cell(0, 0).unwrap().cell_type, CellType::TripleWord));
|
||
|
assert!(matches!(board.get_cell(1, 0).unwrap().cell_type, CellType::Normal));
|
||
|
assert!(matches!(board.get_cell(0, 1).unwrap().cell_type, CellType::Normal));
|
||
|
assert!(matches!(board.get_cell(1, 1).unwrap().cell_type, CellType::DoubleWord));
|
||
|
|
||
|
assert!(matches!(board.get_cell(13, 13).unwrap().cell_type, CellType::DoubleWord));
|
||
|
assert!(matches!(board.get_cell(14, 14).unwrap().cell_type, CellType::TripleWord));
|
||
|
assert!(matches!(board.get_cell(11, 14).unwrap().cell_type, CellType::DoubleLetter));
|
||
|
|
||
|
assert!(matches!(board.get_cell(7, 7).unwrap().cell_type, CellType::Start));
|
||
|
assert!(matches!(board.get_cell(8, 6).unwrap().cell_type, CellType::DoubleLetter));
|
||
|
assert!(matches!(board.get_cell(5, 9).unwrap().cell_type, CellType::TripleLetter));
|
||
|
}
|
||
|
}
|