#[derive(Clone, Copy)]
pub struct Tile {
value: Option<usize>,
}
impl Tile {
pub fn new_with_value(value: usize) -> Self {
Self { value: Some(value) }
}
pub fn new_empty() -> Self {
Self { value: None }
}
pub fn value(&self) -> Option<usize> {
self.value
}
pub fn is_empty(&self) -> bool {
self.value.is_none()
}
}
#[derive(Clone)]
pub struct Grid {
size: usize,
tiles: Vec<Vec<Tile>>,
}
impl Grid {
pub fn new(size: usize) -> Self {
let tiles = (0..size)
.map(|_| (0..size).map(|_| Tile::new_empty()).collect())
.collect();
Self { size, tiles }
}
pub fn set(&mut self, (x, y): (usize, usize), value: Option<usize>) {
self.tiles[y][x] = if let Some(value) = value {
Tile::new_with_value(value)
} else {
Tile::new_empty()
};
}
pub fn get(&self, (x, y): (usize, usize)) -> Option<&Tile> {
match self.tiles.get(y).map(|row| row.get(x)) {
Some(Some(tile)) => Some(tile),
_ => None,
}
}
pub fn get_val(&self, (x, y): (usize, usize)) -> Option<usize> {
match self.get((x, y)).map(|tile| tile.value()) {
Some(Some(value)) => Some(value),
_ => None,
}
}
pub fn size(&self) -> usize {
self.size
}
pub fn tiles(&self) -> &Vec<Vec<Tile>> {
&self.tiles
}
pub fn move_tile(&mut self, (src_x, src_y): (usize, usize), (dst_x, dst_y): (usize, usize)) {
let src = self.tiles[src_y][src_x];
self.tiles[dst_y][dst_x] = src;
self.tiles[src_y][src_x] = Tile::new_empty();
}
pub fn biggest_value(&self) -> usize {
self.tiles()
.iter()
.filter_map(|row| {
row.iter()
.filter_map(|tile| tile.value())
.reduce(|a, b| a.max(b))
})
.reduce(|a, b| a.max(b))
.unwrap_or(0)
}
}