This commit is contained in:
platane
2025-03-23 13:45:30 +01:00
parent be9fca7f10
commit 34d5617f54
5 changed files with 79 additions and 25 deletions

View File

@@ -9,8 +9,6 @@ import { grid } from "./sample";
const freeCells = api.iget_free_cell(g);
console.log(freeCells);
{
const { canvas, draw, highlightCell } = createCanvas(g);
document.body.appendChild(canvas);

View File

@@ -33,6 +33,16 @@ dependencies = [
"wasm-bindgen",
]
[[package]]
name = "console_log"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be8aed40e4edbf4d3b4431ab260b63fdc40f5780a4766824329ea0f1eefe3c0f"
dependencies = [
"log",
"web-sys",
]
[[package]]
name = "js-sys"
version = "0.3.77"
@@ -109,7 +119,9 @@ name = "snk-solver-rust"
version = "1.0.0"
dependencies = [
"console_error_panic_hook",
"console_log",
"js-sys",
"log",
"wasm-bindgen",
"wasm-bindgen-test",
]

View File

@@ -13,6 +13,8 @@ default = ["console_error_panic_hook"]
[dependencies]
wasm-bindgen = "0.2.100"
js-sys = "0.3.77"
console_log = "1.0.0"
log = "0.4"
# The `console_error_panic_hook` crate provides better debugging of panics by
# logging them with `console.error`. This is great for development, but requires

View File

@@ -6,6 +6,9 @@ use js_sys;
use solver::get_free_cell;
use wasm_bindgen::prelude::*;
use log::info;
use log::Level;
#[wasm_bindgen]
extern "C" {
fn alert(s: &str);

View File

@@ -6,13 +6,21 @@ 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();
for x in -1..((grid.width as i8) + 1) {
for x in 0..(grid.width as i8) {
open_list.insert(Point { x, y: 0 });
open_list.insert(Point {
x,
y: (grid.height as i8) - 1,
});
}
for y in 0..(grid.height as i8) {
open_list.insert(Point { x: 0, y });
open_list.insert(Point {
x: (grid.width as i8) - 1,
y,
});
}
open_list.retain(|p| grid.get_cell(&p) <= walkable);
let directions = [
Point { x: 1, y: 0 },
@@ -24,25 +32,9 @@ pub fn get_free_cell(grid: &Grid, walkable: Cell) -> HashSet<Point> {
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);
}
let has_enough_free_exits = {
let mut exit_count = 0;
let mut visited: HashSet<Point> = HashSet::new();
for dir in directions {
let neighbour = Point {
@@ -50,9 +42,56 @@ pub fn get_free_cell(grid: &Grid, walkable: Cell) -> HashSet<Point> {
y: p.y + dir.y,
};
if grid.is_inside(&neighbour)
&& (grid.get_cell(&neighbour) <= walkable)
&& !free.contains(&neighbour)
if !visited.contains(&neighbour)
&& (free.contains(&neighbour) || !grid.is_inside(&neighbour))
{
visited.insert(neighbour);
exit_count += 1;
}
if grid.is_inside(&neighbour) && grid.get_cell(&neighbour) <= walkable {
for alt in [-1, 1] {
let corner = {
if neighbour.x != 0 {
Point {
x: neighbour.x,
y: neighbour.y + alt,
}
} else {
Point {
x: neighbour.x + alt,
y: neighbour.y,
}
}
};
if !visited.contains(&neighbour)
&& !visited.contains(&corner)
&& (free.contains(&corner) || !grid.is_inside(&corner))
{
visited.insert(neighbour);
visited.insert(corner);
exit_count += 1;
}
}
}
}
exit_count >= 2
};
if has_enough_free_exits {
free.insert(p);
for dir in directions {
let neighbour = Point {
x: p.x + dir.x,
y: p.y + dir.y,
};
if !free.contains(&neighbour)
&& grid.is_inside(&neighbour)
&& grid.get_cell(&neighbour) <= walkable
{
open_list.insert(neighbour);
}