Add full word finding

This commit is contained in:
Joel Therrien 2023-07-28 21:53:01 -07:00
parent 4f5de6e52e
commit 5184c5b520

View file

@ -51,7 +51,7 @@ impl Coordinates {
}
}
#[derive(Debug)]
#[derive(Debug, Copy, Clone)]
pub struct Letter {
text: char,
points: u32,
@ -216,7 +216,7 @@ impl Board {
cells.push(Cell {
cell_type: typee,
value: None,
coordinates: Coordinates(i, j),
coordinates: Coordinates(j_orig, i_orig),
})
}
@ -243,7 +243,7 @@ impl Board {
}
}
pub fn score_move(&self) -> Result<u32, &str> {
fn find_played_words(&self) -> Result<Vec<Word>, &str> {
// We don't assume that the move is valid, so let's first establish that
@ -276,27 +276,44 @@ impl Board {
}
let direction = if rows_played.len() > 1 {
Direction::Column
} else {
Direction::Row
} else {
Direction::Column
};
let starting_row = *rows_played.iter().min().unwrap();
let starting_column = *columns_played.iter().min().unwrap();
let mut starting_coords = Coordinates(starting_row, starting_column);
let main_word = self.find_word_at_position(starting_coords, direction).unwrap();
starting_coords = main_word.coords;
let mut words = Vec::new();
// At this point we now know that we're at the start of the word and we have the direction.
// Now we'll head forward and look for every word that intersects one of the played tiles
todo!()
for cell in main_word.cells.as_slice() {
if cell.value.as_ref().unwrap().ephemeral {
let side_word = self.find_word_at_position(cell.coordinates, direction.invert());
match side_word {
None => {}
Some(side_word) => {
if side_word.cells.len() > 1 {
words.push(side_word);
}
}
}
}
}
fn find_word(&self, mut start_coords: Coordinates, direction: Direction) -> Option<Word> {
words.push(main_word);
Ok(words)
}
fn find_word_at_position(&self, mut start_coords: Coordinates, direction: Direction) -> Option<Word> {
// let's see how far we can backtrack to the start of the word
let mut times_moved = 0;
loop {
@ -421,7 +438,22 @@ mod tests {
}
#[test]
fn test_word_finding() {
fn test_cell_coordinates() {
let board = Board::new();
for x in 0..GRID_LENGTH {
for y in 0..GRID_LENGTH {
let cell = board.get_cell(Coordinates(x, y)).unwrap();
let coords = cell.coordinates;
assert_eq!(x, coords.0);
assert_eq!(y, coords.1);
}
}
}
#[test]
fn test_word_finding_at_position() {
let mut board = Board::new();
board.get_cell_mut(Coordinates(8, 6)).unwrap().value = Some(Letter::new_fixed('J', 0));
@ -452,7 +484,7 @@ mod tests {
for x in vec![6, 7, 8, 9] {
println!("x is {}", x);
let first_word = board.find_word(Coordinates(8, x), Direction::Column);
let first_word = board.find_word_at_position(Coordinates(8, x), Direction::Column);
match first_word {
None => {panic!("Expected to find word JOEL")}
Some(x) => {
@ -465,7 +497,7 @@ mod tests {
}
}
let single_letter_word = board.find_word(Coordinates(8, 9), Direction::Row);
let single_letter_word = board.find_word_at_position(Coordinates(8, 9), Direction::Row);
match single_letter_word {
None => {panic!("Expected to find letter L")}
Some(x) => {
@ -478,7 +510,7 @@ mod tests {
for x in vec![0, 1] {
println!("x is {}", x);
let word = board.find_word(Coordinates(x, 0), Direction::Row);
let word = board.find_word_at_position(Coordinates(x, 0), Direction::Row);
match word {
None => {panic!("Expected to find word IS")}
Some(x) => {
@ -493,7 +525,7 @@ mod tests {
for x in vec![3, 4, 5, 6] {
println!("x is {}", x);
let word = board.find_word(Coordinates(x, 0), Direction::Row);
let word = board.find_word_at_position(Coordinates(x, 0), Direction::Row);
match word {
None => {panic!("Expected to find word COOL")}
Some(x) => {
@ -506,10 +538,10 @@ mod tests {
}
}
let no_word = board.find_word(Coordinates(2, 0), Direction::Row);
let no_word = board.find_word_at_position(Coordinates(2, 0), Direction::Row);
assert!(no_word.is_none());
let word = board.find_word(Coordinates(10, 8), Direction::Row);
let word = board.find_word_at_position(Coordinates(10, 8), Direction::Row);
match word {
None => {panic!("Expected to find word EGG")}
Some(x) => {
@ -523,6 +555,137 @@ mod tests {
}
#[test]
fn test_word_finding_whole_board() {
let mut board = Board::new();
fn make_letter(x: char, ephemeral: bool) -> Letter {
Letter {
text: x,
points: 0,
ephemeral,
is_blank: false,
}
}
let words = board.find_played_words();
match words {
Ok(_) => {panic!("Expected to find no words")}
Err(x) => {assert_eq!(x, "Tiles need to be played")}
}
board.get_cell_mut(Coordinates(8, 6)).unwrap().value = Some(Letter::new_fixed('J', 0));
board.get_cell_mut(Coordinates(8, 7)).unwrap().value = Some(make_letter('O', true));
board.get_cell_mut(Coordinates(8, 8)).unwrap().value = Some(make_letter('E', true));
board.get_cell_mut(Coordinates(8, 9)).unwrap().value = Some(Letter::new_fixed( 'L', 0));
board.get_cell_mut(Coordinates(0, 0)).unwrap().value = Some(Letter::new_fixed('I', 0));
board.get_cell_mut(Coordinates(1, 0)).unwrap().value = Some(Letter::new_fixed('S', 0));
board.get_cell_mut(Coordinates(3, 0)).unwrap().value = Some(Letter::new_fixed('C', 0));
board.get_cell_mut(Coordinates(4, 0)).unwrap().value = Some(Letter::new_fixed('O', 0));
board.get_cell_mut(Coordinates(5, 0)).unwrap().value = Some(Letter::new_fixed('O', 0));
board.get_cell_mut(Coordinates(6, 0)).unwrap().value = Some(Letter::new_fixed('L', 0));
fn word_to_text(word: &Word) -> String {
let mut text = String::with_capacity(word.cells.len());
for cell in word.cells.as_slice() {
text.push(cell.value.as_ref().unwrap().text);
}
text
}
fn check_board(board: &mut Board, inverted: bool) {
let words = board.find_played_words();
match words {
Ok(x) => {
assert_eq!(x.len(), 1);
let word = x.get(0).unwrap();
assert_eq!(word_to_text(word), "JOEL");
}
Err(e) => { panic!("Expected to find a word to play; found error {}", e) }
}
let maybe_invert = |coords: Coordinates| {
if inverted {
return Coordinates(coords.1, coords.0);
}
return coords;
};
let maybe_invert_direction = |direction: Direction| {
if inverted {
return direction.invert();
}
return direction;
};
board.get_cell_mut(maybe_invert(Coordinates(9, 8))).unwrap().value = Some(Letter::new_fixed('G', 0));
board.get_cell_mut(maybe_invert(Coordinates(10, 8))).unwrap().value = Some(Letter::new_fixed('G', 0));
let word = board.find_word_at_position(Coordinates(8, 8), maybe_invert_direction(Direction::Row));
match word {
None => {panic!("Expected to find word EGG")}
Some(x) => {
assert_eq!(x.coords.0, 8);
assert_eq!(x.coords.1, 8);
assert_eq!(word_to_text(&x), "EGG");
}
}
let words = board.find_played_words();
match words {
Ok(x) => {
assert_eq!(x.len(), 2);
let word = x.get(0).unwrap();
assert_eq!(word_to_text(word), "EGG");
let word = x.get(1).unwrap();
assert_eq!(word_to_text(word), "JOEL");
}
Err(e) => { panic!("Expected to find a word to play; found error {}", e) }
}
board.get_cell_mut(maybe_invert(Coordinates(9, 8))).unwrap().value = Some(make_letter('G', true));
let words = board.find_played_words();
match words {
Ok(_) => { panic!("Expected error as we played tiles in multiple rows and columns") }
Err(e) => { assert_eq!(e, "Tiles need to be played on one row or column") }
}
}
// make a copy of the board now with x and y swapped
let mut inverted_board = Board::new();
for x in 0..GRID_LENGTH {
for y in 0..GRID_LENGTH {
let cell_original = board.get_cell(Coordinates(x, y)).unwrap();
let cell_new = inverted_board.get_cell_mut(Coordinates(y, x)).unwrap();
match &cell_original.value {
None => {}
Some(x) => {
cell_new.value = Some(*x);
}
}
}
}
println!("Checking original board");
check_board(&mut board, false);
println!("Checking inverted board");
check_board(&mut inverted_board, true);
}
#[test]