Skip to content

Instantly share code, notes, and snippets.

@bitsmanent
Last active June 19, 2019 07:52
Show Gist options
  • Save bitsmanent/0f3facbf56006e7344af844c59cf6364 to your computer and use it in GitHub Desktop.
Save bitsmanent/0f3facbf56006e7344af844c59cf6364 to your computer and use it in GitHub Desktop.
Build random mazes of arbitrary size and draw them in console
(() => {
/*
* Build mazes of arbitrary size using a randomized version of the Deep-first
* search algorhitm. Cells are accessed using the row/column-major order
* method. Mazes are printed in console.
*
* To understand everything else, start reading main().
*/
"use strict";
var Point = {
North: 0,
South: 1,
East: 2,
West: 3
};
function breakdown(from, to) {
var ft = [];
if(from.xy[0] < to.xy[0])
ft = [Point.East, Point.West];
else if(from.xy[0] > to.xy[0])
ft = [Point.West, Point.East];
else if(from.xy[1] < to.xy[1])
ft = [Point.South, Point.North];
else if(from.xy[1] > to.xy[1])
ft = [Point.North, Point.South];
else
return console.error("breakdown(): unexpected error.");
from.walls[ft[0]] = 0;
to.walls[ft[1]] = 0;
}
function draw(grid) {
var x, y, ci, cell, s = "";
for(x = 0; x < grid.w; ++x) {
cell = grid.cells[x];
s += x ? "_" : " ";
s += cell.walls[Point.North] ? "_" : " ";
}
s += " \n";
for(y = 0; y < grid.h; ++y) {
for(x = 0; x < grid.w; ++x) {
ci = y*grid.w + x;
cell = grid.cells[ci];
if(!x) s += cell.walls[Point.West] ? "|" : " ";
s += cell.walls[Point.South] ? "_" : " ";
s += cell.walls[Point.East] ? "|" : "_";
}
s += "\n";
}
console.log(s);
}
function entrances(grid, n = 2) {
var keys = Object.keys(Point), len = keys.length, skip = {}, p, ci;
while(n > 0) {
p = Point[keys[rand(0, len - 1)]];
switch(p) {
case Point.North: ci = rand(0, grid.w - 1); break;
case Point.South: ci = (grid.h - 1)*grid.w + rand(0, grid.w - 1); break;
case Point.East: ci = (grid.h - 1)*grid.w + grid.w - 1; break;
case Point.West: ci = (grid.h - 1)*grid.w; break;
}
/* only one entrance for cell */
if(skip[ci])
continue;
skip[ci] = 1;
grid.cells[ci].walls[p] = 0;
//grid.entrances.push(ci);
--n;
}
}
function neighbours(grid, cell) {
var ret = [], x, y;
x = cell.xy[0];
y = cell.xy[1];
if(x)
ret.push(grid.cells[y*grid.w + (x-1)]);
if(x+1 < grid.w)
ret.push(grid.cells[y*grid.w + (x+1)]);
if(y)
ret.push(grid.cells[(y-1)*grid.w + x]);
if(y+1 < grid.h)
ret.push(grid.cells[(y+1)*grid.w + x]);
return ret;
}
function newgrid(w, h) {
var grid = {
w: w,
h: h,
size: w * h,
cells: [],
//entrances: []
};
[...Array(grid.size)].forEach((undef, i) => {
var walls = {};
walls[Point.North] = 1;
walls[Point.South] = 1;
walls[Point.East] = 1;
walls[Point.West] = 1;
grid.cells[i] = {
visited: 0,
xy: [i % w, Math.trunc(i / w)],
walls: walls
};
});
return grid;
}
function rand(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function main(w = 15, h = 15) {
var visited = 0, backtrack = [], grid, cur, next;
if(w <= 1 || h <= 1)
return console.log("Size too small.");
grid = newgrid(w, h);
cur = grid.cells[rand(0, grid.size - 1)];
cur.visited = 1;
++visited;
while(visited < grid.size) {
next = neighbours(grid, cur).filter(x => x && !x.visited);
if(next.length) {
next = next[rand(0, next.length - 1)];
backtrack.push(cur);
breakdown(cur, next);
cur = next;
cur.visited = 1;
++visited;
}
else if(backtrack.length) {
cur = backtrack.pop();
}
else
return console.error("main(): unexpected error.");
}
entrances(grid);
draw(grid);
}
window.cmazes = main;
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment