Skip to content

Instantly share code, notes, and snippets.

@BrandonDyer64
Created August 30, 2019 22:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save BrandonDyer64/4699b545908470dc1950a51648bc8144 to your computer and use it in GitHub Desktop.
Save BrandonDyer64/4699b545908470dc1950a51648bc8144 to your computer and use it in GitHub Desktop.
extern crate rand;
use rand::prelude::*;
use std::io::{self, Write};
#[derive(PartialEq, Debug, Clone, Copy)]
enum Cell {
Covered(bool),
Revealed(u8)
}
fn main() {
let width = 16;
let height = 16;
let num_mines = 32;
let mut board = build_board(width, height, num_mines);
loop {
print_board(&board, width, false);
if check_win(&board) {
println!("WIN!");
::std::process::exit(0);
}
make_move(&mut board, width as isize, height as isize);
}
}
fn build_board(width: usize, height: usize, num_mines: i32) -> Vec<Cell> {
let mut board = vec![Cell::Covered(false); width * height];
let mut rng = rand::thread_rng();
for _ in 0..num_mines {
let choice = rng.gen::<usize>() % (width * height);
board[choice] = Cell::Covered(true);
}
let width = width as isize;
let height = height as isize;
let x = width / 2;
let y = height / 2;
for y in y-1isize..y+2isize {
for x in x-1isize..x+2isize {
if 0 > y || y > height - 1 { continue; }
if 0 > x || x > width - 1 { continue; }
board[(x + y * width) as usize] = Cell::Covered(false);
}
}
apply_move(&mut board, width / 2, height / 2, width, height);
board
}
fn print_board(board: &Vec<Cell>, width: usize, revealed: bool) {
print!("\n ");
for x in 1 .. width + 1 {
print!("{:>2}", x);
}
println!();
for i in 0..board.len() {
if (i) % width == 0 {
print!("{:>2} ", i / width + 1);
}
let out: String = match board[i] {
Cell::Covered(is_mine) if revealed && is_mine => "◉".into(),
Cell::Covered(is_mine) if revealed && !is_mine => "◌".into(),
Cell::Covered(_) => "□".into(),
Cell::Revealed(num) if num != 0 => num.to_string(),
Cell::Revealed(_) => "·".into(),
};
print!("{} ", out);
if (i + 1) % width == 0 {
println!();
}
}
println!();
}
fn check_win(board: &Vec<Cell>) -> bool {
for cell in board {
if let Cell::Covered(is_mine) = cell {
if !is_mine {
return false;
}
}
}
true
}
fn make_move(board: &mut Vec<Cell>, width: isize, height: isize) {
let x = get_user_input("X".into());
let y = get_user_input("Y".into());
if 0 > x || x > width - 1 || 0 > y || y > height - 1 {
println!("out of bounds");
return;
}
apply_move(board, x, y, width, height);
}
fn apply_move(board: &mut Vec<Cell>, x: isize, y: isize, width: isize, height: isize) {
let index = x + y * width;
if let Cell::Covered(is_mine) = board[index as usize] {
if is_mine {
println!("BOOM!");
print_board(board, width as usize, true);
::std::process::exit(0);
}
let mut count = 0;
for y in y-1isize..y+2isize {
for x in x-1isize..x+2isize {
if 0 > y || y > height - 1 { continue; }
if 0 > x || x > width - 1 { continue; }
if let Cell::Covered(is_mine) = board[(x + y * width) as usize] {
if is_mine {
count += 1;
}
}
}
}
board[index as usize] = Cell::Revealed(count);
if count == 0 {
for y in y-1isize..y+2isize {
for x in x-1isize..x+2isize {
if 0 > y || y > height - 1 { continue; }
if 0 > x || x > width - 1 { continue; }
apply_move(board, x, y, width, height);
}
}
}
};
}
fn get_user_input(name: String) -> isize {
let mut input = String::new();
print!("{}: ", name);
io::stdout().flush().ok().expect("Could not flush stdout");
io::stdin().read_line(&mut input).expect("failed to read");
match input.trim().parse::<isize>() {
Ok(x) => x - 1,
Err(_) => {
println!("Please enter an integer");
get_user_input(name)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment