use std::ops::{Index, IndexMut};
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)]
pub struct Point {
pub x: usize,
pub y: usize,
}
impl Point {
pub fn new(x: usize, y: usize) -> Self {
Self { x, y }
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Cell {
Blocked,
Free,
Path,
}
#[derive(Debug, Clone)]
pub struct Grid {
width: usize,
height: usize,
cells: Vec<Cell>,
}
impl Grid {
pub fn new(width: usize, height: usize, initial_cell: Cell) -> Self {
Self {
width,
height,
cells: vec![initial_cell; width * height],
}
}
pub fn width(&self) -> usize {
self.width
}
pub fn height(&self) -> usize {
self.height
}
pub fn neighbors(&self, point: Point) -> impl Iterator<Item = Point> + '_ {
[(-1, 0), (1, 0), (0, -1), (0, 1)] .iter()
.filter_map(move |&(dx, dy)| {
let nx = point.x as isize + dx;
let ny = point.y as isize + dy;
if nx >= 0 && nx < self.width as isize && ny >= 0 && ny < self.height as isize {
let neighbor_point = Point::new(nx as usize, ny as usize);
if self[neighbor_point] != Cell::Blocked {
return Some(neighbor_point);
}
}
None
})
}
}
impl Index<Point> for Grid {
type Output = Cell;
fn index(&self, point: Point) -> &Self::Output {
&self.cells[point.y * self.width + point.x]
}
}
impl IndexMut<Point> for Grid {
fn index_mut(&mut self, point: Point) -> &mut Self::Output {
&mut self.cells[point.y * self.width + point.x]
}
}