From 87009d654ab3a4dff4b40dea317be8ed8fd2f70e Mon Sep 17 00:00:00 2001 From: Lennard Schober Date: Tue, 30 Apr 2024 21:57:17 +0200 Subject: [PATCH] Add recursive DFS maze generation --- js/scripts2.js | 98 ++++++++++++++++++++++++++++++++++++++++++++++-- pathfinding.html | 1 + 2 files changed, 96 insertions(+), 3 deletions(-) diff --git a/js/scripts2.js b/js/scripts2.js index c39bf0e..50fe737 100644 --- a/js/scripts2.js +++ b/js/scripts2.js @@ -216,6 +216,9 @@ document.querySelectorAll('.dropdown-item').forEach(item => { case "genRandomObstaclesWeights": generateRandomObstaclesWeights(); break; + case "genRecursiveDFS": + generateRecursiveDFS(); + break; case "genRecursive": generateRecursive(0); break; @@ -237,8 +240,6 @@ document.querySelectorAll('.dropdown-item').forEach(item => { // If yes, set the selectedText to the index of that text // Add the event listeners for mousedown, mousemove, and mouseup canvas.addEventListener("mousedown", (e) => { - console.log("MOUSEDOWN"); - var elem = document.getElementById("visualizeButton"); if (elem.innerText == "stop!") toggleVisualizeButton(); @@ -417,7 +418,6 @@ window.addEventListener("mousemove", (e) => { // handle mouseup events canvas.addEventListener("mouseup", (e) => { - console.log("MOUSEUP"); mouseX = getMousePos(e).x; mouseY = getMousePos(e).y; canMove = 0; @@ -1499,6 +1499,68 @@ async function generateRandomObstaclesWeights() { drawGrid(); } +// generate recursively using DFS +async function generateRecursiveDFS() { + if (stopper) return; + stopper = 1; + + const rows = globalGrid.length; + const cols = globalGrid[0].length; + // Create a grid and fill with walls + globalGrid = Array.from({ length: rows }, () => Array(cols).fill(1)); + + animationGrid = Array.from({ length: rows }, () => Array(cols).fill(2)); + drawGrid(); + + // Recursive DFS function + async function dfs(x, y) { + globalGrid[y][x] = 0; // Mark the current cell as visited + const directions = [ + [-1, 0], // up + [0, 1], // right + [1, 0], // down + [0, -1] // left + ]; + + shuffle(directions); // Randomize the directions + + for (let i = 0; i < directions.length; i++) { + const [dx, dy] = directions[i]; + const nx = x + dx * 2; + const ny = y + dy * 2; + + // Check if the next cell is within the grid and not visited + if (nx >= 0 && nx < cols && ny >= 0 && ny < rows && globalGrid[ny][nx] === 1) { + const mx = x + dx; + const my = y + dy; + globalGrid[my][mx] = 0; // Make the wall a passage + + resetCanvas(); + drawGrid(); + await sleep(globalSpeed * 10); + + await dfs(nx, ny); + } + } + } + + await dfs(sCol, sRow); + + // open one random side of end point if encased + if (!endHasEmptyNeighbors()) { + let temp = getClosedSides(); + shuffle(temp); + const [dx, dy] = temp[0]; + const mx = tCol + dx; + const my = tRow + dy; + globalGrid[my][mx] = 0; // Make the wall a passage + } + + stopper = 0; + resetCanvas(); + drawGrid(); +} + // function to generate a maze using recursive division algorithm // 1 = horizontal bias // -1 = vertical bias @@ -1605,6 +1667,33 @@ class PriorityQueue { * */ +function endHasEmptyNeighbors() { + if (tRow > 0 && globalGrid[tRow - 1][tCol] == CellState.EMPTY) return true; + if (tRow + 1 < globalGrid.length && globalGrid[tRow + 1][tCol] == CellState.EMPTY) return true; + if (tCol > 0 && globalGrid[tRow][tCol - 1] == CellState.EMPTY) return true; + if (tCol + 1 < globalGrid[0].length && globalGrid[tRow][tCol + 1] == CellState.EMPTY) return true; + return false; +} + +// check if end point has any opening +function getClosedSides() { + let directions = []; + if (tRow > 0 && globalGrid[tRow - 1][tCol] == CellState.OBSTACLE) directions.push([-1, 0]); + if (tRow + 1 < globalGrid.length && globalGrid[tRow + 1][tCol] == CellState.OBSTACLE) directions.push([1, 0]); + if (tCol > 0 && globalGrid[tRow][tCol - 1] == CellState.OBSTACLE) directions.push([0, -1]); + if (tCol + 1 < globalGrid[0].length && globalGrid[tRow][tCol + 1] == CellState.OBSTACLE) directions.push([0, 1]); + + return directions; +} + +// Function to shuffle array +function shuffle(array) { + for (let i = array.length - 1; i > 0; i--) { + const j = Math.floor(Math.random() * (i + 1)); + [array[i], array[j]] = [array[j], array[i]]; + } +} + // returns the heuristic value for A* and greedy BFS function heuristic(row, col, goalRow, goalCol) { // Manhattan distance heuristic @@ -1833,3 +1922,6 @@ function fastBFS(row, col) { return false; } + + + diff --git a/pathfinding.html b/pathfinding.html index fc66359..5fbdc6b 100644 --- a/pathfinding.html +++ b/pathfinding.html @@ -73,6 +73,7 @@ aria-labelledby="navbarDarkDropdownMenuLink">
  • empty
  • +
  • recursive DFS
  • recursive division
  • recursive division horizontal bias