Решение на Wordle от Иван Пенев

Обратно към всички решения

Към профила на Иван Пенев

Резултати

  • 20 точки от тестове
  • 0 бонус точки
  • 20 точки общо
  • 15 успешни тест(а)
  • 0 неуспешни тест(а)

Код

use std::fmt;
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum GameStatus {
InProgress,
Won,
Lost,
}
#[derive(Debug, PartialEq)]
pub enum GameError {
NotInAlphabet(char),
WrongLength { expected: usize, actual: usize },
GameIsOver(GameStatus),
}
#[derive(Debug)]
pub struct Game {
pub status: GameStatus,
pub attempts: u8,
pub word: Word,
pub alphabet: Vec<char>,
pub history: Vec<Word>,
}
#[derive(Debug, PartialEq, Clone)]
pub struct Word {
pub answer: String,
pub guess: String,
}
impl fmt::Display for Word {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut result = String::new();
let mut guess_it = self.guess.chars();
let mut answ_it = self.answer.chars();
while let Some(guess_ch) = guess_it.next() {
let answ_ch = answ_it.next().unwrap();
let to_push = if answ_ch == guess_ch {
format!("[{}]", guess_ch)
} else if self.answer.contains(guess_ch) {
format!("({})", guess_ch)
} else {
format!(">{}<", guess_ch)
}
.to_string();
result.push_str(&to_push.to_uppercase());
}
write!(f, "{}", result)
}
}
impl fmt::Display for Game {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut result = String::new();
result.push_str(&"|_|".repeat(self.word.answer.chars().count()));
result.push('\n');
let mut iter = self.history.iter();
while let Some(word) = iter.next() {
result.push_str(&word.to_string());
result.push('\n');
}
write!(f, "{}", result.trim_end())
}
}
impl Game {
pub fn new(alphabet: &str, word: &str) -> Result<Self, GameError> {
let alphabet_vec: Vec<char> = alphabet.chars().collect();
Self::check_word_from_alphabet(&alphabet_vec, word)?;
let init_game = Game {
status: GameStatus::InProgress,
attempts: 0,
word: Word {
answer: word.to_string(),
guess: String::new(),
},
alphabet: alphabet_vec,
history: Vec::<Word>::new(),
};
Ok(init_game)
}
pub fn guess_word(&mut self, guess: &str) -> Result<Word, GameError> {
self.word.guess = guess.to_string();
Self::check_game_status(&self)?;
Self::check_guess_length(&self)?;
Self::check_word_from_alphabet(&self.alphabet, guess)?;
self.attempts += 1;
self.history.push(self.word.clone());
if self.word.guess == self.word.answer {
self.status = GameStatus::Won;
return Ok(self.word.clone());
}
if self.attempts == 5 {
self.status = GameStatus::Lost;
}
Ok(self.word.clone())
}
pub fn check_word_from_alphabet(alphabet: &Vec<char>, word: &str) -> Result<(), GameError> {
for ch in word.chars() {
if !alphabet.contains(&ch) {
return Err(GameError::NotInAlphabet(ch));
}
}
Ok(())
}
pub fn check_game_status(&self) -> Result<(), GameError> {
if self.status != GameStatus::InProgress {
return Err(GameError::GameIsOver(self.status));
}
Ok(())
}
pub fn check_guess_length(&self) -> Result<(), GameError> {
let expected = self.word.answer.chars().count();
let actual = self.word.guess.chars().count();
if expected != actual {
return Err(GameError::WrongLength {
expected: expected,
actual: actual,
});
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_basic() {
let english_letters = "abcdefghijklmnopqrstuvwxyz";
assert!(Game::new(english_letters, "!!!").is_err());
let mut game = Game::new(&String::from(english_letters), "abc").unwrap();
assert!(matches!(game.status, GameStatus::InProgress));
assert_eq!(game.attempts, 0);
assert_eq!(game.to_string(), "|_||_||_|");
assert_eq!(game.guess_word("abc").unwrap().to_string(), "[A][B][C]");
}
#[test]
fn test_new_game_with_valid_word() {
let game = Game::new("abcdefghijklmnopqrstuvwxyz", "kebap").unwrap();
assert_eq!(game.status, GameStatus::InProgress);
assert_eq!(game.attempts, 0);
}
#[test]
fn test_new_game_with_invalid_word() {
let err = Game::new("abcdefghijklmnopqrstuvwxyz", "xyz123");
assert!(err.is_err());
assert_eq!(err.unwrap_err(), GameError::NotInAlphabet('1'));
}
#[test]
fn test_new_game_with_cyrillic_alphabet() {
let game = Game::new("абвгдежзийклмнопрстуфхзцшщъьюя", "шльокавица").unwrap();
assert_eq!(game.status, GameStatus::InProgress);
assert_eq!(game.attempts, 0);
}
#[test]
fn test_guess_word_with_finished_won_game() {
let mut game = Game::new("abcdefghijklmnopqrstuvwxyz", "kebap").unwrap();
game.status = GameStatus::Won;
let err = game.guess_word("kebap");
assert!(err.is_err());
assert_eq!(err.unwrap_err(), GameError::GameIsOver(GameStatus::Won));
}
#[test]
fn test_guess_word_with_finished_lost_game() {
let mut game = Game::new("abcdefghijklmnopqrstuvwxyz", "kebap").unwrap();
game.status = GameStatus::Lost;
let err = game.guess_word("kebap");
assert!(err.is_err());
assert_eq!(err.unwrap_err(), GameError::GameIsOver(GameStatus::Lost));
}
#[test]
fn test_guess_word_length_error() {
let mut game = Game::new("кебап", "кебап").unwrap();
let err = game.guess_word("кебапи");
assert!(err.is_err());
assert_eq!(
err.unwrap_err(),
GameError::WrongLength {
expected: 5,
actual: 6
}
);
}
#[test]
fn test_guess_word_alphabet_error() {
let mut game = Game::new("abcdefghijklmnopqrstuvwxyz", "kebap").unwrap();
let err = game.guess_word("кебап");
assert!(err.is_err());
assert_eq!(err.unwrap_err(), GameError::NotInAlphabet('к'));
}
#[test]
fn test_guess_word_valid() {
let mut game = Game::new("abcdefghijklmnopqrstuvwxyz", "rebus").unwrap();
game.guess_word("route").unwrap();
assert_eq!("[R]>O<(U)>T<(E)", game.word.to_string());
game.guess_word("rules").unwrap();
assert_eq!("[R](U)>L<(E)[S]", game.word.to_string());
game.guess_word("rebus").unwrap();
assert_eq!("[R][E][B][U][S]", game.word.to_string());
}
#[test]
fn test_guess_word_valid_cyrillic() {
let mut game = Game::new("абвгдежзийклмнопрстуфхзцшщъьюя", "кебап").unwrap();
game.guess_word("бирак").unwrap();
assert_eq!("(Б)>И<>Р<[А](К)", game.word.to_string());
game.guess_word("кабеп").unwrap();
assert_eq!("[К](А)[Б](Е)[П]", game.word.to_string());
game.guess_word("кебап").unwrap();
assert_eq!("[К][Е][Б][А][П]", game.word.to_string());
}
#[test]
fn test_guess_word_win_game() {
let mut game = Game::new("абвгдежзийклмнопрстуфхзцшщъьюя", "кебап").unwrap();
assert_eq!(GameStatus::InProgress, game.status);
game.guess_word("бирак").unwrap();
assert_eq!(1, game.attempts);
assert_eq!(GameStatus::InProgress, game.status);
game.guess_word("кабеп").unwrap();
assert_eq!(2, game.attempts);
assert_eq!(GameStatus::InProgress, game.status);
game.guess_word("апекб").unwrap();
assert_eq!(3, game.attempts);
assert_eq!(GameStatus::InProgress, game.status);
game.guess_word("кебап").unwrap();
assert_eq!(4, game.attempts);
assert_eq!(GameStatus::Won, game.status);
}
#[test]
fn test_guess_word_lose_game() {
let mut game = Game::new("абвгдежзийклмнопрстуфхзцшщъьюя", "кебап").unwrap();
assert_eq!(GameStatus::InProgress, game.status);
game.guess_word("бирак").unwrap();
assert_eq!(1, game.attempts);
game.guess_word("кабеп").unwrap();
assert_eq!(2, game.attempts);
game.guess_word("апекб").unwrap();
assert_eq!(3, game.attempts);
game.guess_word("бекап").unwrap();
assert_eq!(4, game.attempts);
game.guess_word("пакеб").unwrap();
assert_eq!(5, game.attempts);
assert_eq!(GameStatus::Lost, game.status);
}
#[test]
fn test_guess_word_duplication() {
let mut game = Game::new("abcdefghijklmnopqrstuvwxyz", "foobar").unwrap();
game.guess_word("oopsie").unwrap();
assert_eq!("(O)[O]>P<>S<>I<>E<", game.word.to_string());
let mut game = Game::new("ab", "ab").unwrap();
game.guess_word("bb").unwrap();
assert_eq!("(B)[B]", game.word.to_string());
}
#[test]
fn test_guess_word_uppercase() {
let mut game = Game::new("abcdefghijklmnopqrstuvwxyzäöüß", "süß").unwrap();
game.guess_word("füß").unwrap();
assert_eq!(">F<[Ü][SS]", game.word.to_string());
}
#[test]
fn test_game_history() {
let english_letters = "abcdefghijklmnopqrstuvwxyz";
let mut game = Game::new(english_letters, "rebus").unwrap();
assert_eq!(game.to_string(), "|_||_||_||_||_|");
game.guess_word("route").unwrap();
assert_eq!(game.to_string(), "|_||_||_||_||_|\n[R]>O<(U)>T<(E)");
game.guess_word("rebus").unwrap();
assert_eq!(
game.to_string(),
"|_||_||_||_||_|\n[R]>O<(U)>T<(E)\n[R][E][B][U][S]"
);
}
#[test]
fn test_game_history_ez_win() {
let english_letters = "abcdefghijklmnopqrstuvwxyz";
let mut game = Game::new(english_letters, "a").unwrap();
assert_eq!(game.to_string(), "|_|");
game.guess_word("a").unwrap();
assert_eq!(game.to_string(), "|_|\n[A]");
}
#[test]
fn test_game_history_win() {
let english_letters = "abcdefghijklmnopqrstuvwxyz";
let mut game = Game::new(english_letters, "e").unwrap();
assert_eq!(game.to_string(), "|_|");
game.guess_word("a").unwrap();
assert_eq!(game.to_string(), "|_|\n>A<");
game.guess_word("b").unwrap();
assert_eq!(game.to_string(), "|_|\n>A<\n>B<");
game.guess_word("c").unwrap();
assert_eq!(game.to_string(), "|_|\n>A<\n>B<\n>C<");
game.guess_word("d").unwrap();
assert_eq!(game.to_string(), "|_|\n>A<\n>B<\n>C<\n>D<");
game.guess_word("e").unwrap();
assert_eq!(game.to_string(), "|_|\n>A<\n>B<\n>C<\n>D<\n[E]");
}
#[test]
fn test_game_history_lose() {
let english_letters = "abcdefghijklmnopqrstuvwxyz";
let mut game = Game::new(english_letters, "f").unwrap();
assert_eq!(game.to_string(), "|_|");
game.guess_word("a").unwrap();
assert_eq!(game.to_string(), "|_|\n>A<");
game.guess_word("b").unwrap();
assert_eq!(game.to_string(), "|_|\n>A<\n>B<");
game.guess_word("c").unwrap();
assert_eq!(game.to_string(), "|_|\n>A<\n>B<\n>C<");
game.guess_word("d").unwrap();
assert_eq!(game.to_string(), "|_|\n>A<\n>B<\n>C<\n>D<");
game.guess_word("e").unwrap();
assert_eq!(game.to_string(), "|_|\n>A<\n>B<\n>C<\n>D<\n>E<");
}
}

Лог от изпълнението

Compiling solution v0.1.0 (/tmp/d20230111-3772066-1i1r71v/solution)
    Finished test [unoptimized + debuginfo] target(s) in 0.80s
     Running tests/solution_test.rs (target/debug/deps/solution_test-0edbea2040daef01)

running 15 tests
test solution_test::test_game_display ... ok
test solution_test::test_game_display_cyrillic ... ok
test solution_test::test_game_display_german ... ok
test solution_test::test_game_state_1 ... ok
test solution_test::test_game_state_3 ... ok
test solution_test::test_game_state_2 ... ok
test solution_test::test_word_display ... ok
test solution_test::test_word_display_bulgarian ... ok
test solution_test::test_word_display_german ... ok
test solution_test::test_word_not_in_alphabet_on_construction ... ok
test solution_test::test_word_display_with_repetitions ... ok
test solution_test::test_word_not_in_alphabet_on_construction_cyrrilic ... ok
test solution_test::test_word_not_in_alphabet_on_guess ... ok
test solution_test::test_wrong_length ... ok
test solution_test::test_word_not_in_alphabet_on_guess_cyrillic ... ok

test result: ok. 15 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

История (1 версия и 0 коментара)

Иван качи първо решение на 23.11.2022 01:04 (преди 2 месеца)