Custom Variant and Optimization of Depth-first Search Maze Algorithm Part 2
This is the link for the part 1 if you're interested:
https://steemit.com/programming/@jkazuto/custom-variant-and-optimization-of-depth-first-search-maze-algorithm
In this post we will explore the code behind my simple variant of depth-first search which was made with javascript and p5js framework for rendering in canvas.
You can download the source code here: https://github.com/jepsuCoded/Optimized-Depth-first-Search-Maze-Algorithm
What I've used
- Javascript
- p5js
- Spck Editor (Android App)
Variables
Global variables before the setup
cellX is the number of cells in the x-axis and cellY in the y-axis
let cellX = 91, cellY = 41;
The size of each cells
let s = 7;
Maximum steps before backtracking
let maxStep = cellX+cellY;
Numbers of cell to check per frame
let cycle = 60;
Stroke weight of the cell walls
let strokeSize = 1;
Color variables for displaying
FORMAT: [Red, Green, Blue, Alpha];
let bg = [60, 47, 47, 255];
let color_cellWalls = [255, 244, 230, 255];
let color_movingCell = [133, 68, 66, 255];
let color_unvisited = [190, 155, 123, 255];
Other variables that must not be touched
let _width = s*cellX, _height = s*cellY;
let grid = [];
let cols, rows;
let startPos;
let endPos;
Setup
This setup function is part of the p5js and will run once, upon starting the javascript file.
In this setup function,
- The canvas will be created based on the computed width and height.
- All of the cell will be created and stored in a one dimensional array list called grid.
- Create two algorithms/maze runner, one for the starting cell and one for the exit cell.
function setup() {
createCanvas(_width, _height);
cols = floor(width/floor(width/cellX));
rows = floor(height/floor(height/cellY));
// Initialized all cells in an array called grid
for (let j = 0; j < rows; j++) {
for (let i = 0; i < cols; i++) {
grid.push(new Cell(i, j));
}
}
// First maze generator
startPos = new depthFirst();
// This is the starting cell
startPos.start(grid[0], "start");
// Second maze generator
endPos = new depthFirst();
// This is the ending cell
endPos.start(grid[grid.length-1], "end");
}
Draw
The draw function is also part of the p5js and will run a set of frames per second.
In this draw function,
- If one of the two maze runners is not yet finished
- Draw each walls of all the cells
- Loop for
cycletimes and run the algorithm for two maze runners
- If all of the cells are visited and are done running
- Connect the two maze together to create one whole maze
- Draw everything again
- Stop this function, forever
function draw() {
if (startPos.done === 0 || endPos.done === 0) {
// Draw every cells per frame
background(bg[0], bg[1], bg[2], bg[3]);
grid.forEach(item => item.show());
// For every cycle per frame
for(let i = 0; i < cycle; i++) {
// Run the depth-first search algorithm
startPos.run();
endPos.run();
}
}
// If everything is done and all cells are visited
else if (startPos.done === 1 && endPos.done === 1) {
// Combine two generated mazes
startPos.merge(endPos);
// Draw every frame
background(bg[0], bg[1], bg[2], bg[3]);
grid.forEach(item => item.show());
}
}
DepthFirst
This is where the algorithm run everytime the
run() function begins
The top part of this function is the declaration of variables.
function depthFirst() {
// Group of cells
this.group;
// List of visited cells used for backtracking
this.stack = [];
// List of all visited cell used for merge function
this.track = [];
// Current position of running cell
this.pos;
// Starting cell
this.startPos;
this.done = 0;
// Current steps made
this.steps = 0;
// . . .
}
DepthFirst.start()
// Initialization
this.start = function(pos, name) {
this.pos = pos;
this.startPos = pos;
this.stack.push(pos);
this.group = name;
};
DepthFirst.run()
- Store all unvisited neighbor cells in the
unvisitedarray variable - Set this current cell as visited
- If the steps are greater than the maximum step
- Reset
this.stepsto zero - Backtrack
maxStep/2times
- Reset
- Else Pick a random cell in
unvisited- Store that cell to the
nextvariable - Add that cell to the group maze
- Remove wall between the current cell and the
nextcell - Set this cell to
nextcell - Push this cell to the
stackandtracks - Increment
this.steps
- Store that cell to the
- Else if there is no available cell to visit
- Decrement
this.steps - Backtrack one step
- Pop the
stack
- Decrement
- Else set
doneto 1 since there is no more cell to visit
// Start the algorithm
this.run = function() {
// If not done then proceed
if(this.done === 0) {
// Draw current position of running cell
fill(color_movingCell[0], color_movingCell[1], color_movingCell[2], color_movingCell[3]);
noStroke();
rect(this.pos.a*s, this.pos.b*s, s, s);
// Return all unvisited neighbor of current cell
let unvisited = checkNeighbors(this.pos.a, this.pos.b);
// Make this cell visited
this.pos.visited = true;
// If maximum steps are reached then
if(this.steps >= maxStep - 1) {
// Reset steps to zero
this.steps = 0;
// Go back to old cell to find another path
this.pos = this.stack[this.stack.length-(floor(maxStep*0.5))-1];
}
// Else randomly choose new cell to visit
else if(unvisited && this.steps < maxStep) {
// Pick a new cell randomly
let next = unvisited[floor(random(0, unvisited.length))];
// Set this cell to this group
next.group = this.group;
// Remove wall between this cell and the chosen cell to visit
removeWalls(this.pos, next);
/* this.pos.show(); */
//Set the chosen cell as the current cell
this.pos = next;
// Add this new cell into the tracking list
this.track.push(this.pos);
this.stack.push(this.pos);
this.steps++;
}
// Else if there is no neighbor cell to visit
else if(this.stack.length > 1) { // Also checking for the length of stack array to prevent out of bound error
this.steps--;
// Set the current cell to previous visited cell
this.pos = this.stack[this.stack.length-2];
// Remove the last visited cell on the stack
this.stack.pop();
}
// Else everything is visited and is now done
else if (this.done === 0) this.done = 1;
}
};
DepthFirst.merge()
This function is responsible for connecting two mazes together with one argument needed, a
path maze to connect with this maze.
// Merge two generated maze as one whole maze
this.merge = function(path) {
let cells = [];
// Set all cells as unvisited
for (let i = 0; i < grid.length; i++) {
grid[i].visited = false;
}
// Loop through all cells in a generated maze
for(let i = path.track.length-1; i > 0; i--) {
let current = path.track[i];
// Return neighbors
let possible = checkNeighbors(current.a, current.b);
if (possible) {
for(let j = 0; j < possible.length; j++) {
// If that cell is not in this group then
if(possible[j].group == this.group) {
// Add that cell to possible cells
cells.push([current, possible[j]]);
}
}
}
}
for (let i = 0; i < grid.length; i++) {
grid[i].visited = true;
}
let r = floor(random(0, cells.length));
// Remove wall between that cell in this group and another cell from the given other group
removeWalls(cells[r][0], cells[r][1]);
// Done, this function will not run anymore
this.done++;
};
And that is all the main functionality of this variation of depth-first search, I hope you understand most of it even though I didn't explain it very very well :3
You can see more of the other functions I've used on the source code link given above.
If you enjoy reading this please upvote, share and leave a comment for any feedback!
Leave Custom Variant and Optimization of Depth-first Search Maze Algorithm Part 2 to:
Read more #programming posts
Best Posts From Mr. Kirito
We have not curated any of jkazuto's posts yet. But you can encourage our curation team to review posts by visiting them regularly and by referring other readers. Because we give priority to frequently read content.
More Posts From Mr. Kirito
- ...
- Custom Variant and Optimization of Depth-first Search Maze Algorithm Part 2
- Custom variant and optimization of depth-first search maze algorithm part 1
- 30 Days of Coding - Java: Day 1, Introduction
- Do HYIP sites are all but scammers?
- Hello Everyone! This is the Story of My Life #introduceyourself
- ICO Unlimited Review Scam or Legit? - Another BTC Investment program, 10-15% Daily Profit!