Решение на Wordle от Калин Борисов
Резултати
- 19 точки от тестове
- 0 бонус точки
- 19 точки общо
- 14 успешни тест(а)
- 1 неуспешни тест(а)
Код
use std::fmt;
#[derive(Debug)]
pub enum GameStatus {
InProgress,
Won,
Lost,
}
#[derive(Debug)]
pub enum GameError {
NotInAlphabet(char),
WrongLength { expected: usize, actual: usize },
GameIsOver(GameStatus),
}
#[derive(Debug)]
pub struct Game {
pub status: GameStatus,
pub attempts: u8,
pub alphabet: String,
pub start_word: Word,
pub words: Vec<Word>,
// Каквито други полета ви трябват
}
#[derive(Debug)]
enum Letter {
Unknown,
FullMatch(char),
PartialMatch(char),
NoMatch(char),
}
#[derive(Debug)]
pub struct Word {
pub letters: String,
letters_enum: Vec<Letter>,
// Каквито полета ви трябват
}
impl Word {
pub(crate) fn new(letters_to: String, letters_from: Vec<Letter>) -> Self {
Word {letters: letters_to, letters_enum: letters_from}
}
pub fn compare(self, other: &Word) -> bool {
if self.letters.eq(&other.letters) {
return true;
}
return false;
}
}
impl Game {
/// Конструира нова игра с думи/букви от дадената в `alphabet` азбука. Alphabet е просто низ,
/// в който всеки символ е отделна буква, който вероятно искате да си запазите някак за после.
///
/// Подадената дума с `word` трябва да има само букви от тази азбука. Иначе очакваме да върнете
/// `GameError::NotInAlphabet` грешка с първия символ в `word`, който не е от азбуката.
///
/// Началното състояние на играта е `InProgress` а началния брой опити `attempts` е 0.
///
pub fn new(alphabet: &str, word: &str) -> Result<Self, GameError> {
let tuple = validate_word(alphabet,word);
if tuple.0 == false {
return Err(GameError::NotInAlphabet(tuple.1));
}
let mut vector_of_letters: Vec<Letter> = Vec::new();
for c in word.chars() {
vector_of_letters.push(Letter::FullMatch(c));
}
let start_word = Word::new(word.to_string(),vector_of_letters);
let mut vector_of_letters_for_empty: Vec<Letter> = Vec::new();
for _c in word.chars() {
vector_of_letters_for_empty.push(Letter::Unknown);
}
let empty_word = Word::new("".to_string(),vector_of_letters_for_empty);
let mut vector_of_words: Vec<Word> = Vec::new();
vector_of_words.push(empty_word);
Ok(Game {status: GameStatus::InProgress, attempts: 0, alphabet: alphabet.to_string(), start_word: start_word,words: vector_of_words})
}
/// Опитва се да познае търсената дума. Опита е в `guess`.
///
/// Ако играта е приключила, тоест статуса ѝ е `Won` или `Lost`, очакваме да върнете
/// `GameIsOver` със статуса, с който е приключила.
///
/// Ако `guess` има различен брой букви от търсената дума, очакваме да върнете
/// `GameError::WrongLength`. Полето `expected` на грешката трябва да съдържа броя букви на
/// търсената дума, а `actual` да е броя букви на опита `guess`.
///
/// Ако `guess` има правилния брой букви, но има буква, която не е от азбуката на играта,
/// очакваме `GameError::NotInAlphabet` както по-горе, с първия символ от `guess`, който не е
/// от азбуката.
///
/// Метода приема `&mut self`, защото всеки опит се запазва в играта за по-нататък. Метода
/// връща `Word`, което описва освен самите символи на `guess`, и как тези символи са се
/// напаснали на търсената дума. Също така инкрементира `attempts` с 1.
///
/// След опита за напасване на думата, ако всички букви са уцелени на правилните места,
/// очакваме `state` полето да се промени на `Won`. Иначе, ако `attempts` са станали 5,
/// състоянието трябва да е `Lost`.
///
pub fn guess_word(&mut self, guess: &str) -> Result<Word, GameError> {
match self.status {
GameStatus::Lost => return Err(GameError::GameIsOver(GameStatus::Lost)),
GameStatus::Won => return Err(GameError::GameIsOver(GameStatus::Won)),
GameStatus::InProgress => self.guess_word_util(guess),
}
}
fn guess_word_util(&mut self, guess: &str) -> Result<Word, GameError> {
if self.attempts == 5 {
self.status = GameStatus::Lost;
return Err(GameError::GameIsOver(GameStatus::Lost));
}
if word_size(guess) != word_size(&self.start_word.letters) {
return Err(GameError::WrongLength {expected: word_size(&self.start_word.letters), actual: word_size(guess)});
}
let tuple = validate_word(&self.alphabet,guess);
if tuple.0 == false {
return Err(GameError::NotInAlphabet(tuple.1));
}
let letter_enum = self.get_word_vector(guess);
let new_word: Word = Word::new(guess.to_string(), letter_enum.0);
let new_return: Word = Word::new(guess.to_string(), letter_enum.1);
self.words.push(new_word);
self.attempts += 1;
if self.attempts == 5 {
self.status = GameStatus::Lost;
}
if guess.eq(&self.start_word.letters.to_string()) {
self.status = GameStatus::Won;
}
return Ok(new_return);
}
fn get_word_vector(&mut self, word: &str) -> (Vec<Letter>, Vec<Letter>) {
let mut vector_of_letters: Vec<Letter> = Vec::new();
let mut vector_of_letters_second: Vec<Letter> = Vec::new();
let mut index = 0;
let mut vector_of_char: Vec<char> = Vec::new();
for c in self.start_word.letters.chars() {
vector_of_char.push(c as char);
}
for c in word.chars() {
if c == vector_of_char[index] {
vector_of_letters.push(Letter::FullMatch(c));
vector_of_letters_second.push(Letter::FullMatch(c));
index += 1;
continue;
}
if self.start_word.letters.contains(c) {
vector_of_letters.push(Letter::PartialMatch(c));
vector_of_letters_second.push(Letter::PartialMatch(c));
index += 1;
continue;
}
vector_of_letters.push(Letter::NoMatch(c));
vector_of_letters_second.push(Letter::NoMatch(c));
index += 1;
}
(vector_of_letters,vector_of_letters_second)
}
}
fn word_size(word: &str) -> usize {
let mut counter : usize = 0;
for _c in word.chars() {
counter += 1
}
counter
}
fn validate_word(alphabet: &str, word: &str) -> (bool, char) {
let mut result = true;
let mut cha : char = '_';
for c in word.chars() {
if !result {
return (false, cha);
} else {
result = false;
}
if alphabet.contains(c) {
result = true;
}
cha = c;
}
(true, ' ')
}
impl fmt::Display for Word {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut result = String::from("");
for temp in &self.letters_enum {
match temp {
Letter::NoMatch(x) => result.push_str(&format!(">{}<", x.to_uppercase()),),
Letter::FullMatch(x) => result.push_str(&format!("[{}]", x.to_uppercase())),
Letter::PartialMatch(x) => result.push_str(&format!("({})", x.to_uppercase())),
Letter::Unknown => result.push_str(&format!("|_|")),
}
}
write!(f,"{}", result)
}
}
impl fmt::Display for Game {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut result = String::from("");
let mut _newline = false;
const LINECHAR: &str = "\n";
for word in self.words.iter() {
if _newline == true {
result.push_str(LINECHAR);
_newline = false;
}
result.push_str(&format!("{}",word).to_string());
_newline = true;
}
write!(f,"{}",result)
}
}
Лог от изпълнението
Compiling solution v0.1.0 (/tmp/d20230111-3772066-v3ued8/solution) Finished test [unoptimized + debuginfo] target(s) in 0.78s 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_2 ... ok test solution_test::test_game_state_3 ... 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_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_construction_cyrrilic ... FAILED test solution_test::test_word_not_in_alphabet_on_guess_cyrillic ... ok test solution_test::test_wrong_length ... ok failures: ---- solution_test::test_word_not_in_alphabet_on_construction_cyrrilic stdout ---- thread 'solution_test::test_word_not_in_alphabet_on_construction_cyrrilic' panicked at 'Expression Ok(Game { status: InProgress, attempts: 0, alphabet: "абвгдежзийклмнопрстуфхцчшщъьюя", start_word: Word { letters: "смайлифейс😄", letters_enum: [FullMatch('с'), FullMatch('м'), FullMatch('а'), FullMatch('й'), FullMatch('л'), FullMatch('и'), FullMatch('ф'), FullMatch('е'), FullMatch('й'), FullMatch('с'), FullMatch('😄')] }, words: [Word { letters: "", letters_enum: [Unknown, Unknown, Unknown, Unknown, Unknown, Unknown, Unknown, Unknown, Unknown, Unknown, Unknown] }] }) does not match the pattern "Err(GameError::NotInAlphabet('😄'))"', tests/solution_test.rs:29:5 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace failures: solution_test::test_word_not_in_alphabet_on_construction_cyrrilic test result: FAILED. 14 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s error: test failed, to rerun pass `--test solution_test`
История (5 версии и 0 коментара)
Калин качи решение на 19.11.2022 16:03 (преди почти 3 години)
+// Working version from base test with my own tests running
use std::fmt;
#[derive(Debug)]
pub enum GameStatus {
InProgress,
Won,
Lost,
}
#[derive(Debug)]
pub enum GameError {
NotInAlphabet(char),
WrongLength { expected: usize, actual: usize },
GameIsOver(GameStatus),
}
#[derive(Debug)]
pub struct Game {
pub status: GameStatus,
pub attempts: u8,
pub alphabet: String,
pub start_word: Word,
pub words: Vec<Word>,
// Каквито други полета ви трябват
}
#[derive(Debug)]
enum Letter {
Unknown,
FullMatch(char),
PartialMatch(char),
NoMatch(char),
}
#[derive(Debug)]
pub struct Word {
pub letters: String,
letters_enum: Vec<Letter>,
// Каквито полета ви трябват
}
impl Word {
pub(crate) fn new(letters_to: String, letters_from: Vec<Letter>) -> Self {
Word {letters: letters_to, letters_enum: letters_from}
}
pub fn compare(self, other: &Word) -> bool {
if self.letters.eq(&other.letters) {
return true;
}
return false;
}
}
impl Game {
/// Конструира нова игра с думи/букви от дадената в `alphabet` азбука. Alphabet е просто низ,
/// в който всеки символ е отделна буква, който вероятно искате да си запазите някак за после.
///
/// Подадената дума с `word` трябва да има само букви от тази азбука. Иначе очакваме да върнете
/// `GameError::NotInAlphabet` грешка с първия символ в `word`, който не е от азбуката.
///
/// Началното състояние на играта е `InProgress` а началния брой опити `attempts` е 0.
///
pub fn new(alphabet: &str, word: &str) -> Result<Self, GameError> {
let tuple = validate_word(alphabet,word);
if tuple.0 == false {
return Err(GameError::NotInAlphabet(tuple.1));
}
let mut vector_of_letters: Vec<Letter> = Vec::new();
for c in word.chars() {
vector_of_letters.push(Letter::FullMatch(c));
}
let start_word = Word::new(word.to_string(),vector_of_letters);
let mut vector_of_letters_for_empty: Vec<Letter> = Vec::new();
for _c in word.chars() {
vector_of_letters_for_empty.push(Letter::Unknown);
}
let empty_word = Word::new("".to_string(),vector_of_letters_for_empty);
let mut vector_of_words: Vec<Word> = Vec::new();
vector_of_words.push(empty_word);
Ok(Game {status: GameStatus::InProgress, attempts: 0, alphabet: alphabet.to_string(), start_word: start_word,words: vector_of_words})
}
/// Опитва се да познае търсената дума. Опита е в `guess`.
///
/// Ако играта е приключила, тоест статуса ѝ е `Won` или `Lost`, очакваме да върнете
/// `GameIsOver` със статуса, с който е приключила.
///
/// Ако `guess` има различен брой букви от търсената дума, очакваме да върнете
/// `GameError::WrongLength`. Полето `expected` на грешката трябва да съдържа броя букви на
/// търсената дума, а `actual` да е броя букви на опита `guess`.
///
/// Ако `guess` има правилния брой букви, но има буква, която не е от азбуката на играта,
/// очакваме `GameError::NotInAlphabet` както по-горе, с първия символ от `guess`, който не е
/// от азбуката.
///
/// Метода приема `&mut self`, защото всеки опит се запазва в играта за по-нататък. Метода
/// връща `Word`, което описва освен самите символи на `guess`, и как тези символи са се
/// напаснали на търсената дума. Също така инкрементира `attempts` с 1.
///
/// След опита за напасване на думата, ако всички букви са уцелени на правилните места,
/// очакваме `state` полето да се промени на `Won`. Иначе, ако `attempts` са станали 5,
/// състоянието трябва да е `Lost`.
///
pub fn guess_word(&mut self, guess: &str) -> Result<Word, GameError> {
match self.status {
GameStatus::Lost => return Err(GameError::GameIsOver(GameStatus::Lost)),
GameStatus::Won => return Err(GameError::GameIsOver(GameStatus::Won)),
GameStatus::InProgress => self.guess_word_util(guess),
}
}
fn guess_word_util(&mut self, guess: &str) -> Result<Word, GameError> {
if self.attempts == 5 {
self.status = GameStatus::Lost;
return Err(GameError::GameIsOver(GameStatus::Lost));
}
if guess.len() != self.start_word.letters.len() {
return Err(GameError::WrongLength {expected: self.start_word.letters.len(), actual: guess.len()});
}
let letter_enum = self.get_word_vector(guess);
let new_word: Word = Word::new(guess.to_string(), letter_enum.0);
let new_return: Word = Word::new(guess.to_string(), letter_enum.1);
self.words.push(new_word);
self.attempts += 1;
return Ok(new_return);
}
fn get_word_vector(&mut self, word: &str) -> (Vec<Letter>, Vec<Letter>) {
let mut vector_of_letters: Vec<Letter> = Vec::new();
let mut vector_of_letters_second: Vec<Letter> = Vec::new();
let mut index = 0;
let mut vector_of_char: Vec<char> = Vec::new();
for c in self.start_word.letters.chars() {
vector_of_char.push(c as char);
}
for c in word.chars() {
if c == vector_of_char[index] {
vector_of_letters.push(Letter::FullMatch(c));
vector_of_letters_second.push(Letter::FullMatch(c));
index += 1;
continue;
}
if self.start_word.letters.contains(c) {
vector_of_letters.push(Letter::PartialMatch(c));
vector_of_letters_second.push(Letter::PartialMatch(c));
index += 1;
continue;
}
vector_of_letters.push(Letter::NoMatch(c));
vector_of_letters_second.push(Letter::NoMatch(c));
index += 1;
}
(vector_of_letters,vector_of_letters_second)
}
}
fn validate_word(alphabet: &str, word: &str) -> (bool, char) {
let mut result = true;
for c in word.chars() {
if !result {
return (false, c);
} else {
result = false;
}
if alphabet.contains(c) {
result = true;
}
}
(true, ' ')
}
impl fmt::Display for Word {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut result = String::from("");
for temp in &self.letters_enum {
match temp {
Letter::NoMatch(x) => result.push_str(&format!(">{}<", x.to_uppercase()),),
Letter::FullMatch(x) => result.push_str(&format!("[{}]", x.to_uppercase())),
Letter::PartialMatch(x) => result.push_str(&format!("({})", x.to_uppercase())),
Letter::Unknown => result.push_str(&format!("|_|")),
}
}
write!(f,"{}", result)
}
}
impl fmt::Display for Game {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut result = String::from("");
let mut _newline = false;
const LINECHAR: &str = "\n";
for word in self.words.iter() {
if _newline == true {
result.push_str(LINECHAR);
_newline = false;
}
result.push_str(&format!("{}",word).to_string());
_newline = true;
}
write!(f,"{}",result)
}
}
Калин качи решение на 20.11.2022 23:27 (преди почти 3 години)
// Working version from base test with my own tests running
use std::fmt;
#[derive(Debug)]
pub enum GameStatus {
InProgress,
Won,
Lost,
}
#[derive(Debug)]
pub enum GameError {
NotInAlphabet(char),
WrongLength { expected: usize, actual: usize },
GameIsOver(GameStatus),
}
#[derive(Debug)]
pub struct Game {
pub status: GameStatus,
pub attempts: u8,
pub alphabet: String,
pub start_word: Word,
pub words: Vec<Word>,
// Каквито други полета ви трябват
}
#[derive(Debug)]
enum Letter {
Unknown,
FullMatch(char),
PartialMatch(char),
NoMatch(char),
}
#[derive(Debug)]
pub struct Word {
pub letters: String,
letters_enum: Vec<Letter>,
// Каквито полета ви трябват
}
impl Word {
pub(crate) fn new(letters_to: String, letters_from: Vec<Letter>) -> Self {
Word {letters: letters_to, letters_enum: letters_from}
}
pub fn compare(self, other: &Word) -> bool {
if self.letters.eq(&other.letters) {
return true;
}
return false;
}
}
impl Game {
/// Конструира нова игра с думи/букви от дадената в `alphabet` азбука. Alphabet е просто низ,
/// в който всеки символ е отделна буква, който вероятно искате да си запазите някак за после.
///
/// Подадената дума с `word` трябва да има само букви от тази азбука. Иначе очакваме да върнете
/// `GameError::NotInAlphabet` грешка с първия символ в `word`, който не е от азбуката.
///
/// Началното състояние на играта е `InProgress` а началния брой опити `attempts` е 0.
///
pub fn new(alphabet: &str, word: &str) -> Result<Self, GameError> {
let tuple = validate_word(alphabet,word);
if tuple.0 == false {
return Err(GameError::NotInAlphabet(tuple.1));
}
let mut vector_of_letters: Vec<Letter> = Vec::new();
for c in word.chars() {
vector_of_letters.push(Letter::FullMatch(c));
}
let start_word = Word::new(word.to_string(),vector_of_letters);
let mut vector_of_letters_for_empty: Vec<Letter> = Vec::new();
for _c in word.chars() {
vector_of_letters_for_empty.push(Letter::Unknown);
}
let empty_word = Word::new("".to_string(),vector_of_letters_for_empty);
let mut vector_of_words: Vec<Word> = Vec::new();
vector_of_words.push(empty_word);
Ok(Game {status: GameStatus::InProgress, attempts: 0, alphabet: alphabet.to_string(), start_word: start_word,words: vector_of_words})
}
/// Опитва се да познае търсената дума. Опита е в `guess`.
///
/// Ако играта е приключила, тоест статуса ѝ е `Won` или `Lost`, очакваме да върнете
/// `GameIsOver` със статуса, с който е приключила.
///
/// Ако `guess` има различен брой букви от търсената дума, очакваме да върнете
/// `GameError::WrongLength`. Полето `expected` на грешката трябва да съдържа броя букви на
/// търсената дума, а `actual` да е броя букви на опита `guess`.
///
/// Ако `guess` има правилния брой букви, но има буква, която не е от азбуката на играта,
/// очакваме `GameError::NotInAlphabet` както по-горе, с първия символ от `guess`, който не е
/// от азбуката.
///
/// Метода приема `&mut self`, защото всеки опит се запазва в играта за по-нататък. Метода
/// връща `Word`, което описва освен самите символи на `guess`, и как тези символи са се
/// напаснали на търсената дума. Също така инкрементира `attempts` с 1.
///
/// След опита за напасване на думата, ако всички букви са уцелени на правилните места,
/// очакваме `state` полето да се промени на `Won`. Иначе, ако `attempts` са станали 5,
/// състоянието трябва да е `Lost`.
///
pub fn guess_word(&mut self, guess: &str) -> Result<Word, GameError> {
match self.status {
GameStatus::Lost => return Err(GameError::GameIsOver(GameStatus::Lost)),
GameStatus::Won => return Err(GameError::GameIsOver(GameStatus::Won)),
GameStatus::InProgress => self.guess_word_util(guess),
}
}
fn guess_word_util(&mut self, guess: &str) -> Result<Word, GameError> {
if self.attempts == 5 {
self.status = GameStatus::Lost;
return Err(GameError::GameIsOver(GameStatus::Lost));
}
+
+ if word_size(guess) != word_size(&self.start_word.letters) {
+ return Err(GameError::WrongLength {expected: word_size(&self.start_word.letters), actual: word_size(guess)});
+ }
- if guess.len() != self.start_word.letters.len() {
- return Err(GameError::WrongLength {expected: self.start_word.letters.len(), actual: guess.len()});
+ let tuple = validate_word(&self.alphabet,guess);
+ if tuple.0 == false {
+ return Err(GameError::NotInAlphabet(tuple.1));
}
+
+
+
let letter_enum = self.get_word_vector(guess);
let new_word: Word = Word::new(guess.to_string(), letter_enum.0);
let new_return: Word = Word::new(guess.to_string(), letter_enum.1);
self.words.push(new_word);
self.attempts += 1;
return Ok(new_return);
}
fn get_word_vector(&mut self, word: &str) -> (Vec<Letter>, Vec<Letter>) {
let mut vector_of_letters: Vec<Letter> = Vec::new();
let mut vector_of_letters_second: Vec<Letter> = Vec::new();
let mut index = 0;
let mut vector_of_char: Vec<char> = Vec::new();
for c in self.start_word.letters.chars() {
vector_of_char.push(c as char);
}
for c in word.chars() {
if c == vector_of_char[index] {
vector_of_letters.push(Letter::FullMatch(c));
vector_of_letters_second.push(Letter::FullMatch(c));
index += 1;
continue;
}
if self.start_word.letters.contains(c) {
vector_of_letters.push(Letter::PartialMatch(c));
vector_of_letters_second.push(Letter::PartialMatch(c));
index += 1;
continue;
}
vector_of_letters.push(Letter::NoMatch(c));
vector_of_letters_second.push(Letter::NoMatch(c));
index += 1;
}
(vector_of_letters,vector_of_letters_second)
}
+}
+
+fn word_size(word: &str) -> usize {
+ let mut counter : usize = 0;
+ for _c in word.chars() {
+ counter += 1
+ }
+ counter
}
fn validate_word(alphabet: &str, word: &str) -> (bool, char) {
let mut result = true;
for c in word.chars() {
if !result {
return (false, c);
} else {
result = false;
}
if alphabet.contains(c) {
result = true;
}
}
(true, ' ')
}
impl fmt::Display for Word {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut result = String::from("");
for temp in &self.letters_enum {
match temp {
Letter::NoMatch(x) => result.push_str(&format!(">{}<", x.to_uppercase()),),
Letter::FullMatch(x) => result.push_str(&format!("[{}]", x.to_uppercase())),
Letter::PartialMatch(x) => result.push_str(&format!("({})", x.to_uppercase())),
Letter::Unknown => result.push_str(&format!("|_|")),
}
}
write!(f,"{}", result)
}
}
impl fmt::Display for Game {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut result = String::from("");
let mut _newline = false;
const LINECHAR: &str = "\n";
for word in self.words.iter() {
if _newline == true {
result.push_str(LINECHAR);
_newline = false;
}
result.push_str(&format!("{}",word).to_string());
_newline = true;
}
write!(f,"{}",result)
}
}
Калин качи решение на 23.11.2022 23:38 (преди почти 3 години)
-// Working version from base test with my own tests running
use std::fmt;
#[derive(Debug)]
pub enum GameStatus {
InProgress,
Won,
Lost,
}
#[derive(Debug)]
pub enum GameError {
NotInAlphabet(char),
WrongLength { expected: usize, actual: usize },
GameIsOver(GameStatus),
}
#[derive(Debug)]
pub struct Game {
pub status: GameStatus,
pub attempts: u8,
pub alphabet: String,
pub start_word: Word,
pub words: Vec<Word>,
// Каквито други полета ви трябват
}
#[derive(Debug)]
enum Letter {
Unknown,
FullMatch(char),
PartialMatch(char),
NoMatch(char),
}
#[derive(Debug)]
pub struct Word {
pub letters: String,
letters_enum: Vec<Letter>,
// Каквито полета ви трябват
}
impl Word {
pub(crate) fn new(letters_to: String, letters_from: Vec<Letter>) -> Self {
Word {letters: letters_to, letters_enum: letters_from}
}
pub fn compare(self, other: &Word) -> bool {
if self.letters.eq(&other.letters) {
return true;
}
return false;
}
}
impl Game {
/// Конструира нова игра с думи/букви от дадената в `alphabet` азбука. Alphabet е просто низ,
/// в който всеки символ е отделна буква, който вероятно искате да си запазите някак за после.
///
/// Подадената дума с `word` трябва да има само букви от тази азбука. Иначе очакваме да върнете
/// `GameError::NotInAlphabet` грешка с първия символ в `word`, който не е от азбуката.
///
/// Началното състояние на играта е `InProgress` а началния брой опити `attempts` е 0.
///
pub fn new(alphabet: &str, word: &str) -> Result<Self, GameError> {
let tuple = validate_word(alphabet,word);
if tuple.0 == false {
return Err(GameError::NotInAlphabet(tuple.1));
}
let mut vector_of_letters: Vec<Letter> = Vec::new();
for c in word.chars() {
vector_of_letters.push(Letter::FullMatch(c));
}
let start_word = Word::new(word.to_string(),vector_of_letters);
let mut vector_of_letters_for_empty: Vec<Letter> = Vec::new();
for _c in word.chars() {
vector_of_letters_for_empty.push(Letter::Unknown);
}
let empty_word = Word::new("".to_string(),vector_of_letters_for_empty);
let mut vector_of_words: Vec<Word> = Vec::new();
vector_of_words.push(empty_word);
Ok(Game {status: GameStatus::InProgress, attempts: 0, alphabet: alphabet.to_string(), start_word: start_word,words: vector_of_words})
}
/// Опитва се да познае търсената дума. Опита е в `guess`.
///
/// Ако играта е приключила, тоест статуса ѝ е `Won` или `Lost`, очакваме да върнете
/// `GameIsOver` със статуса, с който е приключила.
///
/// Ако `guess` има различен брой букви от търсената дума, очакваме да върнете
/// `GameError::WrongLength`. Полето `expected` на грешката трябва да съдържа броя букви на
/// търсената дума, а `actual` да е броя букви на опита `guess`.
///
/// Ако `guess` има правилния брой букви, но има буква, която не е от азбуката на играта,
/// очакваме `GameError::NotInAlphabet` както по-горе, с първия символ от `guess`, който не е
/// от азбуката.
///
/// Метода приема `&mut self`, защото всеки опит се запазва в играта за по-нататък. Метода
/// връща `Word`, което описва освен самите символи на `guess`, и как тези символи са се
/// напаснали на търсената дума. Също така инкрементира `attempts` с 1.
///
/// След опита за напасване на думата, ако всички букви са уцелени на правилните места,
/// очакваме `state` полето да се промени на `Won`. Иначе, ако `attempts` са станали 5,
/// състоянието трябва да е `Lost`.
///
pub fn guess_word(&mut self, guess: &str) -> Result<Word, GameError> {
match self.status {
GameStatus::Lost => return Err(GameError::GameIsOver(GameStatus::Lost)),
GameStatus::Won => return Err(GameError::GameIsOver(GameStatus::Won)),
GameStatus::InProgress => self.guess_word_util(guess),
}
}
fn guess_word_util(&mut self, guess: &str) -> Result<Word, GameError> {
if self.attempts == 5 {
self.status = GameStatus::Lost;
return Err(GameError::GameIsOver(GameStatus::Lost));
}
if word_size(guess) != word_size(&self.start_word.letters) {
return Err(GameError::WrongLength {expected: word_size(&self.start_word.letters), actual: word_size(guess)});
}
let tuple = validate_word(&self.alphabet,guess);
if tuple.0 == false {
return Err(GameError::NotInAlphabet(tuple.1));
}
let letter_enum = self.get_word_vector(guess);
let new_word: Word = Word::new(guess.to_string(), letter_enum.0);
let new_return: Word = Word::new(guess.to_string(), letter_enum.1);
self.words.push(new_word);
self.attempts += 1;
return Ok(new_return);
}
fn get_word_vector(&mut self, word: &str) -> (Vec<Letter>, Vec<Letter>) {
let mut vector_of_letters: Vec<Letter> = Vec::new();
let mut vector_of_letters_second: Vec<Letter> = Vec::new();
let mut index = 0;
let mut vector_of_char: Vec<char> = Vec::new();
for c in self.start_word.letters.chars() {
vector_of_char.push(c as char);
}
for c in word.chars() {
if c == vector_of_char[index] {
vector_of_letters.push(Letter::FullMatch(c));
vector_of_letters_second.push(Letter::FullMatch(c));
index += 1;
continue;
}
if self.start_word.letters.contains(c) {
vector_of_letters.push(Letter::PartialMatch(c));
vector_of_letters_second.push(Letter::PartialMatch(c));
index += 1;
continue;
}
vector_of_letters.push(Letter::NoMatch(c));
vector_of_letters_second.push(Letter::NoMatch(c));
index += 1;
}
(vector_of_letters,vector_of_letters_second)
}
}
fn word_size(word: &str) -> usize {
let mut counter : usize = 0;
for _c in word.chars() {
counter += 1
}
counter
}
fn validate_word(alphabet: &str, word: &str) -> (bool, char) {
let mut result = true;
+ let mut cha : char = '_';
for c in word.chars() {
if !result {
- return (false, c);
+ return (false, cha);
} else {
result = false;
}
if alphabet.contains(c) {
result = true;
}
+ cha = c;
}
(true, ' ')
}
impl fmt::Display for Word {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut result = String::from("");
for temp in &self.letters_enum {
match temp {
Letter::NoMatch(x) => result.push_str(&format!(">{}<", x.to_uppercase()),),
Letter::FullMatch(x) => result.push_str(&format!("[{}]", x.to_uppercase())),
Letter::PartialMatch(x) => result.push_str(&format!("({})", x.to_uppercase())),
Letter::Unknown => result.push_str(&format!("|_|")),
}
}
write!(f,"{}", result)
}
}
impl fmt::Display for Game {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut result = String::from("");
let mut _newline = false;
const LINECHAR: &str = "\n";
for word in self.words.iter() {
if _newline == true {
result.push_str(LINECHAR);
_newline = false;
}
result.push_str(&format!("{}",word).to_string());
_newline = true;
}
write!(f,"{}",result)
}
}
Калин качи решение на 23.11.2022 23:55 (преди почти 3 години)
use std::fmt;
#[derive(Debug)]
pub enum GameStatus {
InProgress,
Won,
Lost,
}
#[derive(Debug)]
pub enum GameError {
NotInAlphabet(char),
WrongLength { expected: usize, actual: usize },
GameIsOver(GameStatus),
}
#[derive(Debug)]
pub struct Game {
pub status: GameStatus,
pub attempts: u8,
pub alphabet: String,
pub start_word: Word,
pub words: Vec<Word>,
// Каквито други полета ви трябват
}
#[derive(Debug)]
enum Letter {
Unknown,
FullMatch(char),
PartialMatch(char),
NoMatch(char),
}
#[derive(Debug)]
pub struct Word {
pub letters: String,
letters_enum: Vec<Letter>,
// Каквито полета ви трябват
}
impl Word {
pub(crate) fn new(letters_to: String, letters_from: Vec<Letter>) -> Self {
Word {letters: letters_to, letters_enum: letters_from}
}
pub fn compare(self, other: &Word) -> bool {
if self.letters.eq(&other.letters) {
return true;
}
return false;
}
}
impl Game {
/// Конструира нова игра с думи/букви от дадената в `alphabet` азбука. Alphabet е просто низ,
/// в който всеки символ е отделна буква, който вероятно искате да си запазите някак за после.
///
/// Подадената дума с `word` трябва да има само букви от тази азбука. Иначе очакваме да върнете
/// `GameError::NotInAlphabet` грешка с първия символ в `word`, който не е от азбуката.
///
/// Началното състояние на играта е `InProgress` а началния брой опити `attempts` е 0.
///
pub fn new(alphabet: &str, word: &str) -> Result<Self, GameError> {
let tuple = validate_word(alphabet,word);
if tuple.0 == false {
return Err(GameError::NotInAlphabet(tuple.1));
}
let mut vector_of_letters: Vec<Letter> = Vec::new();
for c in word.chars() {
vector_of_letters.push(Letter::FullMatch(c));
}
let start_word = Word::new(word.to_string(),vector_of_letters);
let mut vector_of_letters_for_empty: Vec<Letter> = Vec::new();
for _c in word.chars() {
vector_of_letters_for_empty.push(Letter::Unknown);
}
let empty_word = Word::new("".to_string(),vector_of_letters_for_empty);
let mut vector_of_words: Vec<Word> = Vec::new();
vector_of_words.push(empty_word);
Ok(Game {status: GameStatus::InProgress, attempts: 0, alphabet: alphabet.to_string(), start_word: start_word,words: vector_of_words})
}
/// Опитва се да познае търсената дума. Опита е в `guess`.
///
/// Ако играта е приключила, тоест статуса ѝ е `Won` или `Lost`, очакваме да върнете
/// `GameIsOver` със статуса, с който е приключила.
///
/// Ако `guess` има различен брой букви от търсената дума, очакваме да върнете
/// `GameError::WrongLength`. Полето `expected` на грешката трябва да съдържа броя букви на
/// търсената дума, а `actual` да е броя букви на опита `guess`.
///
/// Ако `guess` има правилния брой букви, но има буква, която не е от азбуката на играта,
/// очакваме `GameError::NotInAlphabet` както по-горе, с първия символ от `guess`, който не е
/// от азбуката.
///
/// Метода приема `&mut self`, защото всеки опит се запазва в играта за по-нататък. Метода
/// връща `Word`, което описва освен самите символи на `guess`, и как тези символи са се
/// напаснали на търсената дума. Също така инкрементира `attempts` с 1.
///
/// След опита за напасване на думата, ако всички букви са уцелени на правилните места,
/// очакваме `state` полето да се промени на `Won`. Иначе, ако `attempts` са станали 5,
/// състоянието трябва да е `Lost`.
///
pub fn guess_word(&mut self, guess: &str) -> Result<Word, GameError> {
match self.status {
GameStatus::Lost => return Err(GameError::GameIsOver(GameStatus::Lost)),
GameStatus::Won => return Err(GameError::GameIsOver(GameStatus::Won)),
GameStatus::InProgress => self.guess_word_util(guess),
}
}
fn guess_word_util(&mut self, guess: &str) -> Result<Word, GameError> {
if self.attempts == 5 {
self.status = GameStatus::Lost;
return Err(GameError::GameIsOver(GameStatus::Lost));
}
if word_size(guess) != word_size(&self.start_word.letters) {
return Err(GameError::WrongLength {expected: word_size(&self.start_word.letters), actual: word_size(guess)});
}
let tuple = validate_word(&self.alphabet,guess);
if tuple.0 == false {
return Err(GameError::NotInAlphabet(tuple.1));
}
-
-
-
let letter_enum = self.get_word_vector(guess);
let new_word: Word = Word::new(guess.to_string(), letter_enum.0);
let new_return: Word = Word::new(guess.to_string(), letter_enum.1);
self.words.push(new_word);
self.attempts += 1;
+ if self.attempts == 5 {
+ self.status = GameStatus::Lost;
+ }
+ if guess.eq(&self.start_word.letters.to_string()) {
+ self.status = GameStatus::Won;
+ }
+
return Ok(new_return);
}
fn get_word_vector(&mut self, word: &str) -> (Vec<Letter>, Vec<Letter>) {
let mut vector_of_letters: Vec<Letter> = Vec::new();
let mut vector_of_letters_second: Vec<Letter> = Vec::new();
let mut index = 0;
let mut vector_of_char: Vec<char> = Vec::new();
for c in self.start_word.letters.chars() {
vector_of_char.push(c as char);
}
for c in word.chars() {
if c == vector_of_char[index] {
vector_of_letters.push(Letter::FullMatch(c));
vector_of_letters_second.push(Letter::FullMatch(c));
index += 1;
continue;
}
if self.start_word.letters.contains(c) {
vector_of_letters.push(Letter::PartialMatch(c));
vector_of_letters_second.push(Letter::PartialMatch(c));
index += 1;
continue;
}
vector_of_letters.push(Letter::NoMatch(c));
vector_of_letters_second.push(Letter::NoMatch(c));
index += 1;
}
(vector_of_letters,vector_of_letters_second)
}
}
fn word_size(word: &str) -> usize {
let mut counter : usize = 0;
for _c in word.chars() {
counter += 1
}
counter
}
fn validate_word(alphabet: &str, word: &str) -> (bool, char) {
let mut result = true;
let mut cha : char = '_';
for c in word.chars() {
if !result {
return (false, cha);
} else {
result = false;
}
if alphabet.contains(c) {
result = true;
}
cha = c;
}
(true, ' ')
}
impl fmt::Display for Word {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut result = String::from("");
for temp in &self.letters_enum {
match temp {
Letter::NoMatch(x) => result.push_str(&format!(">{}<", x.to_uppercase()),),
Letter::FullMatch(x) => result.push_str(&format!("[{}]", x.to_uppercase())),
Letter::PartialMatch(x) => result.push_str(&format!("({})", x.to_uppercase())),
Letter::Unknown => result.push_str(&format!("|_|")),
}
}
write!(f,"{}", result)
}
}
impl fmt::Display for Game {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let mut result = String::from("");
let mut _newline = false;
const LINECHAR: &str = "\n";
for word in self.words.iter() {
if _newline == true {
result.push_str(LINECHAR);
_newline = false;
}
result.push_str(&format!("{}",word).to_string());
_newline = true;
}
write!(f,"{}",result)
}
-}
+}