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