/// /** * 计算路径给定的IAstarGraph和开始/目标位置 */ class AStarPathfinder { public static search(graph: IAstarGraph, start: T, goal: T){ let foundPath = false; let cameFrom = new Map(); cameFrom.set(start, start); let costSoFar = new Map(); let frontier = new PriorityQueue>(1000); frontier.enqueue(new AStarNode(start), 0); costSoFar.set(start, 0); while (frontier.count > 0){ let current = frontier.dequeue(); if (JSON.stringify(current.data) == JSON.stringify(goal)){ foundPath = true; break; } graph.getNeighbors(current.data).forEach(next => { let newCost = costSoFar.get(current.data) + graph.cost(current.data, next); if (!this.hasKey(costSoFar, next) || newCost < costSoFar.get(next)){ costSoFar.set(next, newCost); let priority = newCost + graph.heuristic(next, goal); frontier.enqueue(new AStarNode(next), priority); cameFrom.set(next, current.data); } }); } return foundPath ? this.recontructPath(cameFrom, start, goal) : null; } private static hasKey(map: Map, compareKey: T){ let iterator = map.keys(); let r: IteratorResult; while (r = iterator.next() , !r.done) { if (JSON.stringify(r.value) == JSON.stringify(compareKey)) return true; } return false; } private static getKey(map: Map, compareKey: T){ let iterator = map.keys(); let valueIterator = map.values(); let r: IteratorResult; let v: IteratorResult; while (r = iterator.next(), v = valueIterator.next(), !r.done) { if (JSON.stringify(r.value) == JSON.stringify(compareKey)) return v.value; } return null; } public static recontructPath(cameFrom: Map, start: T, goal: T): T[]{ let path = []; let current = goal; path.push(goal); while (current != start){ current = this.getKey(cameFrom, current); path.push(current); } path.reverse(); return path; } } /** * 使用PriorityQueue需要的额外字段将原始数据封装在一个小类中 */ class AStarNode extends PriorityQueueNode { public data: T; constructor(data: T){ super(); this.data = data; } }