Last active
June 19, 2019 07:52
-
-
Save bitsmanent/0f3facbf56006e7344af844c59cf6364 to your computer and use it in GitHub Desktop.
Build random mazes of arbitrary size and draw them in console
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(() => { | |
/* | |
* 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