diff --git a/cell.js b/cell.js index fb30550..67bcb5a 100644 --- a/cell.js +++ b/cell.js @@ -5,15 +5,15 @@ class Cell { this.x = x; this.y = y; this.walls = [true, true, true, true]; - this.selected = false; this.visited = false; this.cellWidth = cellWidth; - this.searched = false; - this.finalPath = false; this.parent = undefined; - this.end = false; - this.start = false; - } + this.color = [255, 255, 255, 0]; + } + + get defaultColor(){ + return [255, 255, 255, 0]; + } get top(){ return this.walls[0]; @@ -58,32 +58,8 @@ class Cell { if (this.bottom) line(x + this.cellWidth, y + this.cellWidth, x, y + this.cellWidth); if (this.left) line(x, y, x, y + this.cellWidth); - if (this.visited) { - fill(255, 0, 0); - noStroke(); - rect(x, y, this.cellWidth, this.cellWidth); - } - - if(this.searched){ - fill(210, 180, 140); - noStroke(); - rect(x, y, this.cellWidth, this.cellWidth); - } - - if (this.selected) { - fill(50, 125, 0); - noStroke(); - rect(x, y, this.cellWidth, this.cellWidth); - } - - if(this.finalPath){ - fill(173, 216, 230); - noStroke(); - rect(x, y, this.cellWidth, this.cellWidth); - } - - if(this.start){ - text("Start", x, y + cellWidth / 2); - } + fill(this.color); + noStroke(); + rect(x, y, this.cellWidth, this.cellWidth); } } diff --git a/gen-maze.js b/gen-maze.js index bee5ee9..38e10b4 100644 --- a/gen-maze.js +++ b/gen-maze.js @@ -19,31 +19,47 @@ class Maze{ this.workingStack.push(this.grid[this.index(0,0)]); } + getStartingCell(){ + return this.grid[0]; + } + + getEndingCell(){ + return this.grid[this.index(9, 9)]; + } + updateMazeDisplay(){ - for (var i = 0; i < this.grid.length; i++) { + for (let i = 0; i < this.grid.length; i++) { this.grid[i].show(); } } - buildNextCell(){ + resetMazeState(){ + for (let i = 0; i < this.grid.length; i++){ + this.grid[i].visited = false; + this.grid[i].color = this.grid[i].defaultColor; + this.grid[i].parent = undefined; + } + } + + buildNextCell(selectedColor = [50, 175, 50]){ //Build the maze let currentCell = this.workingStack.pop(); - //currentCell.visited = true; + let nextCell = this.getNeighbors(currentCell); if(nextCell){ this.workingStack.push(currentCell); - currentCell.Selected = false; + currentCell.color = currentCell.defaultColor; currentCell.visited = true; nextCell.visited = true; - nextCell.selected = true; - removeWalls(currentCell, nextCell); + nextCell.color = selectedColor; + this.removeWalls(currentCell, nextCell); this.workingStack.push(nextCell); } else this.workingStack.pop(); - currentCell.selected = false; + currentCell.color = currentCell.defaultColor; } get mazeGenDone() { @@ -51,12 +67,12 @@ class Maze{ } getNeighbors(cell){ - var visited = []; + let visited = []; - var top = this.grid[this.index(cell.x, cell.y - 1)]; - var left = this.grid[this.index(cell.x - 1, cell.y)]; - var bottom = this.grid[this.index(cell.x, cell.y + 1)]; - var right = this.grid[this.index(cell.x + 1, cell.y)]; + let top = this.grid[this.index(cell.x, cell.y - 1)]; + let left = this.grid[this.index(cell.x - 1, cell.y)]; + let bottom = this.grid[this.index(cell.x, cell.y + 1)]; + let right = this.grid[this.index(cell.x + 1, cell.y)]; if (top && !top.visited) { visited.push(top); @@ -77,11 +93,55 @@ class Maze{ return visited[floor(random(0, visited.length))]; else return undefined; - } - - index(x, y) { - if (x < 0 || y < 0 || x > this.columns - 1 || y > this.rows - 1) return -1; - return x + y * this.columns; } + getLegalMoves(cell){ + let neighbors = []; + + let top = this.grid[this.index(cell.x, cell.y - 1)]; + let left = this.grid[this.index(cell.x - 1, cell.y)]; + let bottom = this.grid[this.index(cell.x, cell.y + 1)]; + let right = this.grid[this.index(cell.x + 1, cell.y)]; + + if (top && !top.visited && !cell.top) { + neighbors.push(top); + } + if (left && !left.visited && !cell.left) { + neighbors.push(left); + } + if (right && !right.visited && !cell.right) { + neighbors.push(right); + } + if (bottom && !bottom.visited && !cell.bottom) { + neighbors.push(bottom); + } + + return shuffle(neighbors); + } + + removeWalls(a, b) { + let x = a.x - b.x; + let y = a.y - b.y; + + if (x === -1) { + a.setRight = false; + b.setLeft = false; + } else if (x === 1) { + a.setLeft = false; + b.setRight = false; + } + + if (y === -1) { + a.setBottom = false; + b.setTop = false; + } else if (y === 1) { + a.setTop = false; + b.setBottom = false; + } + } + + index(x, y) { + if (x < 0 || y < 0 || x > this.columns - 1 || y > this.rows - 1) return -1; + return x + y * this.columns; + } } diff --git a/index.html b/index.html index 1acca4e..9bc9e85 100644 --- a/index.html +++ b/index.html @@ -22,6 +22,7 @@ clear: both; } + @@ -40,6 +41,7 @@

diff --git a/maze-solver.js b/maze-solver.js new file mode 100644 index 0000000..61f2d7d --- /dev/null +++ b/maze-solver.js @@ -0,0 +1,57 @@ +class MazeSolver { + constructor(startingCell, targetCell, searchedColor = [210, 180, 140]){ + this.frontier = []; + this.explored = []; + this.targetCell = targetCell; + this.searchedColor = searchedColor; + this.selectedColor = [50, 175, 50]; + this.currentCell = startingCell; + this.frontier.push(startingCell); + } + + clearState(){ + this.frontier = []; + this.explored = []; + } + + depthFirstNextCell(maze){ + breadthFirstNextCell(maze, true); + } + + breadthFirstNextCell(maze, depthFirst = false){ + this.currentCell.color = this.searchedColor; + + if(!depthFirst) + this.currentCell = this.frontier.shift(); + else + this.currentCell = this.frontier.pop(); + + this.currentCell.color = this.selectedColor; + + this.currentCell.visited = true; + + let moves = maze.getLegalMoves(this.currentCell); + + for (let i = 0; i < moves.length; i++){ + this.frontier.push(moves[i]); + moves[i].parent = this.currentCell; + } + + this.explored.push(this.currentCell); + + if(this.currentCell.x == this.targetCell.x && this.currentCell.y == this.targetCell.y) + this.frontier = []; + this.currentCell.color = this.searchedColor; + } + + highlightFinalPath(maze, finalPathColor = [173, 216, 230]){ + let tmp = this.explored.pop(); + + while(tmp != undefined){ + tmp.color = finalPathColor; + tmp = tmp.parent; + } + + maze.updateMazeDisplay(); + } +} diff --git a/sketch.js b/sketch.js index ebf781d..3b7056d 100644 --- a/sketch.js +++ b/sketch.js @@ -1,19 +1,16 @@ var cellWidth = 50; -var columns = 0; -var rows = 0; -var grid = []; -//var currentCell; -var cellStack = []; var frontier = []; var explored = []; var currentNode = {}; var maze = {}; +var algo = {}; function setup() { - var canvas = createCanvas(500, 500); + print("hell"); + var canvas = createCanvas(400, 400); canvas.parent('sketch-holder'); - maze = new Maze(width, height, cellWidth); - frameRate(60); + maze = new Maze(width, height, cellWidth, "Depth"); + frameRate(30); } function draw() { @@ -21,139 +18,23 @@ function draw() { maze.updateMazeDisplay(); - if(maze.workingStack.length > 0){ + if(!maze.mazeGenDone){ maze.buildNextCell(); } - /*else if (cellStack.length == 0 && frontier.length == 0 && explored.length == 0){ - for (var i = 0; i < grid.length; i++) { - grid[i].visited = false; - } - + else if (maze.mazeGenDone && algo.frontier == undefined){ + maze.resetMazeState(); + algo = new MazeSolver(maze.grid[0], maze.grid[maze.index(7,7)]); print("Maze generation done"); - - grid[index(0, 0)].selected = true; - grid[index(0, 0)].visited = true; - grid[index(0, 0)].searched = true; - grid[index(0, 0)].start = true; - currentNode = grid[index(0, 0)]; - - frontier.push(grid[index(0, 0)]); - frameRate(5); + frameRate(10); + } + else if (maze.mazeGenDone && algo.frontier.length > 0){ + algo.breadthFirstNextCell(maze); } - else if (cellStack.length == 0 && frontier.length > 0){ - currentNode.selected = false; - currentNode = frontier.shift(); - - let neighbors = getAllNeighbors(currentNode); - - currentNode.searched = true; - currentNode.selected = true; - - for(let index = 0; index < neighbors.length; index++){ - frontier.push(neighbors[index]); - neighbors[index].parent = currentNode; - } - - explored.push(currentNode); - - if(currentNode.x == 9 && currentNode.y == 9) - //currentNode.end = true; - frontier = []; - }*/ else{ - /*tmp = explored.pop(); - - while (tmp.parent != undefined) { - tmp.finalPath = true; - tmp = tmp.parent; - } - grid[index(0, 0)].finalPath = true; - - for (var i = 0; i < grid.length; i++) { - grid[i].show(); - }*/ + algo.highlightFinalPath(maze); print("Maze search done"); noLoop(); } } - -function index(x, y) { - if (x < 0 || y < 0 || x > columns - 1 || y > rows - 1) return -1; - return x + y * columns; -} - -function removeWalls(a, b) { - var x = a.x - b.x; - var y = a.y - b.y; - - if (x === -1) { - a.setRight = false; - b.setLeft = false; - } else if (x === 1) { - a.setLeft = false; - b.setRight = false; - } - - if (y === -1) { - a.setBottom = false; - b.setTop = false; - } else if (y === 1) { - a.setTop = false; - b.setBottom = false; - } -} - -function getAllNeighbors(cell){ - var Neighbors = []; - - var top = grid[index(cell.x, cell.y - 1)]; - var left = grid[index(cell.x - 1, cell.y)]; - var bottom = grid[index(cell.x, cell.y + 1)]; - var right = grid[index(cell.x + 1, cell.y)]; - - if (top && !top.searched && !cell.top) { - Neighbors.push(top); - } - if (left && !left.searched && !cell.left) { - Neighbors.push(left); - } - if (right && !right.searched && !cell.right) { - Neighbors.push(right); - } - if (bottom && !bottom.searched && !cell.bottom) { - Neighbors.push(bottom); - } - - return shuffle(Neighbors); -} - -function getNeighbors(cell){ - var visited = []; - - var top = grid[index(cell.x, cell.y - 1)]; - var left = grid[index(cell.x - 1, cell.y)]; - var bottom = grid[index(cell.x, cell.y + 1)]; - var right = grid[index(cell.x + 1, cell.y)]; - - if (top && !top.visited) { - visited.push(top); - } - if (left && !left.visited) { - visited.push(left); - } - if (right && !right.visited) { - visited.push(right); - } - if (bottom && !bottom.visited) { - visited.push(bottom); - } - - if(visited.length == 1) - return visited[0]; - else if (visited.length > 1) - return visited[floor(random(0, visited.length))]; - else - return undefined; -}