UNPKG

@esengine/pathfinding

Version:

寻路算法库,支持A*、广度优先等算法,适用于Cocos Creator、Laya等游戏引擎

110 lines (93 loc) 3.15 kB
import { IVector2, Vector2Utils } from '../../../Types/IVector2'; import { IUnweightedGraph } from './IUnweightedGraph'; /** * 广度优先搜索算法实现 * 适用于无权图,保证找到最短路径(步数最少) */ export class BreadthFirstPathfinder { /** * 使用广度优先搜索算法搜索路径 * @param graph 图对象 * @param start 起始节点 * @param goal 目标节点 * @param cameFrom 可选的路径记录Map * @returns 是否找到路径 */ static search<T extends IVector2>( graph: IUnweightedGraph<T>, start: T, goal: T, cameFrom?: Map<number, T> ): boolean { const frontier: T[] = []; const visited = new Set<number>(); const pathMap = cameFrom || new Map<number, T>(); const startHash = Vector2Utils.toHash(start); const goalHash = Vector2Utils.toHash(goal); if (startHash === goalHash) { return true; } frontier.push(start); visited.add(startHash); while (frontier.length > 0) { const current = frontier.shift()!; const currentHash = Vector2Utils.toHash(current); if (currentHash === goalHash) { return true; } for (const neighbor of graph.getNeighbors(current)) { const neighborHash = Vector2Utils.toHash(neighbor); if (visited.has(neighborHash)) { continue; } visited.add(neighborHash); pathMap.set(neighborHash, current); frontier.push(neighbor); } } return false; } /** * 搜索并返回完整路径 * @param graph 图对象 * @param start 起始节点 * @param goal 目标节点 * @returns 路径数组,如果没找到则返回空数组 */ static searchPath<T extends IVector2>( graph: IUnweightedGraph<T>, start: T, goal: T ): T[] { const cameFrom = new Map<number, T>(); if (this.search(graph, start, goal, cameFrom)) { return this.reconstructPath(cameFrom, start, goal); } return []; } /** * 重构路径 * @param cameFrom 路径记录Map * @param start 起始节点 * @param goal 目标节点 * @returns 完整路径 */ static reconstructPath<T extends IVector2>( cameFrom: Map<number, T>, start: T, goal: T ): T[] { const path: T[] = []; let current = goal; const startHash = Vector2Utils.toHash(start); while (Vector2Utils.toHash(current) !== startHash) { path.unshift(current); const currentHash = Vector2Utils.toHash(current); const parent = cameFrom.get(currentHash); if (!parent) break; current = parent; } path.unshift(start); return path; } }