Решение на Hangman от Иван Велков

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

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

Резултати

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

Код

use std::fmt::{self, Display, Write};
use std::str::FromStr;
use std::collections::HashSet;
#[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(_) => write!(f, "error!"),
GameError::BadGuess(_) => write!(f, "error!"),
GameError::InvalidSolution(_) => write!(f, "error!"),
GameError::GameOver => write!(f, "Хлип, хлип - толкос!"),
}
}
}
#[derive(Debug)]
pub enum Command {
TryLetter(char),
TryWord(String),
Info,
Help,
Quit,
}
impl FromStr for Command {
type Err = GameError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let cmd = s.to_lowercase();
let mut iter = cmd.split_whitespace();
// този код ми дава лошо,
// нямах време да разучавам за по адекватни варианти,
// каквито предполагам има с try! или ? , ама кек
match iter.next() {
Some(arg) => {
match arg.chars().nth(0).unwrap() {
'i' => return Ok(Command::Info),
'h' => return Ok(Command::Help),
'q' => return Ok(Command::Quit),
't' => {
match iter.next() {
Some(kek) => {
match kek.chars().nth(0).unwrap() {
'l' => {
match iter.next() {
Some(val) => {
if val.len() == 1 {
return Ok(Command::TryLetter(val.chars().nth(0).unwrap()))
}
return Err(GameError::ParseError(String::from("kek")))
}
_ => return Err(GameError::ParseError(String::from("kek")))
}
},
'w' => {
match iter.next() {
Some(val) => {
return Ok(Command::TryWord(String::from(val)))
}
_ => return Err(GameError::ParseError(String::from("kek")))
}
},
_ => return Err(GameError::ParseError(String::from("kek")))
}
}
_ => return Err(GameError::ParseError(String::from("kek")))
}
},
_ => return Err(GameError::ParseError(String::from("kek")))
}
},
None => return Err(GameError::ParseError(String::from("kek")))
}
}
}
pub struct Game {
pub attempted_letters: HashSet<char>,
pub attempted_words: HashSet<String>,
pub attempts_remaining: u32,
is_continuing: bool,
answer: String,
letters_remaining: u32
}
impl Game {
pub fn new(solution: &str, attempts: u32) -> Result<Self, GameError> {
if solution.is_empty() || solution.find(|x| char::is_alphabetic(x) == false) != None {
return Err(GameError::InvalidSolution(String::from("kek!")));
}
let mut letters = HashSet::new();
for i in solution.chars() {
letters.insert(i);
}
Ok(Self {
attempted_letters: HashSet::new(),
attempted_words: HashSet::new(),
attempts_remaining: attempts,
is_continuing: attempts != 0,
answer: String::from(solution),
letters_remaining: letters.len() as u32
})
}
pub fn guess_letter(&mut self, guess: char) -> Result<bool, GameError> {
if self.is_over() {
return Err(GameError::GameOver)
}
if self.attempted_letters.insert(guess) {
if self.answer.find(guess) != None {
self.letters_remaining -= 1;
if self.letters_remaining == 0 {
self.is_continuing = false;
}
else {
self.make_turn();
}
return Ok(true)
}
else {
self.make_turn();
return Ok(false)
}
}
Err(GameError::BadGuess(String::from("kek")))
}
pub fn guess_word(&mut self, guess: &str) -> Result<bool, GameError> {
if self.is_over() {
return Err(GameError::GameOver)
}
if self.attempted_words.insert(String::from(guess)) {
if self.answer == guess {
self.is_continuing = false;
return Ok(true)
}
else {
self.make_turn();
return Ok(false)
}
}
Err(GameError::BadGuess(String::from("kek")))
}
pub fn is_over(&self) -> bool {
!self.is_continuing
}
fn make_turn(&mut self) {
self.attempts_remaining -= 1;
self.is_continuing = self.attempts_remaining != 0;
}
}
impl Display for Game {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if self.is_over() {
if self.attempts_remaining == 0 {
return write!(f, "lost {:?}", self.answer)
}
return write!(f, "won {:?}", self.answer)
}
let mut res = String::new();
for i in self.answer.chars() {
if self.attempted_letters.contains(&i) {
res.push(i);
}
else {
res.push('_');
}
res.push(' ');
}
write!(f, "{:?} {:?}", self.attempts_remaining, res)
}
}

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

