UNPKG

@0-harshit-0/maze-generator-and-solver

Version:

Generate maze using randomized DFS and Solve it using Path Finding algorithms

233 lines (211 loc) 5.54 kB
class Stack { constructor() { this.stackarray = new Array(); this.length = this.stackarray.length; } push(value) { this.stackarray.unshift(value); this.length = this.stackarray.length; return value; } pop() { if (this.length <= 0) { throw 'Stack is empty'; } const poped = this.stackarray.shift(); this.length = this.stackarray.length; return poped; } view() { return this.stackarray; } } class Queues { constructor() { this.queuearray = new Array(); this.length = this.queuearray.length; } push(value) { this.queuearray.push(value); this.length = this.queuearray.length; return value; } pop() { if (!this.length) throw 'Queue is empty'; const poped = this.queuearray.shift(); this.length = this.queuearray.length; return poped; } view() { return this.queuearray; } } class Node { constructor(data) { this.d = new Set().add(data); this.visited = false; } } class UGraph { constructor(vertices) { this.v = vertices; this.AdjList = new Map(); this.length = 0; } add(v, dv) { //dv | destination vertices if(v == dv) return 0; if(this.AdjList.has(v)) { this.AdjList.get(v).d.add(dv); }else{ if(this.length >= this.v) return 0; this.AdjList.set(v, new Node(dv)); this.length++; } if(this.AdjList.has(dv)) { this.AdjList.get(dv).d.add(v); }else{ if(this.length >= this.v) return 0; this.AdjList.set(dv, new Node(v)); this.length++; } } adjacent(v1, v2) { return this.AdjList.get(v1).d.has(v2); } neighbors(v1) { return this.AdjList.get(v1).d; } remove(v, dv=false) { if(!dv) { this.AdjList.delete(v); }else{ this.AdjList.get(v).d.delete(dv); } } view() { const iterator1 = this.AdjList[Symbol.iterator](); for (const item of iterator1) { console.log(item[0]); console.log(item[1].d); } } } // maze create start function create(width=3, height=3, cellSize=1) { if (!width || !height || !cellSize) throw new Error("please make sure that (width || height || cellSize) is not (null || undefined || 0)"); let w = width, h = height, cs = cellSize; if(w%cs) { throw new Error("please make sure that (width % cellSize == 0)"); } if(h%cs) { throw new Error("please make sure that (height % cellSize == 0)"); } // reset the old stacks/arrays, and start new maze generation return createMaze(width, height, cellSize); } function createMaze(width, height, cellSize) { let maxW = width/cellSize-1; let n = width/cellSize*height/cellSize; const graph = new UGraph(n); let count = 0; for(let i = 0; i < height; i+= cellSize) { for(let j = 0; j < width; j+= cellSize) { if(count+1 <= maxW) { graph.add(count, count+1); } if(count+(width/cellSize) <= n-1) { graph.add(count, count+(width/cellSize)); } count++; } maxW += width/cellSize; } return DFS(graph, 0); } // return the neighbours which are not visited yet function visitedNeighbours(graph, c) { let nArray = [...graph.neighbors(c)]; let remains = []; for (var i = 0; i < nArray.length; i++) { if(!graph.AdjList.get(nArray[i]).visited) { remains.push(nArray[i]); } } return remains; } // use DFS to traverse the graph(maze) and return the traversed nodes(cells/numbers) function DFS(graph, root) { const stk = new Stack(); const mazeArr = []; const mazeGraph = new UGraph(graph.v); graph.AdjList.get(root).visited = true; stk.push(root); while(stk.length) { let curr = stk.pop(); mazeArr.push(curr); // stores backtracked node/number/cells as well let available = visitedNeighbours(graph, curr); if(available.length){ stk.push(curr); let chosen = available[Math.floor(Math.random()*available.length)]; graph.AdjList.get(chosen).visited = true; mazeGraph.add(curr, chosen); stk.push(chosen); //animateStore.push(chosen); // issue with removing walls } } return {mazeArr, mazeGraph}; } // search algorithm: dijkstra // target is always the last cell/node in the graph function search(graph, root, target, searchAlgoId=1) { if(!graph) throw new Error("graph is undefined"); if ([undefined, null].includes(root) || [undefined, null].includes(target)) { throw new Error("(root || target) is (null || undefined)") } if(searchAlgoId === 1) { return dijkstra(graph, root, target); }else { throw new Error("no search search algorithm with id "+searchAlgoId) } } function dijkstra(graph, root, target) { let prev = new Array(), dist = new Array(); let q = new Set(); const iterator1 = graph.AdjList[Symbol.iterator](); [...iterator1].forEach(z=> { dist[z[0]] = 99999; prev[z[0]] = undefined; q.add(z[0]); }); dist[root] = 0; //console.log(q.values().next().value); //let curr = g.list[i]; while(q.size >= 1) { let u = dist.indexOf(Math.min(...dist)); if (u == target) break; if (q.has(u)) { q.delete(u); } let sathi = [...graph.AdjList.get(u).d]; for (var i = 0; i < sathi.length; i++) { if(q.has(sathi[i])){ let alt = dist[u]+1; if(alt < dist[sathi[i]]) { dist[sathi[i]] = alt; prev[sathi[i]] = u; } } } dist[u] = 99999999; } let stk = new Stack(); let ta = target; if (prev[ta] != undefined || ta == root) { while(ta != undefined) { stk.push(ta); ta = prev[ta]; } } return stk; } module.exports = { create, search }