|
@@ -0,0 +1,314 @@
|
|
|
|
+use std::{io::stdin, str::FromStr};
|
|
|
|
+enum GameStatus {
|
|
|
|
+ InProgress,
|
|
|
|
+ Win,
|
|
|
|
+ Fail,
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+enum Hanger {
|
|
|
|
+ Base,
|
|
|
|
+ BaseWithPost,
|
|
|
|
+ BaseWithHanger,
|
|
|
|
+ HangedHead,
|
|
|
|
+ HangedTorso,
|
|
|
|
+ HangedRHand,
|
|
|
|
+ HangedLHand,
|
|
|
|
+ HangedRLeg,
|
|
|
|
+ HangedLLeg,
|
|
|
|
+
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+impl Hanger {
|
|
|
|
+ fn draw(&self) -> String{
|
|
|
|
+ match self {
|
|
|
|
+ Hanger::Base => {
|
|
|
|
+ r#"
|
|
|
|
+ ____________
|
|
|
|
+ ___/ \____
|
|
|
|
+ "#.to_owned()
|
|
|
|
+ },
|
|
|
|
+ Hanger::BaseWithPost => {
|
|
|
|
+ r#"
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ |
|
|
|
|
+ |
|
|
|
|
+ |
|
|
|
|
+ |
|
|
|
|
+ |
|
|
|
|
+ ________|___
|
|
|
|
+ ___/ \____
|
|
|
|
+ "#.to_owned()
|
|
|
|
+ },
|
|
|
|
+ Hanger::BaseWithHanger => {
|
|
|
|
+ r#"
|
|
|
|
+
|
|
|
|
+ ________
|
|
|
|
+ | |
|
|
|
|
+ |
|
|
|
|
+ |
|
|
|
|
+ |
|
|
|
|
+ |
|
|
|
|
+ ________|___
|
|
|
|
+ ___/ \____
|
|
|
|
+ "#.to_owned()
|
|
|
|
+ },
|
|
|
|
+ Hanger::HangedHead => {
|
|
|
|
+ r#"
|
|
|
|
+
|
|
|
|
+ ________
|
|
|
|
+ | |
|
|
|
|
+ o |
|
|
|
|
+ |
|
|
|
|
+ |
|
|
|
|
+ |
|
|
|
|
+ ________|___
|
|
|
|
+ ___/ \____
|
|
|
|
+ "#.to_owned()
|
|
|
|
+ },
|
|
|
|
+ Hanger::HangedTorso => {
|
|
|
|
+ r#"
|
|
|
|
+
|
|
|
|
+ ________
|
|
|
|
+ | |
|
|
|
|
+ o |
|
|
|
|
+ | |
|
|
|
|
+ | |
|
|
|
|
+ |
|
|
|
|
+ ________|___
|
|
|
|
+ ___/ \____
|
|
|
|
+ "#.to_owned()
|
|
|
|
+ },
|
|
|
|
+ Hanger::HangedRHand => {
|
|
|
|
+ r#"
|
|
|
|
+
|
|
|
|
+ ________
|
|
|
|
+ | |
|
|
|
|
+ o |
|
|
|
|
+ |\ |
|
|
|
|
+ | |
|
|
|
|
+ |
|
|
|
|
+ ________|___
|
|
|
|
+ ___/ \____
|
|
|
|
+ "#.to_owned()
|
|
|
|
+ },
|
|
|
|
+ Hanger::HangedLHand => {
|
|
|
|
+ r#"
|
|
|
|
+
|
|
|
|
+ ________
|
|
|
|
+ | |
|
|
|
|
+ o |
|
|
|
|
+ /|\ |
|
|
|
|
+ | |
|
|
|
|
+ |
|
|
|
|
+ ________|___
|
|
|
|
+ ___/ \____
|
|
|
|
+ "#.to_owned()
|
|
|
|
+ },
|
|
|
|
+ Hanger::HangedRLeg => {
|
|
|
|
+ r#"
|
|
|
|
+
|
|
|
|
+ ________
|
|
|
|
+ | |
|
|
|
|
+ o |
|
|
|
|
+ /|\ |
|
|
|
|
+ | |
|
|
|
|
+ \ |
|
|
|
|
+ ________|___
|
|
|
|
+ ___/ \____
|
|
|
|
+ "#.to_owned()
|
|
|
|
+ },
|
|
|
|
+ Hanger::HangedLLeg => {
|
|
|
|
+ r#"
|
|
|
|
+
|
|
|
|
+ ________
|
|
|
|
+ | |
|
|
|
|
+ o |
|
|
|
|
+ /|\ |
|
|
|
|
+ | |
|
|
|
|
+ / \ |
|
|
|
|
+ ________|___
|
|
|
|
+ ___/ \____
|
|
|
|
+ "#.to_owned()
|
|
|
|
+ },
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+impl TryFrom<u32> for Hanger {
|
|
|
|
+ type Error = ();
|
|
|
|
+
|
|
|
|
+ fn try_from(v: u32) -> Result<Self, Self::Error> {
|
|
|
|
+ match v {
|
|
|
|
+ x if x == Hanger::Base as u32 => Ok(Hanger::Base),
|
|
|
|
+ x if x == Hanger::BaseWithPost as u32 => Ok(Hanger::BaseWithPost),
|
|
|
|
+ x if x == Hanger::BaseWithHanger as u32 => Ok(Hanger::BaseWithHanger),
|
|
|
|
+ x if x == Hanger::HangedHead as u32 => Ok(Hanger::HangedHead),
|
|
|
|
+ x if x == Hanger::HangedTorso as u32 => Ok(Hanger::HangedTorso),
|
|
|
|
+ x if x == Hanger::HangedRHand as u32 => Ok(Hanger::HangedRHand),
|
|
|
|
+ x if x == Hanger::HangedLHand as u32 => Ok(Hanger::HangedLHand),
|
|
|
|
+ x if x == Hanger::HangedRLeg as u32 => Ok(Hanger::HangedRLeg),
|
|
|
|
+ x if x == Hanger::HangedLLeg as u32 => Ok(Hanger::HangedLLeg),
|
|
|
|
+ _ => Err(()),
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+struct HangedManWord {
|
|
|
|
+ word_vec: Vec<char>,
|
|
|
|
+ input_vec: Vec<char>,
|
|
|
|
+ word: String,
|
|
|
|
+ counter_def: u32,
|
|
|
|
+ counter: u32,
|
|
|
|
+ counter_err: u32,
|
|
|
|
+ hanger_art: Hanger
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+impl HangedManWord {
|
|
|
|
+ fn new(word: String, counter_def: u32) -> Self {
|
|
|
|
+ let word_vec = Vec::from_iter(
|
|
|
|
+ std::iter::repeat('_').take(word.chars().count())
|
|
|
|
+ );
|
|
|
|
+ let input_vec: Vec<char> = Vec::new();
|
|
|
|
+
|
|
|
|
+ HangedManWord {
|
|
|
|
+ word_vec, input_vec, word, counter_def,
|
|
|
|
+ counter: 0, counter_err: 0, hanger_art: Hanger::Base
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ fn check_letter(&mut self, letter: char) -> bool{
|
|
|
|
+ self.input_vec.push(letter);
|
|
|
|
+ let indices: Vec<usize> = self.word.chars().enumerate().map(
|
|
|
|
+ |(index, char)| {
|
|
|
|
+ if char == letter {
|
|
|
|
+ return index + 1
|
|
|
|
+ }
|
|
|
|
+ else {
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ ).filter(
|
|
|
|
+ |item| item != &0
|
|
|
|
+ ).collect::<Vec<usize>>();
|
|
|
|
+
|
|
|
|
+ for index in indices.clone() {
|
|
|
|
+ self.word_vec[index-1] = letter
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ self.counter += 1;
|
|
|
|
+
|
|
|
|
+ if indices.is_empty() {
|
|
|
|
+ self.counter_err += 1;
|
|
|
|
+ self.hanger_art = Hanger::try_from(self.counter_err).unwrap_or(Hanger::Base);
|
|
|
|
+ return false
|
|
|
|
+ }
|
|
|
|
+ true
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ fn check_complete(&self) -> bool {
|
|
|
|
+ !self.word_vec.contains(&'_')
|
|
|
|
+ }
|
|
|
|
+ fn check_status(&self) -> GameStatus {
|
|
|
|
+ if self.counter_def <= self.counter_err {
|
|
|
|
+ return GameStatus::Fail;
|
|
|
|
+ }
|
|
|
|
+ if self.check_complete() {
|
|
|
|
+ return GameStatus::Win;
|
|
|
|
+ }
|
|
|
|
+ GameStatus::InProgress
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+fn input<T: FromStr>(print: String, error_msg: String, type_error_msg: String) -> T {
|
|
|
|
+
|
|
|
|
+ println!("{}", print);
|
|
|
|
+ let result: T;
|
|
|
|
+
|
|
|
|
+ let mut input_buff = String::new();
|
|
|
|
+ loop {
|
|
|
|
+ input_buff.clear();
|
|
|
|
+ match stdin().read_line(&mut input_buff) {
|
|
|
|
+ Ok(_) => {}
|
|
|
|
+ Err(_) => {
|
|
|
|
+ println!("{}", error_msg);
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+ result = match input_buff.trim().parse::<T>() {
|
|
|
|
+ Ok(res) => res,
|
|
|
|
+ Err(_) => {
|
|
|
|
+ println!("{}", type_error_msg);
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+ };
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ result
|
|
|
|
+
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+fn main() {
|
|
|
|
+
|
|
|
|
+ let word: String = input(
|
|
|
|
+ "Введите слово".to_owned(),
|
|
|
|
+ "Повторите ввод".to_owned(),
|
|
|
|
+ "".to_owned()
|
|
|
|
+ );
|
|
|
|
+
|
|
|
|
+ let counter_def: u32 = 8;
|
|
|
|
+ // input(
|
|
|
|
+ // "Введите количество возможных ошибок".to_owned(),
|
|
|
|
+ // "Повторите ввод".to_owned(),
|
|
|
|
+ // "Введите положительное число".to_owned()
|
|
|
|
+ // );
|
|
|
|
+
|
|
|
|
+ let mut hm_word = HangedManWord::new(word,counter_def);
|
|
|
|
+
|
|
|
|
+ for _ in 0..100 {
|
|
|
|
+ println!()
|
|
|
|
+ }
|
|
|
|
+ let mut correct: bool;
|
|
|
|
+ loop {
|
|
|
|
+
|
|
|
|
+ println!("{:}", hm_word.hanger_art.draw());
|
|
|
|
+ println!("Уже введено: {:?}", hm_word.input_vec);
|
|
|
|
+ println!("{:?}", hm_word.word_vec);
|
|
|
|
+
|
|
|
|
+ match hm_word.check_status() {
|
|
|
|
+ GameStatus::Win => {
|
|
|
|
+ println!(
|
|
|
|
+ "Вы ПОБЕДИЛИ. Кол-во введенных букв: {:}. Кол-во ошибок: {:}/{:}",
|
|
|
|
+ hm_word.counter, hm_word.counter_err, hm_word.counter_def
|
|
|
|
+ );
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ GameStatus::Fail => {
|
|
|
|
+ println!(
|
|
|
|
+ "Вы ПРОИГРАЛИ. Загаданные слово: {:} Кол-во введенных букв: {:}. Кол-во ошибок: {:}/{:}",
|
|
|
|
+ hm_word.word, hm_word.counter, hm_word.counter_err, hm_word.counter_def
|
|
|
|
+ );
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ GameStatus::InProgress => ()
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ let letter: char = input(
|
|
|
|
+ "Введите букву".to_owned(),
|
|
|
|
+ "Повторите ввод".to_owned(),
|
|
|
|
+ "Введите одну букву".to_owned()
|
|
|
|
+ );
|
|
|
|
+
|
|
|
|
+ correct = hm_word.check_letter(letter);
|
|
|
|
+ match correct {
|
|
|
|
+ true => println!("✅"),
|
|
|
|
+ false => println!("❎")
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+}
|