.
This commit is contained in:
@@ -1,10 +1,10 @@
|
||||
#[derive(Copy, Clone, Hash, Eq, PartialEq, Debug)]
|
||||
pub struct Point {
|
||||
pub x: u8,
|
||||
pub y: u8,
|
||||
pub x: i8,
|
||||
pub y: i8,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, PartialOrd)]
|
||||
#[repr(u8)]
|
||||
pub enum Cell {
|
||||
Empty = 0,
|
||||
@@ -32,7 +32,7 @@ impl Grid {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_index(&self, x: u8, y: u8) -> usize {
|
||||
pub fn get_index(&self, x: i8, y: i8) -> usize {
|
||||
return (x as usize) * (self.height as usize) + (y as usize);
|
||||
}
|
||||
pub fn get_cell(&self, p: &Point) -> Cell {
|
||||
@@ -43,8 +43,18 @@ impl Grid {
|
||||
let i = self.get_index(p.x, p.y);
|
||||
self.cells[i] = value;
|
||||
}
|
||||
pub fn is_inside(&self, p: &Point) -> bool {
|
||||
p.x >= 0 && p.x < (self.width as i8) && p.y >= 0 && p.y < (self.height as i8)
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn it_should_sort_cell() {
|
||||
assert_eq!(Cell::Empty < Cell::Color1, true);
|
||||
assert_eq!(Cell::Color1 < Cell::Color2, true);
|
||||
assert_eq!(Cell::Color2 < Cell::Color3, true);
|
||||
assert_eq!(Cell::Color3 < Cell::Color4, true);
|
||||
}
|
||||
#[test]
|
||||
fn it_should_grid_create() {
|
||||
let grid = Grid::create_empty(30, 10);
|
||||
|
||||
@@ -70,7 +70,7 @@ pub fn iget_free_cell(grid: &IGrid) -> js_sys::Uint8Array {
|
||||
|
||||
let out = get_free_cell(&g, Cell::Color1);
|
||||
|
||||
let o: Vec<u8> = out.iter().flat_map(|p| [p.x, p.y]).collect();
|
||||
let o: Vec<u8> = out.iter().flat_map(|p| [p.x as u8, p.y as u8]).collect();
|
||||
|
||||
js_sys::Uint8Array::from(&o[..])
|
||||
}
|
||||
|
||||
@@ -5,15 +5,62 @@ use crate::grid::{Cell, Grid, Point};
|
||||
pub fn get_free_cell(grid: &Grid, walkable: Cell) -> HashSet<Point> {
|
||||
let mut free: HashSet<Point> = HashSet::new();
|
||||
let mut open_list: HashSet<Point> = HashSet::new();
|
||||
let mut changed = true;
|
||||
|
||||
open_list.insert(Point { x: 0, y: 0 });
|
||||
|
||||
while changed {
|
||||
changed = false
|
||||
for x in -1..((grid.width as i8) + 1) {
|
||||
open_list.insert(Point { x, y: 0 });
|
||||
open_list.insert(Point {
|
||||
x,
|
||||
y: (grid.height as i8) - 1,
|
||||
});
|
||||
}
|
||||
|
||||
open_list
|
||||
let directions = [
|
||||
Point { x: 1, y: 0 },
|
||||
Point { x: -1, y: 0 },
|
||||
Point { x: 0, y: 1 },
|
||||
Point { x: 0, y: -1 },
|
||||
];
|
||||
|
||||
while let Some(p) = open_list.iter().next().cloned() {
|
||||
open_list.remove(&p);
|
||||
|
||||
let exit_count: u8 = directions.iter().fold(0, |sum, dir| {
|
||||
let neighbour = Point {
|
||||
x: p.x + dir.x,
|
||||
y: p.y + dir.y,
|
||||
};
|
||||
|
||||
if !grid.is_inside(&neighbour) {
|
||||
sum + 2
|
||||
} else if free.contains(&neighbour) {
|
||||
sum + 1
|
||||
} else {
|
||||
sum
|
||||
}
|
||||
});
|
||||
|
||||
if exit_count >= 2 {
|
||||
if grid.is_inside(&p) && grid.get_cell(&p) <= walkable {
|
||||
free.insert(p);
|
||||
}
|
||||
|
||||
for dir in directions {
|
||||
let neighbour = Point {
|
||||
x: p.x + dir.x,
|
||||
y: p.y + dir.y,
|
||||
};
|
||||
|
||||
if grid.is_inside(&neighbour)
|
||||
&& (grid.get_cell(&neighbour) <= walkable)
|
||||
&& !free.contains(&neighbour)
|
||||
{
|
||||
open_list.insert(neighbour);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -28,7 +75,9 @@ fn it_should_collect_free_cell() {
|
||||
free_cells,
|
||||
HashSet::from([
|
||||
//
|
||||
Point { x: 0, y: 0 }
|
||||
Point { x: 0, y: 0 },
|
||||
Point { x: 0, y: 1 },
|
||||
Point { x: 1, y: 0 },
|
||||
])
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user