Compiling solution v0.1.0 (file:///tmp/d20171210-6053-1f9d1m1/solution)
warning: unused import: `Write`
 --> src/lib.rs:1:31
  |
1 | use std::fmt::{self, Display, Write};
  |                               ^^^^^
  |
  = note: #[warn(unused_imports)] on by default

warning: unused import: `Write`
 --> src/lib.rs:1:31
  |
1 | use std::fmt::{self, Display, Write};
  |                               ^^^^^
  |
  = note: #[warn(unused_imports)] on by default

    Finished dev [unoptimized + debuginfo] target(s) in 5.18 secs
     Running target/debug/deps/solution-3f98bfa5c86a5dd9

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

     Running target/debug/deps/solution_test-3d9e4ea2eafbbc82

running 15 tests
test solution_test::test_command_parsing_cyrillic ... FAILED
test solution_test::test_command_parsing_extra_stuff ... ok
test solution_test::test_command_parsing_full_words ... ok
test solution_test::test_command_parsing_partial_words ... ok
test solution_test::test_command_parsing_spacing ... ok
test solution_test::test_command_parsing_special ... FAILED
test solution_test::test_game_basic ... ok
test solution_test::test_game_cyrillic ... ok
test solution_test::test_game_display ... ok
test solution_test::test_game_error ... ok
test solution_test::test_game_guess_basic ... FAILED
test solution_test::test_game_guess_state_lose ... ok
test solution_test::test_game_guess_state_won ... ok
test solution_test::test_game_guess_word ... ok
test solution_test::test_game_over_guesses ... ok

failures:

---- solution_test::test_command_parsing_cyrillic stdout ----
	thread 'solution_test::test_command_parsing_cyrillic' panicked at 'Expected Ok(Command::TryLetter('\u{44f}')) to match Err(ParseError("kek"))', tests/solution_test.rs:235:4
note: Run with `RUST_BACKTRACE=1` for a backtrace.

---- solution_test::test_command_parsing_special stdout ----
	thread 'solution_test::test_command_parsing_special' panicked at 'Expected Ok(Command::TryLetter('\u{44f}')) to match Err(ParseError("kek"))', tests/solution_test.rs:194:4

---- solution_test::test_game_guess_basic stdout ----
	thread 'solution_test::test_game_guess_basic' panicked at 'assertion failed: `(left == right)`
  left: `10`,
 right: `9`', tests/solution_test.rs:84:4


failures:
    solution_test::test_command_parsing_cyrillic
    solution_test::test_command_parsing_special
    solution_test::test_game_guess_basic

test result: FAILED. 12 passed; 3 failed; 0 ignored; 0 measured; 0 filtered out

error: test failed, to rerun pass '--test solution_test'

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

Иван качи първо решение на 08.12.2017 16:41 (преди почти 8 години)

Иван качи решение на 08.12.2017 16:48 (преди почти 8 години)

use std::fmt::{self, Display, Write};
use std::str::FromStr;
use std::collections::HashSet;
#[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(_) => write!(f, "error!"),
GameError::BadGuess(_) => write!(f, "error!"),
GameError::InvalidSolution(_) => write!(f, "error!"),
GameError::GameOver => write!(f, "Хлип, хлип - толкос!"),
}
}
}
#[derive(Debug)]
pub enum Command {
TryLetter(char),
TryWord(String),
Info,
Help,
Quit,
}
impl FromStr for Command {
type Err = GameError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let cmd = s.to_lowercase();
let mut iter = cmd.split_whitespace();
+ // този код ми дава лошо,
+ // нямах време да разучавам за по адекватни варианти,
+ // каквито предполагам има с try! или ? , ама кек
match iter.next() {
Some(arg) => {
match arg.chars().nth(0).unwrap() {
'i' => return Ok(Command::Info),
'h' => return Ok(Command::Help),
'q' => return Ok(Command::Quit),
't' => {
match iter.next() {
Some(kek) => {
match kek.chars().nth(0).unwrap() {
'l' => {
match iter.next() {
Some(val) => {
if val.len() == 1 {
return Ok(Command::TryLetter(val.chars().nth(0).unwrap()))
}
return Err(GameError::ParseError(String::from("kek")))
}
_ => return Err(GameError::ParseError(String::from("kek")))
}
},
'w' => {
match iter.next() {
Some(val) => {
return Ok(Command::TryWord(String::from(val)))
}
_ => return Err(GameError::ParseError(String::from("kek")))
}
},
_ => return Err(GameError::ParseError(String::from("kek")))
}
}
_ => return Err(GameError::ParseError(String::from("kek")))
}
},
_ => return Err(GameError::ParseError(String::from("kek")))
}
},
None => return Err(GameError::ParseError(String::from("kek")))
}
}
}
pub struct Game {
pub attempted_letters: HashSet<char>,
pub attempted_words: HashSet<String>,
pub attempts_remaining: u32,
is_continuing: bool,
answer: String,
letters_remaining: u32
}
impl Game {
pub fn new(solution: &str, attempts: u32) -> Result<Self, GameError> {
if solution.is_empty() || solution.find(|x| char::is_alphabetic(x) == false) != None {
return Err(GameError::InvalidSolution(String::from("kek!")));
}
let mut letters = HashSet::new();
for i in solution.chars() {
letters.insert(i);
}
Ok(Self {
attempted_letters: HashSet::new(),
attempted_words: HashSet::new(),
attempts_remaining: attempts,
is_continuing: attempts != 0,
answer: String::from(solution),
letters_remaining: letters.len() as u32
})
}
pub fn guess_letter(&mut self, guess: char) -> Result<bool, GameError> {
if self.is_over() {
return Err(GameError::GameOver)
}
if self.attempted_letters.insert(guess) {
if self.answer.find(guess) != None {
self.letters_remaining -= 1;
if self.letters_remaining == 0 {
self.is_continuing = false;
}
else {
self.make_turn();
}
return Ok(true)
}
else {
self.make_turn();
return Ok(false)
}
}
Err(GameError::BadGuess(String::from("kek")))
}
pub fn guess_word(&mut self, guess: &str) -> Result<bool, GameError> {
if self.is_over() {
return Err(GameError::GameOver)
}
if self.attempted_words.insert(String::from(guess)) {
if self.answer == guess {
self.is_continuing = false;
return Ok(true)
}
else {
self.make_turn();
return Ok(false)
}
}
Err(GameError::BadGuess(String::from("kek")))
}
pub fn is_over(&self) -> bool {
!self.is_continuing
}
fn make_turn(&mut self) {
self.attempts_remaining -= 1;
self.is_continuing = self.attempts_remaining != 0;
}
}
impl Display for Game {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if self.is_over() {
if self.attempts_remaining == 0 {
return write!(f, "lost {:?}", self.answer)
}
return write!(f, "won {:?}", self.answer)
}
let mut res = String::new();
for i in self.answer.chars() {
if self.attempted_letters.contains(&i) {
res.push(i);
}
else {
res.push('_');
}
res.push(' ');
}
write!(f, "{:?} {:?}", self.attempts_remaining, res)
}
}