Решение на Hangman от Стефан Георгиев

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

Към профила на Стефан Георгиев

Резултати

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

Код

#[cfg(test)]
mod tests {
#[test]
fn it_works() {
assert_eq!(2 + 2, 4);
}
}
use std::str::FromStr;
use std::collections::HashSet;
#[allow(unused_imports)]
use std::fmt::{self, Display, Write};
fn is_alphabetic(s: &str) -> bool{
let mut flag: bool = false;
for c in s.chars(){
if !((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= 'а' && c <= 'я') || (c >= 'А' && c <= 'Я')){
flag = false;
}
else{
flag = true;
}
}
return flag;
}
#[derive(Debug)]
pub enum GameError {
ParseError(String),
BadGuess(String),
InvalidSolution(String),
GameOver,
}
impl Display for GameError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result{
match *self {
GameError::ParseError(ref x) => write!(f, "{}", x),
GameError::BadGuess(ref y) => write!(f, "{}", y),
GameError::InvalidSolution(ref z) => write!(f, "{}", z),
GameError::GameOver => write!(f, "Game Over!"),
}
}
}
#[derive(Debug)]
pub enum Command {
TryLetter(String),
TryWord(String),
Info,
Help,
Quit,
}
impl FromStr for Command{
type Err = GameError;
fn from_str(s: &str) -> Result <Self, Self::Err>{
let temp: Vec<&str> = s.split(' ').collect();
if s.is_empty(){
Err(GameError::ParseError("Invalid input!".to_string()))
}
else if temp.len() == 1{
if s.starts_with("h") || s.starts_with("H"){
Ok(Command::Help)
}
else if s.starts_with("i") || s.starts_with("I"){
Ok(Command::Info)
}
else if s.starts_with("q") || s.starts_with("Q"){
Ok(Command::Quit)
}
else{
Err(GameError::ParseError("Invalid input!".to_string()))
}
}
else{
if temp[0].starts_with("t") || temp[0].starts_with("T"){
if temp[1].starts_with("l") || temp[1].starts_with("L"){
if temp[2].len() != 1{
Err(GameError::BadGuess("You've already tried this!".to_string()))
}
else{
Ok(Command::TryLetter(temp[2].to_string()))
}
}
else if temp[1].starts_with("w") || temp[1].starts_with("W"){
if temp[2].len() == 0{
Err(GameError::BadGuess("You've already tried this!".to_string()))
}
else{
Ok(Command::TryWord(temp[2].to_string()))
}
}
else{
Err(GameError::ParseError("Invalid input!".to_string()))
}
}
else{
Err(GameError::ParseError("Invalid input!".to_string()))
}
}
}
}
pub struct Game{
pub attempted_letters: HashSet<char>,
pub attempted_words: HashSet<String>,
pub opened_letters_index: HashSet<u32>,
pub attempts_remaining: u32,
pub right_word: String,
pub word_length: usize,
pub opened_letters: usize,
pub game_won: bool,
pub display_word: String,
}
impl Game{
pub fn new(solution: &str, attempts: u32) -> Result<Self, GameError>{
let mut counter: usize = 0;
let temp_word_length: usize = solution.chars().count();
let mut temp_display_word: String = "".to_string();
while counter != temp_word_length{
temp_display_word = temp_display_word + "_ ";
counter += 1;
}
if solution.is_empty(){
Err(GameError::InvalidSolution("Wrong answer!".to_string()))
}
else if !is_alphabetic(solution){
Err(GameError::InvalidSolution("Wrong answer!".to_string()))
}
else{
Ok(Game{
attempted_letters: HashSet::new(),
attempted_words: HashSet::new(),
opened_letters_index: HashSet::new(),
attempts_remaining: attempts,
right_word: solution.to_string(),
word_length: solution.chars().count(),
opened_letters: 0,
game_won: false,
display_word: temp_display_word,
})
}
}
pub fn guess_letter(&mut self, guess: char) -> Result<bool, GameError>{
let mut flag: bool = false;
let mut index1: u32 = 0;
let mut index2: u32 = 0;
let mut index3: u32 = 0;
let mut index4: u32 = 0;
let mut temp: String = "".to_string();
let mut temp2: String = "".to_string();
if self.attempted_letters.contains(&guess){
return Err(GameError::BadGuess("You've already tried this!".to_string()));
}
if self.is_over(){
return Err(GameError::GameOver);
}
for x in self.right_word.chars(){
if guess == x{
self.attempted_letters.insert(guess);
flag = true;
if self.word_length == self.opened_letters{
self.game_won = true;
}
self.opened_letters_index.insert(index2);
for c in self.display_word.chars(){
if index1 == (2*index2){
temp.push(x);
}
else{
temp.push(c);
}
index1 += 1;
}
for x in self.right_word.chars(){
if guess == x && !self.opened_letters_index.contains(&index4){
for c in temp.chars(){
if index3 == (2*index4){
temp2.push(x);
}
else{
temp2.push(c);
}
index3 += 1;
}
}
index4 += 1;
}
if temp2.is_empty(){
self.display_word = temp;
}
else{
self.display_word = temp2;
}
return Ok(true);
}
index2 += 1;
}
if !flag{
self.attempts_remaining -= 1;
Ok(false)
}
else{
Ok(true)
}
}
pub fn guess_word(&mut self, guess: &str) -> Result<bool, GameError>{
if self.attempted_words.contains(guess){
return Err(GameError::BadGuess("You've already tried this!".to_string()));
}
if self.is_over(){
Err(GameError::GameOver)
}
else if self.right_word == guess{
self.attempted_words.insert(guess.to_string());
self.game_won = true;
Ok(true)
}
else{
self.attempted_words.insert(guess.to_string());
self.attempts_remaining -= 1;
Ok(false)
}
}
pub fn is_over(&self) -> bool{
if self.attempts_remaining == 0{
return true;
}
else if self.game_won{
return true;
}
else{
return false;
}
}
}
impl Display for Game{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result{
if self.is_over() {
if self.attempts_remaining == 0{
write!(f, "You lost :/\nThe word was: {}", self.right_word)
}
else{
write!(f, "You won! ^_^\nThe word was: {}", self.right_word)
}
}
else{
write!(f, "Attempts Remaining: {}\n Guess: {}", self.attempts_remaining, self.display_word)
}
}
}

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

