fix(pathfinding): use real cost in A* instead of greedy heuristic
updateNeighborNode overwrote gScore with the heuristic, so A* behaved like greedy best-first search and found longer paths than Dijkstra.
This commit is contained in:
1 parent
331d653ae6
commit
ce7db0f376
2 files changed
+24
-1
No files matched your search
@@ -117,6 +117,30 @@ describe('PathfindingService', () => {
|
|||||||
expect(nodesInShortestPathOrder[0]).toBe(start);
|
expect(nodesInShortestPathOrder[0]).toBe(start);
|
||||||
expect(nodesInShortestPathOrder[nodesInShortestPathOrder.length - 1]).toBe(end);
|
expect(nodesInShortestPathOrder[nodesInShortestPathOrder.length - 1]).toBe(end);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('finds a path as short as Dijkstra on random grids', () => {
|
||||||
|
let seed = 12345;
|
||||||
|
const random = (): number => (seed = (seed * 1664525 + 1013904223) % 4294967296) / 4294967296;
|
||||||
|
for (let run = 0; run < 20; run++) {
|
||||||
|
const build = (): Node[][] => {
|
||||||
|
seed = 1000 + run;
|
||||||
|
const grid = createGrid(20, 20);
|
||||||
|
for (const node of grid.flat()) {
|
||||||
|
node.isWall = random() < 0.3;
|
||||||
|
}
|
||||||
|
grid[0][0].isWall = false;
|
||||||
|
grid[19][19].isWall = false;
|
||||||
|
return grid;
|
||||||
|
};
|
||||||
|
const astarGrid = build();
|
||||||
|
const dijkstraGrid = build();
|
||||||
|
|
||||||
|
const astar = service.aStar(astarGrid, astarGrid[0][0], astarGrid[19][19]);
|
||||||
|
const dijkstra = service.dijkstra(dijkstraGrid, dijkstraGrid[0][0], dijkstraGrid[19][19]);
|
||||||
|
|
||||||
|
expect(astar.nodesInShortestPathOrder.length).toBe(dijkstra.nodesInShortestPathOrder.length);
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('findPath', () => {
|
describe('findPath', () => {
|
||||||
|
|||||||
@@ -155,7 +155,6 @@ export class PathfindingService {
|
|||||||
private updateNeighborNode(neighbor: Node, currentNode: Node, tentativeGScore: number, endNode: Node, openSet: Node[]) {
|
private updateNeighborNode(neighbor: Node, currentNode: Node, tentativeGScore: number, endNode: Node, openSet: Node[]) {
|
||||||
neighbor.linkedNode = currentNode;
|
neighbor.linkedNode = currentNode;
|
||||||
neighbor.nodeData = tentativeGScore;
|
neighbor.nodeData = tentativeGScore;
|
||||||
neighbor['nodeData'] = this.calculateHeuristic(neighbor, endNode);
|
|
||||||
neighbor['hScore'] = this.calculateHeuristic(neighbor, endNode);
|
neighbor['hScore'] = this.calculateHeuristic(neighbor, endNode);
|
||||||
neighbor['fScore'] = neighbor.nodeData + neighbor['hScore'];
|
neighbor['fScore'] = neighbor.nodeData + neighbor['hScore'];
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user