105 lines
2.6 KiB
JavaScript
105 lines
2.6 KiB
JavaScript
|
function get_neighbors(maze, x, y) {
|
||
|
let neighbor_indices = [];
|
||
|
if (!maze[y][x].left && x > 0) {
|
||
|
neighbor_indices.push([x-1,y]);
|
||
|
}
|
||
|
if (!maze[y][x].right && x < maze[0].length-1) {
|
||
|
neighbor_indices.push([x+1,y]);
|
||
|
}
|
||
|
if (!maze[y][x].top && y > 0) {
|
||
|
neighbor_indices.push([x,y-1]);
|
||
|
}
|
||
|
if (!maze[y][x].bottom && y < maze.length-1) {
|
||
|
neighbor_indices.push([x,y+1]);
|
||
|
}
|
||
|
return neighbor_indices;
|
||
|
}
|
||
|
|
||
|
function new_cell() {
|
||
|
return {
|
||
|
left: false,
|
||
|
right: false,
|
||
|
top: false,
|
||
|
bottom: false
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function generate_maze(n) {
|
||
|
let grid = new Array(n).fill().map((x) => (new Array(n).fill().map(new_cell)));
|
||
|
|
||
|
let point_sets = [];
|
||
|
for (let i = 0; i < n; i++) {
|
||
|
for (let j = 0; j < n; j++) {
|
||
|
point_sets.push(new JSONSet([j,i]))
|
||
|
}
|
||
|
}
|
||
|
|
||
|
let edges = [];
|
||
|
for (let i = 0; i < n; i++) {
|
||
|
for (let j = 0; j < n; j++) {
|
||
|
if (i !== n-1) {
|
||
|
edges.push([[i,j],[i+1,j]])
|
||
|
}
|
||
|
if (j !== n-1) {
|
||
|
edges.push([[i,j],[i,j+1]])
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
shuffle_array(edges);
|
||
|
|
||
|
let maze_edges = edges.map((x) => x);
|
||
|
|
||
|
while (edges.length) {
|
||
|
let edge = edges.pop();
|
||
|
|
||
|
let set_inds = edge.map((i) => point_sets.findIndex((x) => x.apply_set_function('has', i)));
|
||
|
if (set_inds[0] == -1 || set_inds[1] == -1) {
|
||
|
throw new Error("Could not find correct index");
|
||
|
}
|
||
|
if (set_inds[0] == set_inds[1]) {
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
// Perform the union of the sets
|
||
|
for (let i of point_sets[set_inds[1]].items) {
|
||
|
point_sets[set_inds[0]].items.add(i);
|
||
|
}
|
||
|
|
||
|
point_sets.splice(set_inds[1], 1);
|
||
|
maze_edges = maze_edges.filter((x) => x !== edge);
|
||
|
}
|
||
|
maze_edges.forEach((edge) => {
|
||
|
let direction = sub(edge[0], edge[1]);
|
||
|
if (direction[0] == -1) {
|
||
|
grid[edge[0][1]][edge[0][0]].right = grid[edge[1][1]][edge[1][0]].left = true;
|
||
|
}
|
||
|
else if (direction[1] == -1) {
|
||
|
grid[edge[0][1]][edge[0][0]].bottom = grid[edge[1][1]][edge[1][0]].top = true;
|
||
|
}
|
||
|
})
|
||
|
return grid;
|
||
|
}
|
||
|
|
||
|
function solve_maze(maze, x, y, end_x, end_y) {
|
||
|
let path = new JSONHash();
|
||
|
let visited = new JSONSet();
|
||
|
let queue = [[x,y]];
|
||
|
while (queue.length) {
|
||
|
let cell = queue.shift();
|
||
|
visited.apply_set_function('add', cell);
|
||
|
if (cell[0] == end_x && cell[1] == end_y) {
|
||
|
let sol_path = [[end_x, end_y]];
|
||
|
while (sol_path[0][0] != x || sol_path[0][1] != y) {
|
||
|
sol_path.unshift(path.get_value(sol_path[0]));
|
||
|
}
|
||
|
return sol_path;
|
||
|
}
|
||
|
for (let i of get_neighbors(maze, cell[0], cell[1])) {
|
||
|
if (!visited.apply_set_function('has', i)) {
|
||
|
queue.push(i);
|
||
|
path.set_value(i, cell);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|