Решение на Wordle от Александър Македонски
Към профила на Александър Македонски
Резултати
- 13 точки от тестове
- 0 бонус точки
- 13 точки общо
- 10 успешни тест(а)
- 5 неуспешни тест(а)
Код
#[derive(Debug)]
#[derive(PartialEq)]
#[derive(Clone)]
pub enum GameStatus {
InProgress,
Won,
Lost,
}
#[derive(Debug)]
pub enum GameError {
NotInAlphabet(char),
InvalidWord,
WrongLength { expected: usize, actual: usize },
GameIsOver(GameStatus),
}
#[derive(Debug)]
pub struct Game {
pub status: GameStatus,
pub attempts: u8,
pub letters_in_alphabet: Vec<char>,
pub word: Word,
pub history: Vec<Word>
}
#[derive(Debug)]
#[derive(Clone)]
pub struct Word {
letters: Vec<char>,
}
impl Game {
pub fn new(alphabet: &str, word: &str) -> Result<Self, GameError> {
let letters_in_alphabet : Vec<char> = alphabet.chars().collect();
let letters_to_guess : Vec<char> = word.chars().collect();
if word.len() == 0 || letters_in_alphabet.len() == 0
{
return Err(GameError::InvalidWord);
}
for letter_to_guess in &letters_to_guess
{
if !!!(letters_in_alphabet.contains(&letter_to_guess))
{
return Err(GameError::NotInAlphabet(*letter_to_guess));
}
}
return Ok(Game{status: GameStatus::InProgress,
attempts: 0,
letters_in_alphabet,
word: Word{
letters: Vec::from(letters_to_guess)},
history: [].to_vec()})
}
pub fn guess_word(&mut self, guess: &str) -> Result<Word, GameError> {
if !!!(self.status == GameStatus::InProgress)
{
return Err(GameError::GameIsOver(self.status.clone()))
}
if guess.len() != self.word.letters.len()
{
return Err(GameError::WrongLength{ expected: self.word.letters.len(), actual: guess.len() })
}
let guess_letters: Vec<char> = guess.chars().collect();
for letter in &guess_letters
{
if !!!self.letters_in_alphabet.contains(&letter)
{
return Err(GameError::NotInAlphabet(*letter));
}
}
let mut bulls: u8 = 0;
let mut word: Word = Word{letters: [].to_vec()};
for i in 0..self.word.letters.len()
{
if self.word.letters[i] == guess_letters[i]
{
bulls+=1;
word.letters.append(&mut ['[',guess_letters[i].to_ascii_uppercase(), ']'].to_vec());
}
else if self.word.letters.contains(&guess_letters[i])
{
word.letters.append(&mut ['(',guess_letters[i].to_ascii_uppercase(),')'].to_vec());
}
else
{
word.letters.append(&mut ['>',guess_letters[i].to_ascii_uppercase(),'<'].to_vec());
}
}
self.attempts += 1;
if usize::from(bulls) == guess.len()
{
self.status = GameStatus::Won;
self.history.push(word.clone());
return Ok(word)
}
if self.attempts == 5
{
self.status = GameStatus::Lost;
}
self.history.push(word.clone());
Ok(word)
}
}
use std::fmt;
impl fmt::Display for Word {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let message: String = self.letters.clone().into_iter().collect();
write!(f, "{}", message)
}
}
impl fmt::Display for Game {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut message: String = "".to_string();
for _letter in &self.word.letters
{
message = format!("{}|_|", message)
}
for word in &self.history
{
message = format!("{}\n{}", message, word)
}
write!(f, "{}", message)
}
}
#[test]
fn test_basic() {
let english_letters = "abcdefghijklmnopqrstuvwxyz";
// Конструираме по два различни начина, just in case -- няма причина да не работи и с двата.
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_alphabet() {
let english_letters = "abcdefghijklmnopqrstuvwxyz";
assert!(Game::new(english_letters, "!").is_err());
assert!(Game::new(english_letters, " ").is_err());
//Празна дума:
assert!(Game::new(english_letters, "").is_err());
assert!(Game::new(english_letters, "дума").is_err());
// Българската буква 'а':
assert!(Game::new(english_letters, "а").is_err());
assert!(Game::new(english_letters, "word l").is_err());
assert!(Game::new(english_letters, "38").is_err());
assert!(Game::new(english_letters, "\n").is_err());
assert!(Game::new(english_letters, "\'").is_err());
let english_letters = "abcdefghijklmnopqrstuvwxyz";
let mut game: Game = Game::new(english_letters, "first").unwrap();
assert!(game.guess_word("abc").is_err());
assert!(game.guess_word("second").is_err());
assert_eq!(game.to_string(), "|_||_||_||_||_|");
assert_eq!(game.attempts, 0); //Опитите не са се увеличили
}
#[test]
fn test_word() {
let word: Word = Word{letters: vec!['w','o','r','d','l','e']};
let word_copy: Word = word.clone();
assert_eq!(word.to_string(), "wordle");
assert_eq!(word.to_string(), "wordle");
// Двойно тестване, за да съм сигурен, че не съм направил местене на памет някъде :D
assert_eq!(word_copy.to_string(), "wordle");
let empty_word: Word = Word{letters: vec![]};
assert_eq!(empty_word.to_string(), "");
}
#[test]
fn test_lose_game() {
//Now we getting serious.
let english_letters = "abcdefghijklmnopqrstuvwxyz";
let mut first_game: Game = Game::new(english_letters, "first").unwrap();
assert!(matches!(first_game.status, GameStatus::InProgress));
assert_eq!(first_game.attempts, 0);
assert_eq!(first_game.to_string(), "|_||_||_||_||_|");
assert_eq!(first_game.guess_word("firbl").unwrap().to_string(), "[F][I][R]>B<>L<");
assert_eq!(first_game.to_string(), "|_||_||_||_||_|\n[F][I][R]>B<>L<");
assert!(matches!(first_game.status, GameStatus::InProgress));
assert_eq!(first_game.attempts, 1);
assert_eq!(first_game.guess_word("farsr").unwrap().to_string(), "[F]>A<[R][S](R)");
assert_eq!(first_game.to_string(), "|_||_||_||_||_|\n[F][I][R]>B<>L<\n[F]>A<[R][S](R)");
assert!(matches!(first_game.status, GameStatus::InProgress));
assert_eq!(first_game.attempts, 2);
assert_eq!(first_game.guess_word("tfirs").unwrap().to_string(), "(T)(F)(I)(R)(S)");
assert_eq!(first_game.to_string(), "|_||_||_||_||_|\n[F][I][R]>B<>L<\n[F]>A<[R][S](R)\n(T)(F)(I)(R)(S)");
assert!(matches!(first_game.status, GameStatus::InProgress));
assert_eq!(first_game.attempts, 3);
assert_eq!(first_game.guess_word("tfirs").unwrap().to_string(), "(T)(F)(I)(R)(S)");
assert_eq!(first_game.attempts, 4);
assert_eq!(first_game.guess_word("tfirs").unwrap().to_string(), "(T)(F)(I)(R)(S)");
assert_eq!(first_game.attempts, 5);
assert!(matches!(first_game.status, GameStatus::Lost));
assert!(first_game.guess_word("first").is_err());
}
#[test]
fn test_win_game() {
//Now we getting serious.
let english_letters = "abcdefghijklmnopqrstuvwxyz";
let mut second_game: Game = Game::new(english_letters, "first").unwrap();
assert_eq!(second_game.guess_word("firbl").unwrap().to_string(), "[F][I][R]>B<>L<");
assert_eq!(second_game.to_string(), "|_||_||_||_||_|\n[F][I][R]>B<>L<");
assert!(matches!(second_game.status, GameStatus::InProgress));
assert_eq!(second_game.attempts, 1);
assert_eq!(second_game.guess_word("first").unwrap().to_string(), "[F][I][R][S][T]");
assert_eq!(second_game.to_string(), "|_||_||_||_||_|\n[F][I][R]>B<>L<\n[F][I][R][S][T]");
assert!(matches!(second_game.status, GameStatus::Won));
assert_eq!(second_game.attempts, 2);
assert!(second_game.guess_word("first").is_err());
}
Лог от изпълнението
Compiling solution v0.1.0 (/tmp/d20230111-3772066-77wvkr/solution) Finished test [unoptimized + debuginfo] target(s) in 0.79s 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 ... FAILED test solution_test::test_game_display_german ... FAILED test solution_test::test_game_state_1 ... ok test solution_test::test_game_state_2 ... ok test solution_test::test_game_state_3 ... ok test solution_test::test_word_display ... ok test solution_test::test_word_display_bulgarian ... FAILED test solution_test::test_word_display_german ... FAILED test solution_test::test_word_display_with_repetitions ... ok test solution_test::test_word_not_in_alphabet_on_construction ... ok test solution_test::test_word_not_in_alphabet_on_guess ... ok test solution_test::test_word_not_in_alphabet_on_guess_cyrillic ... FAILED test solution_test::test_wrong_length ... ok test solution_test::test_word_not_in_alphabet_on_construction_cyrrilic ... ok failures: ---- solution_test::test_game_display_cyrillic stdout ---- thread 'solution_test::test_game_display_cyrillic' panicked at 'called `Result::unwrap()` on an `Err` value: WrongLength { expected: 3, actual: 6 }', tests/solution_test.rs:120:28 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace ---- solution_test::test_game_display_german stdout ---- thread 'solution_test::test_game_display_german' panicked at 'called `Result::unwrap()` on an `Err` value: WrongLength { expected: 3, actual: 5 }', tests/solution_test.rs:134:28 ---- solution_test::test_word_display_bulgarian stdout ---- thread 'solution_test::test_word_display_bulgarian' panicked at 'called `Result::unwrap()` on an `Err` value: WrongLength { expected: 4, actual: 8 }', tests/solution_test.rs:77:40 ---- solution_test::test_word_display_german stdout ---- thread 'solution_test::test_word_display_german' panicked at 'called `Result::unwrap()` on an `Err` value: WrongLength { expected: 3, actual: 5 }', tests/solution_test.rs:88:39 ---- solution_test::test_word_not_in_alphabet_on_guess_cyrillic stdout ---- thread 'solution_test::test_word_not_in_alphabet_on_guess_cyrillic' panicked at 'Expression Err(WrongLength { expected: 4, actual: 8 }) does not match the pattern "Err(GameError::NotInAlphabet('х'))"', tests/solution_test.rs:46:5 failures: solution_test::test_game_display_cyrillic solution_test::test_game_display_german solution_test::test_word_display_bulgarian solution_test::test_word_display_german solution_test::test_word_not_in_alphabet_on_guess_cyrillic test result: FAILED. 10 passed; 5 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s error: test failed, to rerun pass `--test solution_test`