diff --git a/code/assets/js/visual/Grid/index.js b/code/assets/js/visual/Grid/index.js
index a0bd844..9d46f3a 100644
--- a/code/assets/js/visual/Grid/index.js
+++ b/code/assets/js/visual/Grid/index.js
@@ -1,10 +1,10 @@
import {
- createEmptyBoard,
- createBoard,
- createStartNode,
- createEndNode,
- refreshBoard,
- refreshEmptyBoard,
+ createEmptyBoard,
+ createBoard,
+ createStartNode,
+ createEndNode,
+ refreshBoard,
+ refreshEmptyBoard,
} from "./createGrid.js";
import { setWall } from "./createWalls.js";
import { setObstacles } from "./generateObstacles.js";
@@ -13,10 +13,11 @@ import { bfs } from "../PathFindingAlgorithms/bfs.js";
import { bfsIslands } from "../Islands/bfsIslands.js";
import { dfsIslands } from "../Islands/dfsIslands.js";
import { maxIsland } from "../Islands/largeIsland.js";
+import { findPaths } from "../PathFindingAlgorithms/findPaths.js";
import {
- bellmanFord,
- relaxations,
- bellmanStepsLength,
+ bellmanFord,
+ relaxations,
+ bellmanStepsLength,
} from "../PathFindingAlgorithms/bellmanFord.js";
// get dom elements
@@ -26,13 +27,16 @@ export const resetBtn = document.querySelector(".reset");
const weightBtn = document.querySelector(".weight");
const algoBtn = document.querySelector(".algo");
export const startBtn = document.querySelector(".start");
+export const findNextPath = document.querySelector(".findNext");
export const wallBtn = document.querySelector(".setWalls");
export const speedSlider = document.querySelector(".speedSlider");
const islandAlgoBtn = document.querySelector(".islandsAlgo");
export const stepsContainer = document.querySelector(".notification");
export const algorithmType = document.querySelector(".algorithm");
export var manualStart = document.querySelector(".manual");
+
manualStart.setAttribute("disabled", "true");
+findNextPath.setAttribute("disabled", "true");
//global variables
export var rowSize = 20;
@@ -45,7 +49,7 @@ export var mouseDown = false;
export var weightType = weightBtn.options[weightBtn.selectedIndex].value;
export var algorithm = algoBtn.options[algoBtn.selectedIndex].value;
export var islandAlgo =
- islandAlgoBtn.options[islandAlgoBtn.selectedIndex].value;
+ islandAlgoBtn.options[islandAlgoBtn.selectedIndex].value;
//steps arrays
export let bfsSteps = [];
@@ -53,42 +57,45 @@ export let dfsSteps = [];
export let bellmanSteps = [];
export let dijkstrasPath = [];
export let bellmanFordPath = [];
+export let visitedPaths = [];
//event listeners
gridContainer.addEventListener("mousedown", () => {
- mouseDown = true;
+ mouseDown = true;
});
gridContainer.addEventListener("mouseup", () => {
- mouseDown = false;
+ mouseDown = false;
});
gridContainer.addEventListener("mouseover", () => {
- setWall;
+ setWall;
});
wallBtn.addEventListener("click", setObstacles);
islandAlgoBtn.addEventListener("change", () => {
- window.location.reload();
+ window.location.reload();
});
//clear path after traversal
export const clearPath = () => {
- gridContainer.addEventListener("mousedown", setWall);
- gridContainer.addEventListener("mouseup", setWall);
- gridContainer.addEventListener("mouseover", setWall);
- if (
- algorithmType.classList.contains("bfs") ||
- algorithmType.classList.contains("dfs") ||
- algorithmType.classList.contains("numIslands") ||
- algorithmType.classList.contains("maxIsland")
- ) {
- refreshEmptyBoard();
- } else if (
- algorithmType.classList.contains("dijkstras") ||
- algorithmType.classList.contains("bellman-ford")
- ) {
- refreshBoard();
- }
- startBtn.style.visibility = "visible";
+ gridContainer.addEventListener("mousedown", setWall);
+ gridContainer.addEventListener("mouseup", setWall);
+ gridContainer.addEventListener("mouseover", setWall);
+ if (
+ algorithmType.classList.contains("bfs") ||
+ algorithmType.classList.contains("dfs") ||
+ algorithmType.classList.contains("numIslands") ||
+ algorithmType.classList.contains("maxIsland") ||
+ algorithmType.classList.contains("findPaths") ||
+ algorithmType.classList.contains("findPaths")
+ ) {
+ refreshEmptyBoard();
+ } else if (
+ algorithmType.classList.contains("dijkstras") ||
+ algorithmType.classList.contains("bellman-ford")
+ ) {
+ refreshBoard();
+ }
+ startBtn.style.visibility = "visible";
};
resetBtn.addEventListener("click", () => location.reload());
@@ -102,223 +109,247 @@ stepsContainer.append(stepsTitle);
//log steps for algorithm
export const notification = (row, col, erow, ecol, cost, prevCost) => {
- var step = document.createElement("div");
- step.classList.add("step");
- var push = document.createElement("p");
- var explore = document.createElement("p");
- var costText = document.createElement("p");
- if (algorithmType.classList.contains("bellman-ford")) {
- if (bellmanSteps.length == 0) {
- push.textContent = `Selected (${row}, ${col}) as path.`;
- } else {
- if (
- bellmanSteps.length <=
- bellmanStepsLength - bellmanStepsLength / relaxations
- ) {
- push.textContent = `Relaxing (${row}, ${col}): current cost ${prevCost}, updated cost ${
- cost || "inf"
- }.`;
- explore.textContent = `Processing (${erow}, ${ecol}).`;
- } else {
- push.textContent = `Pushed (${row}, ${col}) to dist[] array.`;
- explore.textContent = `Exploring (${erow}, ${ecol}).`;
- }
- }
- } else if (
- algorithmType.classList.contains("dijkstras") ||
- algorithmType.classList.contains("bfs")
- ) {
- if (bfsSteps.length == 0) {
- push.textContent = `Selected (${row}, ${col}) as path.`;
- } else {
- push.textContent = `Pushed (${row}, ${col}) to array.`;
- explore.textContent = `Processing (${erow}, ${ecol}).`;
- costText.textContent = `Cost from source is ${cost}`;
- }
- } else if (algorithmType.classList.contains("dfs")) {
- if (row == erow && col == ecol) {
- push.textContent = `Pushed (${erow}, ${ecol}) to stack.`;
- explore.textContent = `Exploring (${erow}, ${ecol}).`;
- } else {
- push.textContent = `Popped (${row}, ${col}) from stack.`;
- }
- }
- step.appendChild(push);
- step.appendChild(explore);
- step.appendChild(costText);
- stepsContainer.append(step);
- stepsContainer.scrollTop = stepsContainer.scrollHeight;
+ var step = document.createElement("div");
+ step.classList.add("step");
+ var push = document.createElement("p");
+ var explore = document.createElement("p");
+ var costText = document.createElement("p");
+ if (algorithmType.classList.contains("bellman-ford")) {
+ if (bellmanSteps.length == 0) {
+ push.textContent = `Selected (${row}, ${col}) as path.`;
+ } else {
+ if (
+ bellmanSteps.length <=
+ bellmanStepsLength - bellmanStepsLength / relaxations
+ ) {
+ push.textContent = `Relaxing (${row}, ${col}): current cost ${prevCost}, updated cost ${
+ cost || "inf"
+ }.`;
+ explore.textContent = `Processing (${erow}, ${ecol}).`;
+ } else {
+ push.textContent = `Pushed (${row}, ${col}) to dist[] array.`;
+ explore.textContent = `Exploring (${erow}, ${ecol}).`;
+ }
+ }
+ } else if (
+ algorithmType.classList.contains("dijkstras") ||
+ algorithmType.classList.contains("bfs") ||
+ algorithmType.classList.contains("findPaths")
+ ) {
+ if (bfsSteps.length == 0) {
+ push.textContent = `Selected (${row}, ${col}) as path.`;
+ } else {
+ push.textContent = `Pushed (${row}, ${col}) to array.`;
+ explore.textContent = `Processing (${erow}, ${ecol}).`;
+ costText.textContent = `Cost from source is ${cost}`;
+ }
+ } else if (algorithmType.classList.contains("dfs")) {
+ if (row == erow && col == ecol) {
+ push.textContent = `Pushed (${erow}, ${ecol}) to stack.`;
+ explore.textContent = `Exploring (${erow}, ${ecol}).`;
+ } else {
+ push.textContent = `Popped (${row}, ${col}) from stack.`;
+ }
+ }
+ step.appendChild(push);
+ step.appendChild(explore);
+ step.appendChild(costText);
+ stepsContainer.append(step);
+ stepsContainer.scrollTop = stepsContainer.scrollHeight;
- step.addEventListener("click", () => {
- let node = document.querySelector(`div[row='${row}'][col='${col}']`);
- let node1 = document.querySelector(`div[row='${erow}'][col='${ecol}']`);
- setTimeout(() => {
- node.setAttribute("class", "pathColor");
- node1.setAttribute("class", "pathColor");
- }, 1000);
- node1.setAttribute("class", "manualStep");
- node.setAttribute("class", "chosenPath");
- });
+ step.addEventListener("click", () => {
+ let node = document.querySelector(`div[row='${row}'][col='${col}']`);
+ let node1 = document.querySelector(`div[row='${erow}'][col='${ecol}']`);
+ setTimeout(() => {
+ node.setAttribute("class", "pathColor");
+ node1.setAttribute("class", "pathColor");
+ }, 1000);
+ node1.setAttribute("class", "manualStep");
+ node.setAttribute("class", "chosenPath");
+ });
};
// step by step visualization
let isPath = true;
export const stepper = (steps) => {
- gridContainer.removeEventListener("mousedown", setWall);
- gridContainer.removeEventListener("mouseover", setWall);
- // wallBtn.setAttribute("disabled", true);
- if (isPath) {
- clearPath();
- bellmanFordPath.splice(
- 0,
- bellmanFordPath.length - bellmanFordPath.length / 5
- );
- startBtn.setAttribute("disabled", "true");
- clearPathBtn.setAttribute("disabled", "true");
- stepsContainer.classList.remove("notification");
- stepsContainer.classList.add("show");
- wallBtn.setAttribute("disabled", "true");
- isPath = false;
- }
- if (steps.length == 0) {
- if (
- algorithmType.classList.contains("dijkstras") ||
- algorithmType.classList.contains("bfs")
- ) {
- if (dijkstrasPath.length == 0) {
- alert("Steps completed!");
- } else {
- //draw path
- var pcol = dijkstrasPath[0][0];
- var prow = dijkstrasPath[0][1];
- setTimeout(() => {
- node.setAttribute("class", "pathColor");
- }, 1000);
- node.setAttribute("class", "chosenPath");
- notification(pcol, prow, 0, 0);
- dijkstrasPath.shift();
- }
- } else if (algorithmType.classList.contains("bellman-ford")) {
- if (bellmanFordPath.length == 0) {
- alert("Bellman ford steps completed!");
- } else {
- //draw path
- var pcol = bellmanFordPath[0][0];
- var prow = bellmanFordPath[0][1];
- let node = document.querySelector(
- `div[row='${pcol}'][col='${prow}']`
- );
- node.setAttribute("class", "chosenPath");
- notification(pcol, prow, 0, 0);
- bellmanFordPath.shift();
- }
- } else {
- alert("Completed Steps");
- }
- } else {
- var cr = steps[0][0];
- var cc = steps[0][1];
- var cost = steps[0][2];
- var er = steps[0][3];
- var ec = steps[0][4];
- let node = document.querySelector(`div[row='${cr}'][col='${cc}']`);
- setTimeout(() => {
- node.setAttribute("class", "pathColor");
- }, 1000);
- node.setAttribute("class", "chosenPath");
- //relaxation for bellman ford nodes
- let prevCost = node.innerHTML;
- node.innerHTML = cost || "inf";
- notification(cr, cc, er, ec, cost, prevCost);
- steps.shift();
- }
+ gridContainer.removeEventListener("mousedown", setWall);
+ gridContainer.removeEventListener("mouseover", setWall);
+ // wallBtn.setAttribute("disabled", true);
+ if (isPath) {
+ clearPath();
+ bellmanFordPath.splice(
+ 0,
+ bellmanFordPath.length - bellmanFordPath.length / 5
+ );
+ startBtn.setAttribute("disabled", "true");
+ clearPathBtn.setAttribute("disabled", "true");
+ stepsContainer.classList.remove("notification");
+ stepsContainer.classList.add("show");
+ wallBtn.setAttribute("disabled", "true");
+ isPath = false;
+ }
+ if (steps.length == 0) {
+ if (
+ algorithmType.classList.contains("dijkstras") ||
+ algorithmType.classList.contains("bfs")
+ ) {
+ if (dijkstrasPath.length == 0) {
+ alert("Steps completed!");
+ } else {
+ //draw path
+ var pcol = dijkstrasPath[0][0];
+ var prow = dijkstrasPath[0][1];
+ setTimeout(() => {
+ node.setAttribute("class", "pathColor");
+ }, 1000);
+ node.setAttribute("class", "chosenPath");
+ notification(pcol, prow, 0, 0);
+ dijkstrasPath.shift();
+ }
+ } else if (algorithmType.classList.contains("bellman-ford")) {
+ if (bellmanFordPath.length == 0) {
+ alert("Bellman ford steps completed!");
+ } else {
+ //draw path
+ var pcol = bellmanFordPath[0][0];
+ var prow = bellmanFordPath[0][1];
+ let node = document.querySelector(`div[row='${pcol}'][col='${prow}']`);
+ node.setAttribute("class", "chosenPath");
+ notification(pcol, prow, 0, 0);
+ bellmanFordPath.shift();
+ }
+ } else {
+ alert("Completed Steps");
+ }
+ } else {
+ var cr = steps[0][0];
+ var cc = steps[0][1];
+ var cost = steps[0][2];
+ var er = steps[0][3];
+ var ec = steps[0][4];
+ let node = document.querySelector(`div[row='${cr}'][col='${cc}']`);
+ setTimeout(() => {
+ node.setAttribute("class", "pathColor");
+ }, 1000);
+ node.setAttribute("class", "chosenPath");
+ //relaxation for bellman ford nodes
+ let prevCost = node.innerHTML;
+ node.innerHTML = cost || "inf";
+ notification(cr, cc, er, ec, cost, prevCost);
+ steps.shift();
+ }
+};
+
+const findNextPathFunc = (nodes) => {
+ let startNextRow = nodes.slice(-1)[0][0];
+ let startNextCol = nodes.slice(-1)[0][1];
+ let node = document.querySelector(
+ `div[row='${startNextRow}'][col='${startNextCol}']`
+ );
+ nodes.pop();
+ clearPath();
+ dfs(startRow, startCol, endRow, endCol);
+ if (parseInt(node.getAttribute("wall")) == 0) {
+ node.setAttribute("wall", 1);
+ }
};
//run normal visualization
const startVisualization = () => {
- if (algorithmType.classList.contains("bfs")) {
- bfs(startRow, startCol, endRow, endCol);
- manualStart.addEventListener("click", () => {
- stepper(bfsSteps);
- });
- } else if (algorithmType.classList.contains("dfs")) {
- dfs(startRow, startCol, endRow, endCol);
- manualStart.addEventListener("click", () => {
- stepper(dfsSteps);
- });
- } else if (algorithmType.classList.contains("dijkstras")) {
- bfs(startRow, startCol, endRow, endCol);
- manualStart.addEventListener("click", () => {
- stepper(bfsSteps);
- });
- } else if (algorithmType.classList.contains("bellman-ford")) {
- bellmanFord(startRow, startCol, endRow, endCol);
- manualStart.addEventListener("click", () => {
- stepper(bellmanSteps);
- });
- } else if (algorithmType.classList.contains("numIslands")) {
- if (islandAlgo === "bfs") {
- bfsIslands();
- } else if (islandAlgo === "dfs") {
- dfsIslands();
- }
- } else if (algorithmType.classList.contains("maxIsland")) {
- maxIsland();
- }
+ if (algorithmType.classList.contains("bfs")) {
+ bfs(startRow, startCol, endRow, endCol);
+ manualStart.addEventListener("click", () => {
+ stepper(bfsSteps);
+ });
+ } else if (algorithmType.classList.contains("dfs")) {
+ dfs(startRow, startCol, endRow, endCol);
+ manualStart.addEventListener("click", () => {
+ stepper(dfsSteps);
+ });
+ } else if (algorithmType.classList.contains("dijkstras")) {
+ bfs(startRow, startCol, endRow, endCol);
+ manualStart.addEventListener("click", () => {
+ stepper(bfsSteps);
+ });
+ } else if (algorithmType.classList.contains("bellman-ford")) {
+ bellmanFord(startRow, startCol, endRow, endCol);
+ manualStart.addEventListener("click", () => {
+ stepper(bellmanSteps);
+ });
+ } else if (algorithmType.classList.contains("numIslands")) {
+ if (islandAlgo === "bfs") {
+ bfsIslands();
+ } else if (islandAlgo === "dfs") {
+ dfsIslands();
+ }
+ } else if (algorithmType.classList.contains("maxIsland")) {
+ maxIsland();
+ } else if (algorithmType.classList.contains("findPaths")) {
+ findPaths(startRow, startCol, endRow, endCol);
+ findNextPath.addEventListener("click", () => {
+ findNextPathFunc(visitedPaths);
+ });
+ // manualStart.addEventListener("click", () => {
+ // stepper(dfsSteps);
+ // });
+ }
};
startBtn.addEventListener("click", startVisualization);
+// findNextPath.addEventListener("click");
//Initialize board
window.onload = () => {
- gridContainer.addEventListener("mousedown", setWall);
- gridContainer.addEventListener("mouseup", setWall);
- gridContainer.addEventListener("mouseover", setWall);
- if (
- algorithmType.classList.contains("bfs") ||
- algorithmType.classList.contains("dfs") ||
- algorithmType.classList.contains("numIslands") ||
- algorithmType.classList.contains("maxIsland")
- ) {
- createEmptyBoard();
- } else if (
- algorithmType.classList.contains("dijkstras") ||
- algorithmType.classList.contains("bellman-ford")
- ) {
- createBoard();
- }
- if (
- algorithmType.classList.contains("bfs") ||
- algorithmType.classList.contains("dfs") ||
- algorithmType.classList.contains("dijkstras") ||
- algorithmType.classList.contains("bellman-ford")
- ) {
- createStartNode(startRow, startCol);
- createEndNode(endRow, endCol);
- } else if (
- algorithmType.classList.contains("numIslands") ||
- algorithmType.classList.contains("maxIslands")
- ) {
- if (islandAlgo === "bfs") {
- createStartNode(0, 0);
- createEndNode(19, 39);
- document
- .querySelector(`div[row='${0}'][col='${0}']`)
- .classList.add("islandsPathNode");
- document
- .querySelector(`div[row='${19}'][col='${39}']`)
- .classList.add("islandsPathNode");
- } else if (
- islandAlgo === "dfs" ||
- algorithmType.classList.contains("maxIslands")
- ) {
- createStartNode(0, 0);
- createEndNode(0, 1);
- document
- .querySelector(`div[row='${0}'][col='${0}']`)
- .classList.add("islandsPathNode");
- document
- .querySelector(`div[row='${0}'][col='${1}']`)
- .classList.add("islandsPathNode");
- }
- }
+ gridContainer.addEventListener("mousedown", setWall);
+ gridContainer.addEventListener("mouseup", setWall);
+ gridContainer.addEventListener("mouseover", setWall);
+ if (
+ algorithmType.classList.contains("bfs") ||
+ algorithmType.classList.contains("dfs") ||
+ algorithmType.classList.contains("numIslands") ||
+ algorithmType.classList.contains("maxIsland") ||
+ algorithmType.classList.contains("findPaths")
+ ) {
+ createEmptyBoard();
+ } else if (
+ algorithmType.classList.contains("dijkstras") ||
+ algorithmType.classList.contains("bellman-ford")
+ ) {
+ createBoard();
+ }
+ if (
+ algorithmType.classList.contains("bfs") ||
+ algorithmType.classList.contains("dfs") ||
+ algorithmType.classList.contains("dijkstras") ||
+ algorithmType.classList.contains("bellman-ford") ||
+ algorithmType.classList.contains("findPaths")
+ ) {
+ createStartNode(startRow, startCol);
+ createEndNode(endRow, endCol);
+ } else if (
+ algorithmType.classList.contains("numIslands") ||
+ algorithmType.classList.contains("maxIslands")
+ ) {
+ if (islandAlgo === "bfs") {
+ createStartNode(0, 0);
+ createEndNode(19, 39);
+ document
+ .querySelector(`div[row='${0}'][col='${0}']`)
+ .classList.add("islandsPathNode");
+ document
+ .querySelector(`div[row='${19}'][col='${39}']`)
+ .classList.add("islandsPathNode");
+ } else if (
+ islandAlgo === "dfs" ||
+ algorithmType.classList.contains("maxIslands")
+ ) {
+ createStartNode(0, 0);
+ createEndNode(0, 1);
+ document
+ .querySelector(`div[row='${0}'][col='${0}']`)
+ .classList.add("islandsPathNode");
+ document
+ .querySelector(`div[row='${0}'][col='${1}']`)
+ .classList.add("islandsPathNode");
+ }
+ }
};
diff --git a/code/assets/js/visual/PathFindingAlgorithms/dfs.js b/code/assets/js/visual/PathFindingAlgorithms/dfs.js
index b859b31..c885655 100644
--- a/code/assets/js/visual/PathFindingAlgorithms/dfs.js
+++ b/code/assets/js/visual/PathFindingAlgorithms/dfs.js
@@ -1,13 +1,13 @@
import { setWall } from "../Grid/createWalls.js";
import {
- rowSize,
- colSize,
- manualStart,
- dfsSteps,
- startBtn,
- clearPathBtn,
- wallBtn,
- gridContainer,
+ rowSize,
+ colSize,
+ manualStart,
+ dfsSteps,
+ startBtn,
+ clearPathBtn,
+ wallBtn,
+ gridContainer,
} from "../Grid/index.js";
let speedSlider = document.querySelector(".speedSlider");
@@ -16,110 +16,110 @@ let bool = false;
let count = 1;
//check edge cases
-const checker = (row, col) => {
- if (row >= 0 && col >= 0 && row < rowSize && col < colSize) return true;
- return false;
+export const checker = (row, col) => {
+ if (row >= 0 && col >= 0 && row < rowSize && col < colSize) return true;
+ return false;
};
// visualize algorithm
-const changeColor = (node, cost) => {
- setTimeout(() => {
- node.setAttribute("class", "chosenPath");
- node.innerHTML = cost;
- }, cost * time);
- // draw path blue
- setTimeout(() => {
- node.setAttribute("class", "pathColor");
- }, cost * time + 100);
- //draw path green
- setTimeout(() => {
- node.setAttribute("class", "chosenPath");
- }, cost * time + 1000);
+export const changeColor = (node, cost) => {
+ setTimeout(() => {
+ node.setAttribute("class", "chosenPath");
+ node.innerHTML = cost;
+ }, cost * time);
+ // draw path blue
+ setTimeout(() => {
+ node.setAttribute("class", "pathColor");
+ }, cost * time + 100);
+ //draw path green
+ setTimeout(() => {
+ node.setAttribute("class", "chosenPath");
+ }, cost * time + 1000);
};
//traverse grid
const traverse = (node, visited, cost, endNode) => {
- let row = parseInt(node.getAttribute("row"));
- let col = parseInt(node.getAttribute("col"));
- if (bool || node == endNode) {
- bool = true;
- return;
- }
+ let row = parseInt(node.getAttribute("row"));
+ let col = parseInt(node.getAttribute("col"));
+ if (bool || node == endNode) {
+ bool = true;
+ return;
+ }
- let wall = parseInt(node.getAttribute("wall"));
- if (wall == 1) return;
+ let wall = parseInt(node.getAttribute("wall"));
+ if (wall == 1) return;
- visited.push(node);
- dfsSteps.push([row, col, cost, row, col]);
- changeColor(node, cost);
+ visited.push(node);
+ dfsSteps.push([row, col, cost, row, col]);
+ changeColor(node, cost);
- // Check all sides of a node
- let cr = row,
- cc = col;
+ // Check all sides of a node
+ let cr = row,
+ cc = col;
- if (checker(cr + 1, cc)) {
- let child = document.querySelector(`div[row="${cr + 1}"][col="${cc}"]`);
- if (!visited.includes(child)) {
- traverse(child, visited, cost + 1, endNode);
- count++;
- } else {
- dfsSteps.push([row, col, cost, cr + 1, cc]);
- }
- }
- if (checker(cr, cc + 1)) {
- let child = document.querySelector(`div[row="${cr}"][col="${cc + 1}"]`);
- if (!visited.includes(child)) {
- traverse(child, visited, cost + 1, endNode);
- count++;
- } else {
- dfsSteps.push([row, col, cost, cr, cc + 1]);
- }
- }
- if (checker(cr - 1, cc)) {
- let child = document.querySelector(`div[row="${cr - 1}"][col="${cc}"]`);
- if (!visited.includes(child)) {
- traverse(child, visited, cost + 1, endNode);
- count++;
- } else {
- dfsSteps.push([row, col, cost, cr - 1, cc]);
- }
- }
- if (checker(cr, cc - 1)) {
- let child = document.querySelector(`div[row="${cr}"][col="${cc - 1}"]`);
- if (!visited.includes(child)) {
- traverse(child, visited, cost + 1, endNode);
- count++;
- } else {
- dfsSteps.push([row, col, cost, cr, cc - 1]);
- }
- }
+ if (checker(cr + 1, cc)) {
+ let child = document.querySelector(`div[row="${cr + 1}"][col="${cc}"]`);
+ if (!visited.includes(child)) {
+ traverse(child, visited, cost + 1, endNode);
+ count++;
+ } else {
+ dfsSteps.push([row, col, cost, cr + 1, cc]);
+ }
+ }
+ if (checker(cr, cc + 1)) {
+ let child = document.querySelector(`div[row="${cr}"][col="${cc + 1}"]`);
+ if (!visited.includes(child)) {
+ traverse(child, visited, cost + 1, endNode);
+ count++;
+ } else {
+ dfsSteps.push([row, col, cost, cr, cc + 1]);
+ }
+ }
+ if (checker(cr - 1, cc)) {
+ let child = document.querySelector(`div[row="${cr - 1}"][col="${cc}"]`);
+ if (!visited.includes(child)) {
+ traverse(child, visited, cost + 1, endNode);
+ count++;
+ } else {
+ dfsSteps.push([row, col, cost, cr - 1, cc]);
+ }
+ }
+ if (checker(cr, cc - 1)) {
+ let child = document.querySelector(`div[row="${cr}"][col="${cc - 1}"]`);
+ if (!visited.includes(child)) {
+ traverse(child, visited, cost + 1, endNode);
+ count++;
+ } else {
+ dfsSteps.push([row, col, cost, cr, cc - 1]);
+ }
+ }
};
//depth first search algorithm
export const dfs = (x1 = 0, y1 = 0, x2 = rowSize - 1, y2 = colSize - 1) => {
- time = speedSlider.value;
- time = 40 + (time - 1) * -2;
- gridContainer.removeEventListener("mousedown", setWall);
- gridContainer.removeEventListener("mouseover", setWall);
- let startNode = document.querySelector(`div[row='${x1}'][col='${y1}']`);
- let endNode = document.querySelector(`div[row='${x2}'][col='${y2}']`);
+ time = speedSlider.value;
+ time = 40 + (time - 1) * -2;
+ gridContainer.removeEventListener("mousedown", setWall);
+ gridContainer.removeEventListener("mouseover", setWall);
+ let startNode = document.querySelector(`div[row='${x1}'][col='${y1}']`);
+ let endNode = document.querySelector(`div[row='${x2}'][col='${y2}']`);
- //disable start and clear path buttons
- startBtn.setAttribute("disabled", "true");
- clearPathBtn.setAttribute("disabled", "true");
- wallBtn.setAttribute("disabled", "true");
+ //disable start and clear path buttons
+ startBtn.setAttribute("disabled", "true");
+ clearPathBtn.setAttribute("disabled", "true");
+ wallBtn.setAttribute("disabled", "true");
- let visited = [];
- let cost = 1;
- bool = false;
+ let visited = [];
+ let cost = 1;
+ bool = false;
- traverse(startNode, visited, cost, endNode);
+ traverse(startNode, visited, cost, endNode);
- // re-enable disabled buttons
- setTimeout(() => {
- startBtn.removeAttribute("disabled");
- clearPathBtn.removeAttribute("disabled");
- manualStart.removeAttribute("disabled");
- wallBtn.removeAttribute("disabled");
- }, count * time + 100);
+ // re-enable disabled buttons
+ setTimeout(() => {
+ startBtn.removeAttribute("disabled");
+ clearPathBtn.removeAttribute("disabled");
+ manualStart.removeAttribute("disabled");
+ wallBtn.removeAttribute("disabled");
+ }, count * time + 100);
};
diff --git a/code/assets/js/visual/PathFindingAlgorithms/findPaths.js b/code/assets/js/visual/PathFindingAlgorithms/findPaths.js
new file mode 100644
index 0000000..42aeebd
--- /dev/null
+++ b/code/assets/js/visual/PathFindingAlgorithms/findPaths.js
@@ -0,0 +1,113 @@
+import { setWall } from "../Grid/createWalls.js";
+import {
+ rowSize,
+ colSize,
+ manualStart,
+ dfsSteps,
+ visitedPaths,
+ startBtn,
+ clearPathBtn,
+ wallBtn,
+ gridContainer,
+ findNextPath,
+} from "../Grid/index.js";
+import { changeColor, checker } from "./dfs.js";
+
+let speedSlider = document.querySelector(".speedSlider");
+let time = speedSlider.value;
+let bool = false;
+let count = 1;
+
+//traverse grid
+const traverse = (node, visited, cost, endNode) => {
+ let row = parseInt(node.getAttribute("row"));
+ let col = parseInt(node.getAttribute("col"));
+ if (bool || node == endNode) {
+ bool = true;
+ return;
+ }
+
+ let wall = parseInt(node.getAttribute("wall"));
+ if (wall == 1) return;
+
+ visited.push(node);
+ visitedPaths.push([row, col]);
+ dfsSteps.push([row, col, cost, row, col]);
+ changeColor(node, cost);
+
+ // Check all sides of a node
+ let cr = row,
+ cc = col;
+
+ if (checker(cr + 1, cc)) {
+ let child = document.querySelector(`div[row="${cr + 1}"][col="${cc}"]`);
+ if (!visited.includes(child)) {
+ traverse(child, visited, cost + 1, endNode);
+ count++;
+ } else {
+ dfsSteps.push([row, col, cost, cr + 1, cc]);
+ }
+ }
+ if (checker(cr, cc + 1)) {
+ let child = document.querySelector(`div[row="${cr}"][col="${cc + 1}"]`);
+ if (!visited.includes(child)) {
+ traverse(child, visited, cost + 1, endNode);
+ count++;
+ } else {
+ dfsSteps.push([row, col, cost, cr, cc + 1]);
+ }
+ }
+ if (checker(cr - 1, cc)) {
+ let child = document.querySelector(`div[row="${cr - 1}"][col="${cc}"]`);
+ if (!visited.includes(child)) {
+ traverse(child, visited, cost + 1, endNode);
+ count++;
+ } else {
+ dfsSteps.push([row, col, cost, cr - 1, cc]);
+ }
+ }
+ if (checker(cr, cc - 1)) {
+ let child = document.querySelector(`div[row="${cr}"][col="${cc - 1}"]`);
+ if (!visited.includes(child)) {
+ traverse(child, visited, cost + 1, endNode);
+ count++;
+ } else {
+ dfsSteps.push([row, col, cost, cr, cc - 1]);
+ }
+ }
+};
+
+//depth first search algorithm
+export const findPaths = (
+ x1 = 0,
+ y1 = 0,
+ x2 = rowSize - 1,
+ y2 = colSize - 1
+) => {
+ time = speedSlider.value;
+ time = 40 + (time - 1) * -2;
+ gridContainer.removeEventListener("mousedown", setWall);
+ gridContainer.removeEventListener("mouseover", setWall);
+ let startNode = document.querySelector(`div[row='${x1}'][col='${y1}']`);
+ let endNode = document.querySelector(`div[row='${x2}'][col='${y2}']`);
+
+ //disable start and clear path buttons
+ startBtn.setAttribute("disabled", "true");
+ clearPathBtn.setAttribute("disabled", "true");
+ wallBtn.setAttribute("disabled", "true");
+
+ let visited = [];
+ let cost = 1;
+ bool = false;
+
+ traverse(startNode, visited, cost, endNode);
+
+ // re-enable disabled buttons
+ setTimeout(() => {
+ startBtn.removeAttribute("disabled");
+ clearPathBtn.removeAttribute("disabled");
+ manualStart.removeAttribute("disabled");
+ findNextPath.removeAttribute("disabled");
+ wallBtn.removeAttribute("disabled");
+ }, count * time + 100);
+};
diff --git a/code/dfs-visual.html b/code/dfs-visual.html
index 28da8d2..263dc66 100644
--- a/code/dfs-visual.html
+++ b/code/dfs-visual.html
@@ -1,249 +1,320 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Depth first search path finding algorithm.
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Depth first search path finding algorithm.
-
-
-
-
-
-
-
-
-
-
-
-
-
This is an empty path without any walls, you can click is to add obstacles/walls.
-
-
-
A
-
Start Node -> this is the starting point(source),
- search for a path starts here.
-
-
-
B
-
End Node -> where the search stops when a path to destination has been found
-
-
-
-
These act as obstacles, walls. On a real map these may be buildings or structures that may
- block
- a shorter path to a destination.
-
-
-
7
-
After the algorithm is complete, we have arrived at the destination, now the shortest path is
- highlighted in green with the cost of path written written in black inside the path.
-
-
-
-
-
-
Depth first traversal.
-
-
-
- This algorithm starts its search at the root and
- explores one of its children's subtree and then moves
- on to the next child's subtree and etcetera
- The idea used is to go as deep into the graph as
- possible and backtrack once we reach a vertex with
- unvisited neighbors.
- That is, start search at one vertex, after visiting
- the vertex, perform dfs for each unvisited adjacent
- vertex. In this way we visit all vertices reachable
- from the starting vertex.
- We use a stack data structure.
-
-
-
-
Algorithm
-
- 1. Mark the current node as visited(initially
- current node is the root node).
-
-
- 2. Check if current node is the end node, If so,
- then return it.
-
-
- 3. Iterate over children nodes of current node,
- and do the following:
-
-
- 1. Check if a child node is not visited.
-
-
- 2.If so, then, mark it as visited.
-
-
- 3. Go to it's sub graph recursively until you
- find the end node(In other words, do the same
- steps here passing the child node as the current
- node in the next recursive call).
-
-
- 4. If the child node has the end node in this
- sub graph, then, return it.
-
-
- 4. If end node is not found, then end node is
- not in the graph!
-
-
-
-
Computational complexity
- This algorithm takes
O(V + E) where v is the number of
- vertices and e is the number of edges.
-
-
-
Applications
-
- topological sorting.
- bipartite graph testing.
- finding strongly connected components.
-
- solving puzzles that can only have one
- solution.
-
- detecting cycles in a graph.
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
+
+
+
+
+
+
+
+
+
+
+
+
+ This is an empty path without any walls, you can click is to add
+ obstacles/walls.
+
+
+
+
A
+
+
+ Start Node -> this is the starting point(source), search for a
+ path starts here.
+
+
+
+
B
+
+
+ End Node -> where the search stops when a path to destination has
+ been found
+
+
+
+
+
+
+ These act as obstacles, walls. On a real map these may be
+ buildings or structures that may block a shorter path to a
+ destination.
+
+
+
+
7
+
+
+ After the algorithm is complete, we have arrived at the
+ destination, now the shortest path is highlighted in green with
+ the cost of path written written in black inside the path.
+
+
+
+
+
+
+
Depth first traversal.
+
+
+
+ This algorithm starts its search at the root and explores one of
+ its children's subtree and then moves on to the next child's
+ subtree and etcetera
+ The idea used is to go as deep into the graph as possible and
+ backtrack once we reach a vertex with unvisited neighbors.
+
+ That is, start search at one vertex, after visiting the vertex,
+ perform dfs for each unvisited adjacent vertex. In this way we
+ visit all vertices reachable from the starting vertex.
+ We use a stack data structure.
+
+
+
+
Algorithm
+
+ 1. Mark the current node as visited(initially current node is
+ the root node).
+
+
+ 2. Check if current node is the end node, If so, then return it.
+
+
+ 3. Iterate over children nodes of current node, and do the
+ following:
+
+
1. Check if a child node is not visited.
+
2.If so, then, mark it as visited.
+
+ 3. Go to it's sub graph recursively until you find the end
+ node(In other words, do the same steps here passing the child
+ node as the current node in the next recursive call).
+
+
+ 4. If the child node has the end node in this sub graph, then,
+ return it.
+
+
+ 4. If end node is not found, then end node is not in the graph!
+
+
+
+
Computational complexity
+ This algorithm takes
O(V + E) where v is the
+ number of vertices and e is the number of edges.
+
+
+
Applications
+
+ topological sorting.
+ bipartite graph testing.
+ finding strongly connected components.
+ solving puzzles that can only have one solution.
+ detecting cycles in a graph.
+
+
+
+
+
+
+
+
+
+
+
+