main.rs 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. use std::{io::stdin, str::FromStr};
  2. enum GameStatus {
  3. InProgress,
  4. Win,
  5. Fail,
  6. }
  7. enum Hanger {
  8. Base,
  9. BaseWithPost,
  10. BaseWithHanger,
  11. HangedHead,
  12. HangedTorso,
  13. HangedRHand,
  14. HangedLHand,
  15. HangedRLeg,
  16. HangedLLeg,
  17. }
  18. impl Hanger {
  19. fn draw(&self) -> String{
  20. match self {
  21. Hanger::Base => {
  22. r#"
  23. ____________
  24. ___/ \____
  25. "#.to_owned()
  26. },
  27. Hanger::BaseWithPost => {
  28. r#"
  29. |
  30. |
  31. |
  32. |
  33. |
  34. ________|___
  35. ___/ \____
  36. "#.to_owned()
  37. },
  38. Hanger::BaseWithHanger => {
  39. r#"
  40. ________
  41. | |
  42. |
  43. |
  44. |
  45. |
  46. ________|___
  47. ___/ \____
  48. "#.to_owned()
  49. },
  50. Hanger::HangedHead => {
  51. r#"
  52. ________
  53. | |
  54. o |
  55. |
  56. |
  57. |
  58. ________|___
  59. ___/ \____
  60. "#.to_owned()
  61. },
  62. Hanger::HangedTorso => {
  63. r#"
  64. ________
  65. | |
  66. o |
  67. | |
  68. | |
  69. |
  70. ________|___
  71. ___/ \____
  72. "#.to_owned()
  73. },
  74. Hanger::HangedRHand => {
  75. r#"
  76. ________
  77. | |
  78. o |
  79. |\ |
  80. | |
  81. |
  82. ________|___
  83. ___/ \____
  84. "#.to_owned()
  85. },
  86. Hanger::HangedLHand => {
  87. r#"
  88. ________
  89. | |
  90. o |
  91. /|\ |
  92. | |
  93. |
  94. ________|___
  95. ___/ \____
  96. "#.to_owned()
  97. },
  98. Hanger::HangedRLeg => {
  99. r#"
  100. ________
  101. | |
  102. o |
  103. /|\ |
  104. | |
  105. \ |
  106. ________|___
  107. ___/ \____
  108. "#.to_owned()
  109. },
  110. Hanger::HangedLLeg => {
  111. r#"
  112. ________
  113. | |
  114. o |
  115. /|\ |
  116. | |
  117. / \ |
  118. ________|___
  119. ___/ \____
  120. "#.to_owned()
  121. },
  122. }
  123. }
  124. }
  125. impl TryFrom<u32> for Hanger {
  126. type Error = ();
  127. fn try_from(v: u32) -> Result<Self, Self::Error> {
  128. match v {
  129. x if x == Hanger::Base as u32 => Ok(Hanger::Base),
  130. x if x == Hanger::BaseWithPost as u32 => Ok(Hanger::BaseWithPost),
  131. x if x == Hanger::BaseWithHanger as u32 => Ok(Hanger::BaseWithHanger),
  132. x if x == Hanger::HangedHead as u32 => Ok(Hanger::HangedHead),
  133. x if x == Hanger::HangedTorso as u32 => Ok(Hanger::HangedTorso),
  134. x if x == Hanger::HangedRHand as u32 => Ok(Hanger::HangedRHand),
  135. x if x == Hanger::HangedLHand as u32 => Ok(Hanger::HangedLHand),
  136. x if x == Hanger::HangedRLeg as u32 => Ok(Hanger::HangedRLeg),
  137. x if x == Hanger::HangedLLeg as u32 => Ok(Hanger::HangedLLeg),
  138. _ => Err(()),
  139. }
  140. }
  141. }
  142. struct HangedManWord {
  143. word_vec: Vec<char>,
  144. input_vec: Vec<char>,
  145. word: String,
  146. counter_def: u32,
  147. counter: u32,
  148. counter_err: u32,
  149. hanger_art: Hanger
  150. }
  151. impl HangedManWord {
  152. fn new(word: String, counter_def: u32) -> Self {
  153. let word_vec = Vec::from_iter(
  154. std::iter::repeat('_').take(word.chars().count())
  155. );
  156. let input_vec: Vec<char> = Vec::new();
  157. HangedManWord {
  158. word_vec, input_vec, word, counter_def,
  159. counter: 0, counter_err: 0, hanger_art: Hanger::Base
  160. }
  161. }
  162. fn check_letter(&mut self, letter: char) -> bool{
  163. self.input_vec.push(letter);
  164. let indices: Vec<usize> = self.word.chars().enumerate().map(
  165. |(index, char)| {
  166. if char == letter {
  167. return index + 1
  168. }
  169. else {
  170. return 0;
  171. }
  172. }
  173. ).filter(
  174. |item| item != &0
  175. ).collect::<Vec<usize>>();
  176. for index in indices.clone() {
  177. self.word_vec[index-1] = letter
  178. }
  179. self.counter += 1;
  180. if indices.is_empty() {
  181. self.counter_err += 1;
  182. self.hanger_art = Hanger::try_from(self.counter_err).unwrap_or(Hanger::Base);
  183. return false
  184. }
  185. true
  186. }
  187. fn check_complete(&self) -> bool {
  188. !self.word_vec.contains(&'_')
  189. }
  190. fn check_status(&self) -> GameStatus {
  191. if self.counter_def <= self.counter_err {
  192. return GameStatus::Fail;
  193. }
  194. if self.check_complete() {
  195. return GameStatus::Win;
  196. }
  197. GameStatus::InProgress
  198. }
  199. }
  200. fn input<T: FromStr>(print: String, error_msg: String, type_error_msg: String) -> T {
  201. println!("{}", print);
  202. let result: T;
  203. let mut input_buff = String::new();
  204. loop {
  205. input_buff.clear();
  206. match stdin().read_line(&mut input_buff) {
  207. Ok(_) => {}
  208. Err(_) => {
  209. println!("{}", error_msg);
  210. continue;
  211. }
  212. };
  213. result = match input_buff.trim().parse::<T>() {
  214. Ok(res) => res,
  215. Err(_) => {
  216. println!("{}", type_error_msg);
  217. continue;
  218. }
  219. };
  220. break;
  221. }
  222. result
  223. }
  224. fn main() {
  225. let word: String = input(
  226. "Введите слово".to_owned(),
  227. "Повторите ввод".to_owned(),
  228. "".to_owned()
  229. );
  230. let counter_def: u32 = 8;
  231. // input(
  232. // "Введите количество возможных ошибок".to_owned(),
  233. // "Повторите ввод".to_owned(),
  234. // "Введите положительное число".to_owned()
  235. // );
  236. let mut hm_word = HangedManWord::new(word,counter_def);
  237. for _ in 0..100 {
  238. println!()
  239. }
  240. let mut correct: bool;
  241. loop {
  242. println!("{:}", hm_word.hanger_art.draw());
  243. println!("Уже введено: {:?}", hm_word.input_vec);
  244. println!("{:?}", hm_word.word_vec);
  245. match hm_word.check_status() {
  246. GameStatus::Win => {
  247. println!(
  248. "Вы ПОБЕДИЛИ. Кол-во введенных букв: {:}. Кол-во ошибок: {:}/{:}",
  249. hm_word.counter, hm_word.counter_err, hm_word.counter_def
  250. );
  251. break;
  252. }
  253. GameStatus::Fail => {
  254. println!(
  255. "Вы ПРОИГРАЛИ. Загаданные слово: {:} Кол-во введенных букв: {:}. Кол-во ошибок: {:}/{:}",
  256. hm_word.word, hm_word.counter, hm_word.counter_err, hm_word.counter_def
  257. );
  258. break;
  259. }
  260. GameStatus::InProgress => ()
  261. }
  262. let letter: char = input(
  263. "Введите букву".to_owned(),
  264. "Повторите ввод".to_owned(),
  265. "Введите одну букву".to_owned()
  266. );
  267. correct = hm_word.check_letter(letter);
  268. match correct {
  269. true => println!("✅"),
  270. false => println!("❎")
  271. }
  272. }
  273. }