console_games/games/
tower_of_hanoi.rs1use self::internal::PromptDiskMoveResult;
2use crate::Play;
3use console::Term;
4use std::io::{stdin, stdout, Write};
5mod internal;
6
7pub struct TowerOfHanoi;
8
9impl TowerOfHanoi {
10 fn prompt_disk_count(&self) -> usize {
11 let default: usize = 3;
12 loop {
13 print!("Enter disk count (left empty for default of {default}): ");
14 stdout().flush().expect("Failed to flush stdout");
15 let mut input = String::new();
16 stdin().read_line(&mut input).expect("Failed to read line");
17 if input.trim().is_empty() {
18 break default;
19 }
20 let Ok(count) = input.trim().parse() else { continue };
21 break count;
22 }
23 }
24}
25
26impl Play for TowerOfHanoi {
27 fn name(&self) -> &'static str {
28 "Tower of Hanoi"
29 }
30
31 fn instructions(&self) -> Option<&'static str> {
32 Some(
33 "The objective of the game is to move all the disks from the leftmost tower to the rightmost tower.\nA larger disk cannot be placed on top of a smaller disk."
34 )
35 }
36
37 fn start(&self) {
38 let term = Term::stdout();
39 let disk_count = self.prompt_disk_count();
40 let mut game = internal::TowerOfHanoi::new(disk_count);
41
42 loop {
43 term.clear_screen().expect("Failed to clear screen");
44 game.render();
45
46 if let Ok(PromptDiskMoveResult { from, to }) = game.prompt_disk_move() {
47 if game.move_disk(from, to).is_err() {
48 term.clear_screen().expect("Failed to clear screen");
49 continue;
50 }
51 } else {
52 term.clear_screen().expect("Failed to clear screen");
53 continue;
54 }
55
56 if game.win() {
57 term.clear_screen().expect("Failed to clear screen");
58 game.render();
59 println!("You win!\n");
60 break;
61 }
62 }
63 }
64}