Compiling solution v0.1.0 (file:///tmp/d20171210-6053-m684ig/solution)
warning: value assigned to `flag` is never read
   --> src/lib.rs:160:5
    |
160 |     flag = true;
    |     ^^^^
    |
    = note: #[warn(unused_assignments)] on by default

warning: value assigned to `flag` is never read
   --> src/lib.rs:160:5
    |
160 |     flag = true;
    |     ^^^^
    |
    = note: #[warn(unused_assignments)] on by default

error[E0308]: mismatched types
   --> tests/solution_test.rs:180:41
    |
180 |     assert_match!(Ok(Command::TryLetter('x')), "try letter x".parse::<Command>());
    |                                         ^^^ expected struct `std::string::String`, found char
    |
    = note: expected type `std::string::String`
               found type `char`

error[E0308]: mismatched types
   --> tests/solution_test.rs:183:41
    |
183 |     assert_match!(Ok(Command::TryLetter('z')), "Try Letter z".parse::<Command>());
    |                                         ^^^ expected struct `std::string::String`, found char
    |
    = note: expected type `std::string::String`
               found type `char`

error[E0308]: mismatched types
   --> tests/solution_test.rs:194:41
    |
194 |     assert_match!(Ok(Command::TryLetter('я')), "try letter я".parse::<Command>());
    |                                         ^^^ expected struct `std::string::String`, found char
    |
    = note: expected type `std::string::String`
               found type `char`

error[E0308]: mismatched types
   --> tests/solution_test.rs:221:41
    |
221 |     assert_match!(Ok(Command::TryLetter('c')), "t l c".parse::<Command>());
    |                                         ^^^ expected struct `std::string::String`, found char
    |
    = note: expected type `std::string::String`
               found type `char`

error[E0308]: mismatched types
   --> tests/solution_test.rs:235:41
    |
235 |     assert_match!(Ok(Command::TryLetter('я')), "try letter я".parse::<Command>());
    |                                         ^^^ expected struct `std::string::String`, found char
    |
    = note: expected type `std::string::String`
               found type `char`

error[E0308]: mismatched types
   --> tests/solution_test.rs:241:41
    |
241 |     assert_match!(Ok(Command::TryLetter('a')), "try letter a b c".parse::<Command>());
    |                                         ^^^ expected struct `std::string::String`, found char
    |
    = note: expected type `std::string::String`
               found type `char`

error[E0308]: mismatched types
   --> tests/solution_test.rs:249:41
    |
249 |     assert_match!(Ok(Command::TryLetter('a')), "tr le a".parse::<Command>());
    |                                         ^^^ expected struct `std::string::String`, found char
    |
    = note: expected type `std::string::String`
               found type `char`

error: aborting due to 7 previous errors

error: Could not compile `solution`.

To learn more, run the command again with --verbose.

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

Стефан качи първо решение на 08.12.2017 02:07 (преди почти 8 години)

Имаш компилационна грешка! Базовия тест не я хваща, понеже е трудно да уловим всички, но виж условието -- TryLetter(char), а не TryLetter(String). Оправи си този проблем, или ще останеш с 0 точки.

Честно да ти кажа аз също на моменти не разбирам какво съм писал в кода, тъй като както винаги всичко ми се изсипва наведнъж и трябваше да пиша задачата ден преди крайния срок. Четирите индекса го оставих така, защото просто заработи и не ми се мислеше как може да стане по-лесно. Иначе за компилационната грешка от проверяващата система ли е, защото при мен базовия тест върви и бях тествал през main и вариант с дума на кирилица и също тръгна.

Знам, че базовия тест минаваше, но е защото този път не успях да вмъкна достатъчно проверки, изглежда. Ако видиш условието, вместо TryLetter(char), си ползвал TryLetter(String), което при какъвто и да е по-обстоен тест, няма как да се компилира. Ще ми се да бях вмъкнал някакси проверка за това, (и всъщност го направих, след като намерих проблема: https://github.com/fmi/rust-homework/commit/c1f075f8f1569e8c5964885df6608d276b274286), но дори и без това, беше си написано в условието. Ако сме сложили определени конкретни типове/сигнатури, очакваме да се използват. Даваме ви колкото свобода можем за internals, но интерфейсите трябва да са 1:1, за да можем да ги тестваме.

В случая съм убеден, че е станало от бързане, и се надявах за 1 ден да успееш да си го поправиш, ама... не стана :). Ще имаш шанс да наваксаш откъм точки, но те съветвам да пробваш да си алокираш време по-отрано следващия път. Rust не е от езиците, в които можеш да напишеш работещо решение в последния момент :).

Да, убедих се, че не е толкова лесно да се напише добро и работещо като цяло решение за 1 ден, а особено като разбрах, че първоначалната ми идея да обхождам string с for както в C++ няма как да се получи, тъй като Rust работел главно с итератори, а не с индекси, пък от друга страна string в Rust разбрах, че е и с UTF-8 encoding, който също не може да се обхожда с индекси, и въобще не ми стана приятно, но уви, пробвах да скалъпя някакво решение, тръгна ми базовия тест (зарадвах се като първокурсник :D ), реших че съм готов и въобще дори не съм обърнал внимание, че съм писал TryLetter(String), вместо TryLetter(char). Иначе да, ще се пробвам да си заделям повече време за писане, стига ФМИ да не ми обърква още повече графиците.