use rand::Rng; use std::fmt; #[derive(Clone, Copy)] struct Cell { neighbors: u8, revealed: bool, flagged: bool, mine: bool, } impl fmt::Display for Cell { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if self.flagged { write!(f, "F")?; } if !self.revealed { write!(f, "+")?; return Ok(()); } if self.mine { write!(f, "M")?; return Ok(()); } if self.neighbors > 0 { write!(f, "{}", self.neighbors)?; } else { write!(f, "_")?; } Ok(()) } } #[derive(Clone)] struct Grid(Vec>); impl fmt::Display for Grid { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { for row in self.0.iter() { for cell in row.iter() { write!(f, " {} ", cell)?; } write!(f, "\n")?; } Ok(()) } } fn mark_neighbors(grid: &mut Grid, x: usize, y: usize) { for row in y.saturating_sub(1)..=y.saturating_add(1) { for col in x.saturating_sub(1)..=x.saturating_add(1) { if x == col && y == row { continue; } let Some(cell) = grid.0.get_mut(row).and_then(|row| row.get_mut(col)) else { continue; }; cell.neighbors += 1; } } } fn plant_mines(grid: &mut Grid, mines: u8) { let mut rng = rand::thread_rng(); let mut mines_left = mines; while mines_left > 0 { let row = rng.gen_range(0..grid.0.len()); let col = rng.gen_range(0..grid.0[0].len()); let cell: &mut Cell = &mut grid.0[row][col]; if !cell.mine { mines_left -= 1; cell.mine = true; mark_neighbors(grid, col, row); } } } fn main() { let mut grid = Grid(vec![ vec![ Cell { neighbors: 0, flagged: false, mine: false, revealed: false, }; 9 ]; 9 ]); plant_mines(&mut grid, 10); println!("{}", grid); }