1

I have generated a maze using depth first search - recursive backtracker algorithm. I also want to solve, but not getting idea about how to start solving my maze.

I am using p5.js to create my maze, and want to solve my already generated maze.

This is my javascript code for generating maze. You might want to add p5.js cdn in your html file if you want to run this code.

var cols, rows;
var w = 40;
var grid = [];
var current;
var stack = [];
function setup() {
    createCanvas(400,400);
    cols = floor(width/w);
    rows = floor(height/w);
    frameRate(5);
    for (var j = 0; j<rows; j++){
        for (var i = 0; i < cols; i++) {
            var cell = new Cell(i,j);
            grid.push(cell);
        }
    }
    current = grid[0];
}
function draw(){
    background(51);
    for (var i = 0; i<grid.length; i++){
        grid[i].show();
    }
    current.visited = true;
    current.highlight();
    var next = current.checkNeighbours();
    if (next) {
        next.visited = true;
        stack.push(current);
        removeWalls(current,next);
        current = next;
    }
    else if(stack.length > 0){
        current = stack.pop();
    }
}
function index(i,j){
    if (i < 0 || j < 0 || i > cols-1 || j > rows-1) {
        return -1;
    }
    return i + j * cols;
}
function Cell(i,j){
    this.i = i;
    this.j = j;
    this.walls = [true,true,true,true];
    this.visited = false;
    this.checkNeighbours = function(){
        var neighbours = [];
        var top =       grid[index(i, j-1)];
        var right =     grid[index(i+1, j)];
        var bottom =    grid[index(i, j+1)];
        var left =      grid[index(i-1, j)];
        if (top && !top.visited){
            neighbours.push(top);
        }
        if (right && !right.visited){
            neighbours.push(right);
        }
        if (bottom && !bottom.visited){
            neighbours.push(bottom);
        }
        if (left && !left.visited){
            neighbours.push(left);
        }
        if (neighbours.length > 0){
            var r = floor(random(0, neighbours.length));
            return neighbours[r];
        }
        else{
            return undefined;
        }
    }
    this.highlight = function(){
        x = this.i*w;
        y = this.j*w;
        noStroke();
        fill(0,0,255,200);
        rect(x,y,w,w);
    }
    this.show = function(){
        x = this.i*w;
        y = this.j*w;
        stroke(255);
        if (this.walls[0]){
            line(x   ,y    ,x+w ,y);
        }   
        if (this.walls[1]){
            line(x+w ,y    ,x+w ,y+w);
        }
        if (this.walls[2]){
            line(x+w ,y+w  ,x   ,y+w);
        }
        if (this.walls[3]){
            line(x   ,y+w  ,x   ,y)
        }   
        if (this.visited) {
            noStroke();
            fill(255,0,255,100);
            rect(x,y,w,w);
        }
    }
}
function removeWalls(a,b){
    var x = a.i - b.i;
    if (x === 1){
        a.walls[3] = false;
        b.walls[1] = false;
    }
    else if (x === -1){
        a.walls[1] = false;
        b.walls[3] = false; 
    }
    var y = a.j - b.j;
    if (y === 1){
        a.walls[0] = false;
        b.walls[2] = false;
    }
    else if (y === -1){
        a.walls[2] = false;
        b.walls[0] = false; 
    }   
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.7.3/p5.js"></script>
Rabbid76
  • 202,892
  • 27
  • 131
  • 174
pratteek shaurya
  • 850
  • 2
  • 12
  • 34
  • I would start off by looking at Search algorithms, the likes of Depth First Search. Or complete algorithms such as Breadth First Search or A*. – Luke Garrigan Apr 05 '19 at 08:51
  • It's hard to help with general "how do I do this" questions other than by pointing you to google. Have you tried googling "maze solving algorithm" and reading tutorials? – Kevin Workman Apr 06 '19 at 17:11

2 Answers2

1

There are many algorithmsfor solving mazes. One simple way to solve mazes created with the recursive backtracker algorithm is to keep track of the solution as the maze is being generated.

  1. Make the first cell the starting cell and push it onto the solution stack
  2. Make the last cell the goal cell
  3. While the solution stack does not contain the goal cell
    1. if the next neighbor is un-visited push it onto the solution stack
    2. if a cell has no next neighbor pop the solution stack as we are backtracking
  4. When the goal cell is pushed onto the solution stack mark the solution complete

Adapting the questions code so that it also implements the solution algorithm we have:

var cols, rows;
var w = 40;
var grid = [];
var current;
var stack = [];
var solution = [];
var goal;
var solutionComplete;
function setup() {
    createCanvas(400,400);
    cols = floor(width/w);
    rows = floor(height/w);
    frameRate(5);
    for (var j = 0; j<rows; j++){
        for (var i = 0; i < cols; i++) {
            var cell = new Cell(i,j);
            grid.push(cell);
        }
    }
    current = grid[0];
    grid[grid.length - 1].goal = true;
    solution.push(grid[0]);
}
function draw(){
    background(51);
    for (var i = 0; i<grid.length; i++){
        grid[i].show();
    }
    current.visited = true;
    current.highlight();
    var next = current.checkNeighbours();
    if (next) {
        if (!next.visited){
          if (!solutionComplete){
            solution.push(next);
            if (next.goal){
              solutionComplete = true;
            }
          }
        }
        next.visited = true;
        stack.push(current);
        removeWalls(current,next);
        current = next;
    }
    else if(stack.length > 0){
        current = stack.pop();
        if (!solutionComplete){
          solution.pop();
        }
    }
    if (solutionComplete){
      for (let i = 0; i < solution.length; i++){
        solution[i].solutionCell = true;
      }
    }
}
function index(i,j){
    if (i < 0 || j < 0 || i > cols-1 || j > rows-1) {
        return -1;
    }
    return i + j * cols;
}
function Cell(i,j){
    this.i = i;
    this.j = j;
    this.walls = [true,true,true,true];
    this.visited = false;
    this.goal = false;
    this.solutionCell = false;
    this.checkNeighbours = function(){
        var neighbours = [];
        var top =       grid[index(i, j-1)];
        var right =     grid[index(i+1, j)];
        var bottom =    grid[index(i, j+1)];
        var left =      grid[index(i-1, j)];
        if (top && !top.visited){
            neighbours.push(top);
        }
        if (right && !right.visited){
            neighbours.push(right);
        }
        if (bottom && !bottom.visited){
            neighbours.push(bottom);
        }
        if (left && !left.visited){
            neighbours.push(left);
        }
        if (neighbours.length > 0){
            var r = floor(random(0, neighbours.length));
            return neighbours[r];
        }
        else{
            return undefined;
        }
    }
    this.highlight = function(){
        x = this.i*w;
        y = this.j*w;
        noStroke();
        fill(0,0,255,200);
        rect(x,y,w,w);
    }
    this.show = function(){
        x = this.i*w;
        y = this.j*w;
        stroke(255);
        if (this.walls[0]){
            line(x   ,y    ,x+w ,y);
        }   
        if (this.walls[1]){
            line(x+w ,y ,x+w ,y+w);
        }
        if (this.walls[2]){
            line(x+w ,y+w  ,x ,y+w);
        }
        if (this.walls[3]){
            line(x ,y+w ,x ,y)
        }
        if (this.goal){
            noStroke();
            fill(0,255,0,100);
            rect(x,y,w,w);
        }        
        else if (this.solutionCell){
            noStroke();
            fill(255,0,0,100);
            rect(x,y,w,w);
        }else if(this.visited) {
            noStroke();
            fill(255,0,255,100);
            rect(x,y,w,w);
        }
    }
}
function removeWalls(a,b){
    var x = a.i - b.i;
    if (x === 1){
        a.walls[3] = false;
        b.walls[1] = false;
    }
    else if (x === -1){
        a.walls[1] = false;
        b.walls[3] = false; 
    }
    var y = a.j - b.j;
    if (y === 1){
        a.walls[0] = false;
        b.walls[2] = false;
    }
    else if (y === -1){
        a.walls[2] = false;
        b.walls[0] = false; 
    }   
}
   <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.7.2/p5.min.js"></script>

It would not be difficult to break the maze generation and solution implementations apart so that the maze is completely generated before the solution is determined but unless there is a restriction that forces us to solve a completed maze it makes sense to build the solution along with the maze.

Charlie Wallace
  • 1,810
  • 1
  • 15
  • 17
0

Sorry about this this is very related but coding train a coding youtuber made a maze generating algorithm, but i don't know if it used depth first search

unixGeek
  • 41
  • 2