134 lines
3.4 KiB
JavaScript
134 lines
3.4 KiB
JavaScript
let cols = 5; //columns in the grid
|
|
let rows = 5; //rows in the grid
|
|
|
|
let grid = new Array(cols); //array of all the grid points
|
|
|
|
let openSet = []; //array containing unevaluated grid points
|
|
let closedSet = []; //array containing completely evaluated grid points
|
|
|
|
let start; //starting grid point
|
|
let end; // ending grid point (goal)
|
|
let path = [];
|
|
|
|
//heuristic we will be using - Manhattan distance
|
|
//for other heuristics visit - https://theory.stanford.edu/~amitp/GameProgramming/Heuristics.html
|
|
function heuristic(position0, position1) {
|
|
let d1 = Math.abs(position1.x - position0.x);
|
|
let d2 = Math.abs(position1.y - position0.y);
|
|
|
|
return d1 + d2;
|
|
}
|
|
|
|
//constructor function to create all the grid points as objects containind the data for the points
|
|
function GridPoint(x, y) {
|
|
this.x = x; //x location of the grid point
|
|
this.y = y; //y location of the grid point
|
|
this.f = 0; //total cost function
|
|
this.g = 0; //cost function from start to the current grid point
|
|
this.h = 0; //heuristic estimated cost function from current grid point to the goal
|
|
this.neighbors = []; // neighbors of the current grid point
|
|
this.parent = undefined; // immediate source of the current grid point
|
|
|
|
// update neighbors array for a given grid point
|
|
this.updateNeighbors = function (grid) {
|
|
let i = this.x;
|
|
let j = this.y;
|
|
if (i < cols - 1) {
|
|
this.neighbors.push(grid[i + 1][j]);
|
|
}
|
|
if (i > 0) {
|
|
this.neighbors.push(grid[i - 1][j]);
|
|
}
|
|
if (j < rows - 1) {
|
|
this.neighbors.push(grid[i][j + 1]);
|
|
}
|
|
if (j > 0) {
|
|
this.neighbors.push(grid[i][j - 1]);
|
|
}
|
|
};
|
|
}
|
|
|
|
//initializing the grid
|
|
function init() {
|
|
//making a 2D array
|
|
for (let i = 0; i < cols; i++) {
|
|
grid[i] = new Array(rows);
|
|
}
|
|
|
|
for (let i = 0; i < cols; i++) {
|
|
for (let j = 0; j < rows; j++) {
|
|
grid[i][j] = new GridPoint(i, j);
|
|
}
|
|
}
|
|
|
|
for (let i = 0; i < cols; i++) {
|
|
for (let j = 0; j < rows; j++) {
|
|
grid[i][j].updateNeighbors(grid);
|
|
}
|
|
}
|
|
|
|
start = grid[0][0];
|
|
end = grid[cols - 1][rows - 1];
|
|
|
|
openSet.push(start);
|
|
|
|
console.log(grid);
|
|
}
|
|
|
|
//A star search implementation
|
|
|
|
export function search() {
|
|
init();
|
|
while (openSet.length > 0) {
|
|
//assumption lowest index is the first one to begin with
|
|
let lowestIndex = 0;
|
|
for (let i = 0; i < openSet.length; i++) {
|
|
if (openSet[i].f < openSet[lowestIndex].f) {
|
|
lowestIndex = i;
|
|
}
|
|
}
|
|
let current = openSet[lowestIndex];
|
|
|
|
if (current === end) {
|
|
let temp = current;
|
|
path.push(temp);
|
|
while (temp.parent) {
|
|
path.push(temp.parent);
|
|
temp = temp.parent;
|
|
}
|
|
console.log("DONE!");
|
|
// return the traced path
|
|
return path.reverse();
|
|
}
|
|
|
|
//remove current from openSet
|
|
openSet.splice(lowestIndex, 1);
|
|
//add current to closedSet
|
|
closedSet.push(current);
|
|
|
|
let neighbors = current.neighbors;
|
|
|
|
for (let i = 0; i < neighbors.length; i++) {
|
|
let neighbor = neighbors[i];
|
|
|
|
if (!closedSet.includes(neighbor)) {
|
|
let possibleG = current.g + 1;
|
|
|
|
if (!openSet.includes(neighbor)) {
|
|
openSet.push(neighbor);
|
|
} else if (possibleG >= neighbor.g) {
|
|
continue;
|
|
}
|
|
|
|
neighbor.g = possibleG;
|
|
neighbor.h = heuristic(neighbor, end);
|
|
neighbor.f = neighbor.g + neighbor.h;
|
|
neighbor.parent = current;
|
|
}
|
|
}
|
|
}
|
|
|
|
//no solution by default
|
|
return [];
|
|
}
|