A*路径查找问题处理(Java)
我对编程还很陌生,不过在完成了一系列教程之后,我最终得到了这段代码,用于处理我正在尝试制作的一个小游戏的寻路 If适用于小而直的路径,但不适用于复杂的路径(它会冻结并且A*路径查找问题处理(Java),java,processing,a-star,Java,Processing,A Star,我对编程还很陌生,不过在完成了一系列教程之后,我最终得到了这段代码,用于处理我正在尝试制作的一个小游戏的寻路 If适用于小而直的路径,但不适用于复杂的路径(它会冻结并且closedSet.size()在一个只有54*46的网格中变得大于70000) 请注意,wall是真的,这取决于碰撞瓷砖的高度,因此从一点来说可能是真的,但从另一点来说可能是假的。这就是问题所在吗 import java.util.*; int heuristic(int x,int y,int x_,int y_){ i
closedSet.size()
在一个只有54*46的网格中变得大于70000)
请注意,wall
是真的,这取决于碰撞瓷砖的高度,因此从一点来说可能是真的,但从另一点来说可能是假的。这就是问题所在吗
import java.util.*;
int heuristic(int x,int y,int x_,int y_){
int dstX = abs(x - x_);
int dstY = abs(y - y_);
if(dstX > dstY){
return 14*dstY + 10*(dstX - dstY);
}else{
return 14*dstX + 10*(dstY - dstX);
}
}
boolean wall(int x, int y, int x_, int y_){
Tile tileS = getTile(x, y);
Tile tileCurr = getTile(x_, y_);
if(abs(tileS.altitude - tileCurr.altitude) > 1 || tileS.altitude < 1){
return true;
}else{
return false;
}
}
ArrayList<PVector> findPath(int startx, int starty, int endx, int endy){
Queue<Spot> openSet = new PriorityQueue<Spot>(fComparator);
ArrayList<Spot> closedSet = new ArrayList<Spot>();
Spot start = new Spot(startx, starty);
Spot end = new Spot(endx, endy);
Spot current = start;
openSet.add(start);
while(!openSet.isEmpty()){
current = openSet.poll();
closedSet.add(current);
println(closedSet.size());
if (current.x == end.x && current.y == end.y) {
break;
}
ArrayList<Spot> successors = new ArrayList<Spot>();
for(int i = 0; i < collidingTiles.size(); i++){
JSONObject difference = collidingTiles.getJSONObject(i);
/*JSONArray such as
[{x: -1, y: -1},{x: 0, y: -1},...](not including {x:0, y:0})
*/
int x_ = difference.getInt("x");
int y_ = difference.getInt("y");
int x = x_ + current.x;
int y = y_ + current.y;
if(x >= 0 && x <= map.columns && y >= 0 && y <= map.rows){
Spot s = new Spot(x, y);
successors.add(s);
}
}
for(Spot s: successors){
if (!closedSet.contains(s) && !wall(s.x, s.y, current.x, current.y)) {
int tempG = current.g + heuristic(s.x, s.y, current.x, current.y);
if(tempG < s.g || !openSet.contains(s)){
s.g = tempG;
s.h = heuristic(s.x, s.y, end.x, end.y);
s.f = s.g + s.h;
s.parent = current;
if (!openSet.contains(s)) {
openSet.add(s);
}
}
}
}
successors.clear();
}
ArrayList<PVector> path = new ArrayList<PVector>();
Spot temp = current;
PVector tile = new PVector(temp.x + 0.5, temp.y + 0.5);
path.add(tile);
while (temp.parent != null) {
tile = new PVector(temp.parent.x + 0.5, temp.parent.y + 0.5);
path.add(0, tile);
temp = temp.parent;
}
return path;
}
class Spot{
int x, y;
int f, g, h = 0;
Spot parent;
Spot(int x_, int y_){
x = x_;
y = y_;
}
}
Comparator<Spot> fComparator = new Comparator<Spot>() {
@Override
int compare(Spot s1, Spot s2) {
return s1.f - s2.f;
}
};
import java.util.*;
整数启发式(整数x,整数y,整数x,整数y){
int-dstX=abs(x-x_);
int-dstY=abs(y-y_);
如果(dstX>dstY){
返回14*dstY+10*(dstX-dstY);
}否则{
返回14*dstX+10*(dstY-dstX);
}
}
布尔墙(intx,inty,intx,inty){
瓷砖=getTile(x,y);
tileCurr=getTile(x,y);
如果(绝对高度(平铺高度-平铺高度)>1 | |平铺高度<1){
返回true;
}否则{
返回false;
}
}
ArrayList findPath(int-startx、int-starty、int-endx、int-endy){
Queue openSet=new PriorityQueue(fComparator);
ArrayList closedSet=新的ArrayList();
点启动=新点(startx、starty);
点端点=新点(端点,端点);
点电流=启动;
添加(开始);
而(!openSet.isEmpty()){
current=openSet.poll();
closedSet.add(当前);
println(closedSet.size());
if(current.x==end.x&¤t.y==end.y){
打破
}
ArrayList继承者=新的ArrayList();
对于(int i=0;i=0&&x=0&&y
closedSet.size()
在仅为54*46的网格中大于70000
您的代码确实实现了一些逻辑
“如果某个节点已关闭,则不再处理该节点”,以及
如果节点已在开放集中,请比较G分数
但在这两种情况下,它都不起作用,因为Spot
没有实现equals
,因此contains
正在比较引用等式,它将始终为false。因此,实现Spot.equals
。具体地说,让它只比较x
和y
,因为f/g/h/parent
对于为此目的被视为相等的节点,允许不同
即使有效,在数组列表上使用contains
和PriorityQueue
对性能也不是很好。对于封闭列表,使用HashSet
很容易(当然,也可以实现Spot.hashCode
,在某种程度上只取决于x
和y
)。对于开放列表,摆脱慢速包含
需要更多的工作。可以使用的一个技巧是手动维护二进制堆,另外还有一个HashMap
,它将x,y
对映射到相应节点所在堆中的索引。手动维护堆的原因是具有每当节点在队列中移动时,必须更新hMap
,而正常的PriorityQueue
不具备此类功能
从性能的角度来看,寻找继任者作品的方式也让我感到担忧,但我看不到细节
请注意,wall
是正确的,这取决于碰撞瓷砖的高度,因此从一点来说可能是正确的,但从另一点来说可能是错误的。这是问题所在吗
import java.util.*;
int heuristic(int x,int y,int x_,int y_){
int dstX = abs(x - x_);
int dstY = abs(y - y_);
if(dstX > dstY){
return 14*dstY + 10*(dstX - dstY);
}else{
return 14*dstX + 10*(dstY - dstX);
}
}
boolean wall(int x, int y, int x_, int y_){
Tile tileS = getTile(x, y);
Tile tileCurr = getTile(x_, y_);
if(abs(tileS.altitude - tileCurr.altitude) > 1 || tileS.altitude < 1){
return true;
}else{
return false;
}
}
ArrayList<PVector> findPath(int startx, int starty, int endx, int endy){
Queue<Spot> openSet = new PriorityQueue<Spot>(fComparator);
ArrayList<Spot> closedSet = new ArrayList<Spot>();
Spot start = new Spot(startx, starty);
Spot end = new Spot(endx, endy);
Spot current = start;
openSet.add(start);
while(!openSet.isEmpty()){
current = openSet.poll();
closedSet.add(current);
println(closedSet.size());
if (current.x == end.x && current.y == end.y) {
break;
}
ArrayList<Spot> successors = new ArrayList<Spot>();
for(int i = 0; i < collidingTiles.size(); i++){
JSONObject difference = collidingTiles.getJSONObject(i);
/*JSONArray such as
[{x: -1, y: -1},{x: 0, y: -1},...](not including {x:0, y:0})
*/
int x_ = difference.getInt("x");
int y_ = difference.getInt("y");
int x = x_ + current.x;
int y = y_ + current.y;
if(x >= 0 && x <= map.columns && y >= 0 && y <= map.rows){
Spot s = new Spot(x, y);
successors.add(s);
}
}
for(Spot s: successors){
if (!closedSet.contains(s) && !wall(s.x, s.y, current.x, current.y)) {
int tempG = current.g + heuristic(s.x, s.y, current.x, current.y);
if(tempG < s.g || !openSet.contains(s)){
s.g = tempG;
s.h = heuristic(s.x, s.y, end.x, end.y);
s.f = s.g + s.h;
s.parent = current;
if (!openSet.contains(s)) {
openSet.add(s);
}
}
}
}
successors.clear();
}
ArrayList<PVector> path = new ArrayList<PVector>();
Spot temp = current;
PVector tile = new PVector(temp.x + 0.5, temp.y + 0.5);
path.add(tile);
while (temp.parent != null) {
tile = new PVector(temp.parent.x + 0.5, temp.parent.y + 0.5);
path.add(0, tile);
temp = temp.parent;
}
return path;
}
class Spot{
int x, y;
int f, g, h = 0;
Spot parent;
Spot(int x_, int y_){
x = x_;
y = y_;
}
}
Comparator<Spot> fComparator = new Comparator<Spot>() {
@Override
int compare(Spot s1, Spot s2) {
return s1.f - s2.f;
}
};
这很好,A*可以容忍一个点可以从一侧到达,但不能从另一侧到达。它不能本机考虑的是,如果一个点到达的方向会影响该节点的后续节点,但在这里不会发生这种情况。我看到很多整数,我应该看到地图坐标,这些坐标是真的还是真的它们是你根据模型计算距离的另一种方法?根据经验,你应该使用float或类似的格式来存储地图坐标,特别是如果你要根据这些来计算东西的话。你的帖子写得很好,但由于大部分都是调试,你会提高获得大量帮助的机会。当然,这不是一个简单的问题永远都有可能,但至少能够运行它会让更多处于更好位置的人提供帮助。非常感谢@harold