我正在使用 A* 在我正在处理的 Java 项目中进行寻路。不过,我尝试实施它有一些问题。它不仅有点慢,而且有时会遇到永远找不到路径的无限循环问题。我相信这是我的代码中某个地方的错误的结果。路径查找器在 3d 空间上运行,并使用基本启发式(如果需要,我可以提供代码,但是,它只是计算两点之间的距离平方)。
代码在这里:
public class BinaryPathFinder extends PathFinder {
private final PriorityBuffer<PathNode> paths;
private final HashMap<Point, Integer> mindists = new HashMap<Point, Integer>();
private final ComparableComparator<PathNode> comparator = new ComparableComparator<PathNode>();
private Path lastPath;
private Point start, end;
private final byte SIZE_INCREMENT = 20;
public BinaryPathFinder(PathHeuristic heuristic,
Pathplayer player, PathWorld pathWorld) {
super(heuristic, player, pathWorld);
this.world = pathWorld.getWorld();
paths = new PriorityBuffer<PathNode>(8000, comparator);
}
@Override
public boolean find() {
try {
PathNode root = new PathNode();
root.point = start;
calculateTotalCost(root, start, start, false);
expand(root);
while (true) {
PathNode p = paths.remove();
if (p == null)
return false;
Point last = p.point;
if (isGoal(last)) {
calculatePath(p); // Iterate back.
this.mindists.clear();
this.paths.clear();
return true;
}
expand(p);
}
} catch (Exception e) {
e.printStackTrace();
}
this.mindists.clear();
this.paths.clear();
return false;
}
@Override
public Path path() {
return this.lastPath;
}
@Override
public void recalculate(Point start, Point end) {
this.start = start;
this.end = end;
this.lastPath = null;
}
private void expand(PathNode path) {
Point p = path.point;
Integer min = mindists.get(p);
if (min == null || min > path.totalCost)
mindists.put(p, path.totalCost);
else
return;
Point[] successors = generateSuccessors(p);
for (Point t : successors) {
if (t == null)
continue;
PathNode newPath = new PathNode(path);
newPath.point = t;
calculateTotalCost(newPath, p, t, false);
paths.add(newPath);
}
}
private void calculatePath(PathNode p) {
Point[] retPath = new Point[20];
Point[] copy = null;
short added = 0;
for (PathNode i = p; i != null; i = i.parent) {
if (added >= retPath.length) {
copy = new Point[retPath.length + SIZE_INCREMENT];
System.arraycopy(retPath, 0, copy, 0, retPath.length);
retPath = copy;
}
retPath[added++] = i.point;
}
this.lastPath = new Path(retPath);
}
private int calculateHeuristic(Point start, Point end, boolean endPoint) {
return this.heuristic.calculate(start, end, this.pathWorld,
this.player, endPoint);
}
private int calculateTotalCost(PathNode p, Point from, Point to,
boolean endPoint) {
int g = (calculateHeuristic(from, to, endPoint) + ((p.parent != null) ? p.parent.cost
: 0));
int h = calculateHeuristic(from, to, endPoint);
p.cost = g;
p.totalCost = (g + h);
return p.totalCost;
}
private Point[] generateSuccessors(Point point) {
Point[] points = new Point[27];
Point temp = null;
byte counter = -1;
for (int x = point.x - 1; x <= point.x + 1; ++x) {
for (int y = point.y + 1; y >= point.y - 1; --y) {
for (int z = point.z - 1; z <= point.z + 1; ++z) {
++counter;
if (x == 0 && y == 0 && z == 0)
continue;
temp = new Point(x, y, z);
if (valid(temp))
points[counter] = temp;
}
}
}
return points;
}
private boolean isGoal(Point last) {
return last.equals(this.end);
}
}
路径节点在这里:
public class PathNode implements Comparable<PathNode> {
public Point point;
public final PathNode parent;
public int cost;
public int totalCost;
public PathNode(Point point, PathNode parent, short cost, short totalCost) {
this.point = point;
this.parent = parent;
this.cost = cost;
this.totalCost = totalCost;
}
public PathNode() {
this.point = null;
this.parent = null;
this.cost = this.totalCost = 0;
}
public PathNode(PathNode path) {
this.parent = path;
this.cost = path.cost;
this.totalCost = path.totalCost;
}
@Override
public int compareTo(PathNode node) {
int result = node.totalCost - node.cost;
if (result > node.totalCost)
return 1;
else if (result == 0)
return 0;
else
return -1;
}
}
Point 只是一个定义整数 x、y、z 值的包装类。
我正在使用 Apache Commons PriorityBuffer 来存储路径节点。帮助将不胜感激 - 在此先感谢!