This commit is contained in:
platane
2025-03-23 11:24:57 +01:00
parent 85e229a04d
commit c0a042d6b4
4 changed files with 140 additions and 66 deletions

View File

@@ -5,10 +5,22 @@ import { grid } from "./sample";
(async () => { (async () => {
const api = await import("@snk/solver-r"); const api = await import("@snk/solver-r");
const g = api.Grid.create(grid.width, grid.height, grid.data); const g = api.IGrid.create(grid.width, grid.height, grid.data);
const { canvas, draw, highlightCell } = createCanvas(g); const freeCells = api.iget_free_cell(g);
document.body.appendChild(canvas);
draw({ width: g.width, height: g.height, data: g.cells }, [] as any, []); console.log(freeCells);
{
const { canvas, draw, highlightCell } = createCanvas(g);
document.body.appendChild(canvas);
draw({ width: g.width, height: g.height, data: g.data }, [] as any, []);
for (let i = freeCells.length / 2; i--; ) {
const x = freeCells[i * 2 + 0];
const y = freeCells[i * 2 + 1];
highlightCell(x, y);
}
}
})(); })();

View File

@@ -0,0 +1,63 @@
#[derive(Copy, Clone, Hash, Eq, PartialEq, Debug)]
pub struct Point {
pub x: u8,
pub y: u8,
}
#[derive(Copy, Clone, Debug, PartialEq)]
#[repr(u8)]
pub enum Cell {
Empty = 0,
Color1 = 1,
Color2 = 2,
Color3 = 3,
Color4 = 4,
}
#[derive(Clone)]
pub struct Grid {
pub width: u8,
pub height: u8,
pub cells: Vec<Cell>,
}
impl Grid {
pub fn create_empty(width: u8, height: u8) -> Grid {
let n = (width as usize) * (height as usize);
let cells = (0..n).map(|_| Cell::Empty).collect();
Grid {
width,
height,
cells,
}
}
pub fn get_index(&self, x: u8, y: u8) -> usize {
return (x as usize) * (self.height as usize) + (y as usize);
}
pub fn get_cell(&self, p: &Point) -> Cell {
let i = self.get_index(p.x, p.y);
return self.cells[i];
}
pub fn set_cell(&mut self, p: &Point, value: Cell) -> () {
let i = self.get_index(p.x, p.y);
self.cells[i] = value;
}
}
#[test]
fn it_should_grid_create() {
let grid = Grid::create_empty(30, 10);
assert_eq!(grid.width, 30);
assert_eq!(grid.height, 10);
assert_eq!(grid.get_cell(&Point { x: 2, y: 3 }), Cell::Empty);
}
#[test]
fn it_should_grid_setter() {
let mut grid = Grid::create_empty(20, 10);
grid.set_cell(&Point { x: 12, y: 3 }, Cell::Color1);
assert_eq!(grid.get_cell(&Point { x: 12, y: 3 }), Cell::Color1);
}

View File

@@ -1,4 +1,9 @@
mod grid;
mod solver;
use grid::{Cell, Grid};
use js_sys; use js_sys;
use solver::get_free_cell;
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
#[wasm_bindgen] #[wasm_bindgen]
@@ -11,45 +16,17 @@ pub fn greet() {
alert("Hello, wasm-game-of-life!"); alert("Hello, wasm-game-of-life!");
} }
#[derive(Copy, Clone)]
pub struct Point {
x: i8,
y: i8,
}
#[wasm_bindgen]
#[derive(Copy, Clone, Debug, PartialEq)]
#[repr(u8)]
pub enum Cell {
Empty = 0,
Color1 = 1,
Color2 = 2,
Color3 = 3,
Color4 = 4,
Color5 = 5,
}
#[wasm_bindgen] #[wasm_bindgen]
#[derive(Clone)] #[derive(Clone)]
pub struct Grid { pub struct IGrid {
pub width: i8, pub width: u8,
pub height: i8, pub height: u8,
cells: Vec<Cell>, cells: Vec<Cell>,
} }
#[wasm_bindgen] #[wasm_bindgen]
impl Grid { impl IGrid {
pub fn create_empty(width: i8, height: i8) -> Grid { pub fn create(width: u8, height: u8, data: js_sys::Uint8Array) -> IGrid {
let n = (width as usize) * (height as usize);
let cells = (0..n).map(|_| Cell::Empty).collect();
Grid {
width,
height,
cells,
}
}
pub fn create(width: i8, height: i8, data: js_sys::Uint8Array) -> Grid {
let cells = data let cells = data
.to_vec() .to_vec()
.iter() .iter()
@@ -59,12 +36,11 @@ impl Grid {
2 => Cell::Color2, 2 => Cell::Color2,
3 => Cell::Color3, 3 => Cell::Color3,
4 => Cell::Color4, 4 => Cell::Color4,
5 => Cell::Color5,
_ => panic!("unknown cell"), _ => panic!("unknown cell"),
}) })
.collect(); .collect();
Grid { IGrid {
width, width,
height, height,
cells, cells,
@@ -72,40 +48,29 @@ impl Grid {
} }
#[wasm_bindgen(getter)] #[wasm_bindgen(getter)]
pub fn cells(&self) -> js_sys::Uint8Array { pub fn data(&self) -> js_sys::Uint8Array {
let o: Vec<u8> = self.cells.iter().map(|u| *u as u8).collect(); let o: Vec<u8> = self.cells.iter().map(|u| *u as u8).collect();
js_sys::Uint8Array::from(&o[..]) js_sys::Uint8Array::from(&o[..])
} }
} }
type Snake = [Point; 5]; impl From<IGrid> for Grid {
fn from(value: IGrid) -> Self {
pub fn get_index(grid: &Grid, x: i8, y: i8) -> usize { Self {
return (x as usize) * (grid.height as usize) + (y as usize); width: value.width,
height: value.height,
cells: value.cells,
}
}
} }
pub fn get_cell(grid: &Grid, p: &Point) -> Cell { #[wasm_bindgen]
let i = get_index(grid, p.x, p.y); pub fn iget_free_cell(grid: &IGrid) -> js_sys::Uint8Array {
return grid.cells[i]; let g = Grid::from(grid.clone());
}
pub fn set_cell(grid: &mut Grid, p: &Point, value: Cell) -> () {
let i = get_index(&grid, p.x, p.y);
grid.cells[i] = value;
}
#[test] let out = get_free_cell(&g, Cell::Color1);
fn grid_create() {
let grid = Grid::create_empty(30, 10);
assert_eq!(grid.width, 30); let o: Vec<u8> = out.iter().flat_map(|p| [p.x, p.y]).collect();
assert_eq!(grid.height, 10);
assert_eq!(get_cell(&grid, &Point { x: 2, y: 3 }), Cell::Empty); js_sys::Uint8Array::from(&o[..])
}
#[test]
fn grid_setter() {
let mut grid = Grid::create_empty(20, 10);
set_cell(&mut grid, &Point { x: 12, y: 3 }, Cell::Color1);
assert_eq!(get_cell(&grid, &Point { x: 12, y: 3 }), Cell::Color1);
} }

View File

@@ -0,0 +1,34 @@
use std::collections::HashSet;
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
}
open_list
}
#[test]
fn it_should_collect_free_cell() {
let mut grid = Grid::create_empty(2, 2);
grid.set_cell(&Point { x: 1, y: 1 }, Cell::Color2);
let free_cells = get_free_cell(&grid, Cell::Color1);
assert_eq!(
free_cells,
HashSet::from([
//
Point { x: 0, y: 0 }
])
);
}