Skip to content

Instantly share code, notes, and snippets.

@shawnco
Last active May 7, 2022 23:35
Show Gist options
  • Save shawnco/504944d2a2d005fc2961aea195dab593 to your computer and use it in GitHub Desktop.
Save shawnco/504944d2a2d005fc2961aea195dab593 to your computer and use it in GitHub Desktop.
Depth-first Javascript maze generation
/* Assumes HTML file with <canvas id='maze' width='500' height='500'></canvas>
Also assumes the body bg color is black, canvas bg color is white */
const UNIT = 25;
const GRID = 20;
class Cell {
constructor(x,y) {
this.x = x; this.y=y;
this.visited = false;
// TOP, RIGHT, BTM, LEFT
// HAS IT BEEN VISITED?
this.neighbors = [null, null, null, null];
this.hasWall = [true, true, true, true];
}
assignNeighbors(cells) {
if (this.x > 0) {
const find = cells.find(c => c.x == this.x-1 && c.y == this.y);
if (find) this.neighbors[3] = find;
}
if (this.x < GRID-1) {
const find = cells.find(c => c.x == this.x+1 && c.y == this.y);
if (find) this.neighbors[1] = find;
}
if (this.y > 0) {
const find = cells.find(c => c.y == this.y-1 && c.x == this.x);
if (find) this.neighbors[0] = find;
}
if (this.y < GRID-1) {
const find = cells.find(c => c.y == this.y+1 && c.x == this.x);
if (find) this.neighbors[2] = find;
}
}
draw(ctx) {
if (this.hasWall[0]) {
ctx.beginPath();
ctx.moveTo(this.x*UNIT, this.y*UNIT);
ctx.lineTo(this.x*UNIT+UNIT, this.y*UNIT);
ctx.stroke();
}
if (this.hasWall[1]) {
ctx.beginPath();
ctx.moveTo(this.x*UNIT+UNIT, this.y*UNIT);
ctx.lineTo(this.x*UNIT+UNIT, this.y*UNIT+UNIT);
ctx.stroke();
}
if (this.hasWall[2]) {
ctx.beginPath();
ctx.moveTo(this.x*UNIT, this.y*UNIT+UNIT);
ctx.lineTo(this.x*UNIT+UNIT, this.y*UNIT+UNIT);
ctx.stroke();
}
if (this.hasWall[3]) {
ctx.beginPath();
ctx.moveTo(this.x*UNIT, this.y*UNIT);
ctx.lineTo(this.x*UNIT, this.y*UNIT+UNIT);
ctx.stroke();
}
}
}
const ctx = document.getElementById('maze').getContext('2d');
const cells = [];
[...Array(GRID).keys()].map(x => {
console.log(x);
[...Array(GRID).keys()].map(y => {
cells.push(new Cell(x,y));
});
});
// now assign the neighbors array
cells.map(c => c.assignNeighbors(cells));
function buildRecursive(cell, wallIndex) {
cell.visited = true;
cell.hasWall[(wallIndex + 2) % 4] = false;
let unvisitedNeighborIndices = [];
cell.neighbors.map((n, i) => {
if (n && !n.visited) unvisitedNeighborIndices.push(i);
});
while (unvisitedNeighborIndices.length) {
const nextCellIndex = unvisitedNeighborIndices[Math.floor(Math.random()*unvisitedNeighborIndices.length)];
cell.hasWall[nextCellIndex] = false;
buildRecursive(cell.neighbors[nextCellIndex], nextCellIndex);
unvisitedNeighborIndices = [];
cell.neighbors.map((n, i) => {
if (n && !n.visited) unvisitedNeighborIndices.push(i);
});
}
}
buildRecursive(cells[0], 0)
cells.map(c => c.draw(ctx));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment