use rand::prelude::*;
use std::{io, io::prelude::*, thread, time::Duration};
const COLORS: [&str; 5] = [
"\x1b[42m", // Green background
"\x1b[41m", // Red background
"\x1b[43m", // Yellow background
"\x1b[44m", // Blue background
"\x1b[47m", // White background
];
const RESET: &str = "\x1b[0m";
const SQUARES: [[&str; 3]; 4] = [
[" ", " 1 ", " "],
[" ", " 2 ", " "],
[" ", " 3 ", " "],
[" ", " 4 ", " "],
];
fn main() {
let mut turns: Vec<i8> = gen_turn_array();
let mut amnt: i8 = 0;
let mut good_answer: bool = true;
let mut playing: bool = true;
let mut high_score: i8 = 0;
show_base("Press enter to start the game".to_string());
let _ = io::stdin().read(&mut [0u8]).unwrap();
while playing {
while good_answer {
show_game(amnt, turns.clone());
amnt += 1;
let mut response: String = String::new();
print!("Enter the sequence: ");
let _ = io::stdout().flush();
io::stdin()
.read_line(&mut response)
.expect("Failed to read from stdin");
if response.trim() == "q" {
println!("Goodbye!");
return;
} else {
if process_response(amnt, turns.clone(), response) {
println!("Good job! Now we add a turn.");
println!("Press enter to continue...");
let _ = io::stdin().read(&mut [0u8]).unwrap();
} else {
if high_score < amnt {
high_score = amnt;
}
println!("Sorry mate, wrong sequence.");
println!("Turns: {}", amnt);
println!("High score: {}", high_score);
good_answer = false;
}
}
}
print!("Wanna play again? (y/n) ");
let mut response: String = String::new();
let _ = io::stdout().flush();
io::stdin()
.read_line(&mut response)
.expect("Failure reading input.");
if response.trim() == "y" {
playing = true;
good_answer = true;
amnt = 0;
turns = gen_turn_array();
} else {
playing = false;
}
}
}
fn gen_turn_array() -> Vec<i8> {
let mut rng = rand::thread_rng();
let mut vec = Vec::with_capacity(255);
for _ in 0..255 {
vec.push(rng.gen_range(1..5));
}
return vec;
}
fn process_response(amnt: i8, turns: Vec<i8>, response: String) -> bool {
for i in 0..amnt {
if let Some(ch) = response.chars().nth(i as usize) {
if let Some(num) = ch.to_digit(10) {
let value_as_i8 = num as i8;
if turns[i as usize] != value_as_i8 {
return false;
}
} else {
println!("The char #{} is not a digit.", i);
return false;
}
} else {
return false;
}
}
return true;
}
fn show_game(amnt: i8, turns: Vec<i8>) {
for i in 0..amnt + 1 {
print!("{esc}[2J{esc}[1;1H", esc = 27 as char); //Clear the screen
println!("============== Simon Game ==============");
let turn: i8 = turns[i as usize];
match turn {
1 => {
println!(
"{}{}{}|{}{}{}|{}{}{}|{}{}{}",
COLORS[4],
SQUARES[0][0],
RESET,
COLORS[1],
SQUARES[1][0],
RESET,
COLORS[2],
SQUARES[2][0],
RESET,
COLORS[3],
SQUARES[3][0],
RESET
);
println!(
"{}{}{}|{}{}{}|{}{}{}|{}{}{}",
COLORS[4],
SQUARES[0][1],
RESET,
COLORS[1],
SQUARES[1][1],
RESET,
COLORS[2],
SQUARES[2][1],
RESET,
COLORS[3],
SQUARES[3][1],
RESET
);
println!(
"{}{}{}|{}{}{}|{}{}{}|{}{}{}",
COLORS[4],
SQUARES[0][2],
RESET,
COLORS[1],
SQUARES[1][2],
RESET,
COLORS[2],
SQUARES[2][2],
RESET,
COLORS[3],
SQUARES[3][2],
RESET
);
}
2 => {
println!(
"{}{}{}|{}{}{}|{}{}{}|{}{}{}",
COLORS[0],
SQUARES[0][0],
RESET,
COLORS[4],
SQUARES[1][0],
RESET,
COLORS[2],
SQUARES[2][0],
RESET,
COLORS[3],
SQUARES[3][0],
RESET
);
println!(
"{}{}{}|{}{}{}|{}{}{}|{}{}{}",
COLORS[0],
SQUARES[0][1],
RESET,
COLORS[4],
SQUARES[1][1],
RESET,
COLORS[2],
SQUARES[2][1],
RESET,
COLORS[3],
SQUARES[3][1],
RESET
);
println!(
"{}{}{}|{}{}{}|{}{}{}|{}{}{}",
COLORS[0],
SQUARES[0][2],
RESET,
COLORS[4],
SQUARES[1][2],
RESET,
COLORS[2],
SQUARES[2][2],
RESET,
COLORS[3],
SQUARES[3][2],
RESET
);
}
3 => {
println!(
"{}{}{}|{}{}{}|{}{}{}|{}{}{}",
COLORS[0],
SQUARES[0][0],
RESET,
COLORS[1],
SQUARES[1][0],
RESET,
COLORS[4],
SQUARES[2][0],
RESET,
COLORS[3],
SQUARES[3][0],
RESET
);
println!(
"{}{}{}|{}{}{}|{}{}{}|{}{}{}",
COLORS[0],
SQUARES[0][1],
RESET,
COLORS[1],
SQUARES[1][1],
RESET,
COLORS[4],
SQUARES[2][1],
RESET,
COLORS[3],
SQUARES[3][1],
RESET
);
println!(
"{}{}{}|{}{}{}|{}{}{}|{}{}{}",
COLORS[0],
SQUARES[0][2],
RESET,
COLORS[1],
SQUARES[1][2],
RESET,
COLORS[4],
SQUARES[2][2],
RESET,
COLORS[3],
SQUARES[3][2],
RESET
);
}
4 => {
println!(
"{}{}{}|{}{}{}|{}{}{}|{}{}{}",
COLORS[0],
SQUARES[0][0],
RESET,
COLORS[1],
SQUARES[1][0],
RESET,
COLORS[2],
SQUARES[2][0],
RESET,
COLORS[4],
SQUARES[3][0],
RESET
);
println!(
"{}{}{}|{}{}{}|{}{}{}|{}{}{}",
COLORS[0],
SQUARES[0][1],
RESET,
COLORS[1],
SQUARES[1][1],
RESET,
COLORS[2],
SQUARES[2][1],
RESET,
COLORS[4],
SQUARES[3][1],
RESET
);
println!(
"{}{}{}|{}{}{}|{}{}{}|{}{}{}",
COLORS[0],
SQUARES[0][2],
RESET,
COLORS[1],
SQUARES[1][2],
RESET,
COLORS[2],
SQUARES[2][2],
RESET,
COLORS[4],
SQUARES[3][2],
RESET
);
}
_ => println!("Error parsing turn."),
}
println!("========================================");
println!("Animating...");
thread::sleep(Duration::from_millis(1000));
}
show_base("Animation finished!".to_string());
}
fn show_base(message: String) {
print!("{esc}[2J{esc}[1;1H", esc = 27 as char); //Clear the screen
println!("============== Simon Game ==============");
println!(
"{}{}{}|{}{}{}|{}{}{}|{}{}{}",
COLORS[0],
SQUARES[0][0],
RESET,
COLORS[1],
SQUARES[1][0],
RESET,
COLORS[2],
SQUARES[2][0],
RESET,
COLORS[3],
SQUARES[3][0],
RESET
);
println!(
"{}{}{}|{}{}{}|{}{}{}|{}{}{}",
COLORS[0],
SQUARES[0][1],
RESET,
COLORS[1],
SQUARES[1][1],
RESET,
COLORS[2],
SQUARES[2][1],
RESET,
COLORS[3],
SQUARES[3][1],
RESET
);
println!(
"{}{}{}|{}{}{}|{}{}{}|{}{}{}",
COLORS[0],
SQUARES[0][2],
RESET,
COLORS[1],
SQUARES[1][2],
RESET,
COLORS[2],
SQUARES[2][2],
RESET,
COLORS[3],
SQUARES[3][2],
RESET
);
println!("========================================");
println!("{}", message);
}