A* Search

index.html
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>p5.js example</title>
<style> body {padding: 10; margin: 10;} </style>
<script src="./p5.min.js"></script>
<script src="./p5.dom.min.js"></script>
<script src="./p5.sound.min.js"></script>
<script src="./sketch.js"></script>
</head>
<body>
</body>
</html>
sketch.js
// https://github.com/CodingTrain/AStar/blob/master/sketch.js
let cols = 25;
let rows = 25;
let grid = new Array(cols);
let squareSize = 10;
let a = { x: 0, y: 0 }
let b = { x: 0, y: 1 }
let aTo = { x: 0, y: 0 }
let bTo = { x: 0, y: 1 }
let openSet = [];
let closedSet = [];
let start;
let end;
let path = [];
function Spot(i, j) {
this.i = i;
this.j = j;
this.f = 0;
this.g = 0; // amount of time, cost, it takes from 0
this.h = 0; // amount of time, cost, it takes to the end
this.neighbors = [];
this.previous = undefined;
this.wall = false;
if (random(1) < 0.3) {
this.wall = true;
}
this.show = function(color) {
fill(color);
// noStroke();
if (this.wall) {
fill(0);
}
rect(this.i * squareSize, this.j * squareSize, squareSize, squareSize);
}
this.addNeighbors = function(grid) {
const i = this.i;
const j = this.j;
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]);
if (i > 0 && j > 0)
this.neighbors.push(grid[i - 1][j - 1]);
if (i < cols - 1 && j > 0)
this.neighbors.push(grid[i + 1][j - 1]);
if (i > 0 && j < rows - 1)
this.neighbors.push(grid[i - 1][j + 1]);
if (i < cols - 1 && j < rows - 1)
this.neighbors.push(grid[i + 1][j + 1]);
}
}
function setup() {
createCanvas(500, 500);
frameRate(10);
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 Spot(i, j);
}
}
for (let i = 0; i < cols; i++) {
for (let j = 0; j < rows; j++) {
grid[i][j].addNeighbors(grid);
}
}
start = grid[cols - 1][rows - 1];
end = grid[0][0];
start.wall = false;
end.wall = false;
openSet.push(start);
}
function draw() {
if (openSet.length > 0) {
let lowestIndex = 0;
for (let i = 0; i < openSet.length; i++) {
if (openSet[i].f < openSet[lowestIndex].f)
lowestIndex = i;
}
var current = openSet[lowestIndex];
if (current === end) {
console.log("Done");
noLoop();
// return;
}
// remove from open set when current exists
for (let i = openSet.length - 1; i >= 0; i--) {
if (openSet[i] === current)
openSet.splice(i, 1);
}
closedSet.push(current);
// add candidates where to go
let neighbors = current.neighbors;
for (let i = 0; i < neighbors.length; i++) {
let neighbor = neighbors[i];
if (!closedSet.includes(neighbor) && !neighbor.wall) {
let tempG = current.g + 1;
let foundNewPath = false;
if (openSet.includes(neighbor)) {
if (tempG < neighbor.g) { // we found better shorter distance to the end
neighbor.g = tempG;
foundNewPath = true;
}
} else {
neighbor.g = tempG;
foundNewPath = true;
openSet.push(neighbor);
}
if (foundNewPath) {
neighbor.h = heuristic(neighbor, end);
neighbor.f = neighbor.g + neighbor.h;
neighbor.previous = current;
}
}
}
} else {
console.log("No solution.");
noLoop();
// return;
// no solution
}
for (let i = 0; i < cols; i++) {
for (let j = 0; j < grid[i].length; j++) {
grid[i][j].show(color(255));
}
}
for (const closed of closedSet) {
closed.show(color(255, 0, 0));
}
for (const open of openSet) {
open.show(color(0, 255, 0));
}
path = [];
let temp = current;
path.push(temp);
while (temp.previous) {
path.push(temp.previous);
temp = temp.previous;
}
for (const p of path) {
p.show(color(0, 0, 255));
}
}
function heuristic(a, b) {
let d = dist(a.i, a.j, b.i, b.j);
// let d = abs(a.i - b.i) + abs(a.j - b.j);
return d;
}
function mouseClicked() {
let x = int(mouseX / squareSize);
let y = int(mouseY / squareSize);
if (x < grid.length &&
y < grid[0].length &&
grid[x][y] != 1) {
aTo.i = x;
aTo.j = y;
}
return false;
}
function keyPressed() {
}Last updated