console_games/
game_center.rs

1use std::io::{stdin, stdout, Write};
2
3use console::{style, Term};
4
5use crate::{games::*, Play};
6
7pub struct GameCenter;
8
9impl GameCenter {
10    /// returns a list of all games that are available in the game center
11    pub fn games() -> [Box<dyn Play>; 6] {
12        [
13            Box::new(GuessTheWord),
14            Box::new(GuessTheNumber),
15            Box::new(WordType),
16            Box::new(FourInALine),
17            Box::new(TowerOfHanoi),
18            Box::new(MineSweeper),
19        ]
20    }
21
22    /// call this function to start the console game application
23    pub fn enter() {
24        let term = Term::stdout();
25        term.clear_screen().expect("Failed to clear screen");
26
27        println!("{}\n", style("press ctrl + c to exit").red());
28
29        let mut games = Self::games();
30
31        loop {
32            term.set_title("Console Games");
33            let (game_idx_err_msg, game_idx) = match Self::select_game(&games) {
34                Some(value) => value,
35                None => continue,
36            };
37            println!();
38
39            match games.get_mut(game_idx) {
40                Some(game) => {
41                    let name = game.name();
42
43                    term.set_title(name);
44                    term.clear_screen().expect("Failed to clear screen");
45
46                    println!("Welcome to {}!\n", style(name).green());
47                    if let Some(instructions) = game.instructions() {
48                        println!("{}\n", instructions);
49                    }
50
51                    game.start();
52                }
53                None => println!("{}", &game_idx_err_msg),
54            };
55        }
56    }
57
58    fn select_game(games: &[Box<dyn Play>]) -> Option<(String, usize)> {
59        println!("{}", style("Select your game").cyan());
60        for (i, game) in games.iter().enumerate() {
61            println!("{}: {}", i, game.name())
62        }
63        print!("Game number: ");
64        stdout().flush().expect("Flush failed");
65
66        let mut game_idx = String::new();
67        stdin()
68            .read_line(&mut game_idx)
69            .expect("Cannot read game number");
70        let game_idx_err_msg = format!(
71            "Game number must be an integer between {} to {}",
72            0,
73            games.len() - 1,
74        );
75        let game_idx: usize = match game_idx.trim_end().parse() {
76            Ok(idx) => idx,
77            Err(_) => {
78                println!("{}", &game_idx_err_msg);
79                return None;
80            }
81        };
82
83        Some((game_idx_err_msg, game_idx))
84    }
85}