Java A*(A星)-算法|有墙时如何返回?

Java A*(A星)-算法|有墙时如何返回?,java,data-structures,processing,path-finding,a-star,Java,Data Structures,Processing,Path Finding,A Star,我目前正在尝试实现A*(A星)算法。当我没有墙的时候,当它只需要沿着墙走的时候,我已经让它工作了。我现在的问题是,当我把起点放在墙里面时,我的算法是无限计算的,因为我认为它不会倒转。你们能帮帮我吗 以下是节点类的代码: int[][] mMap; // if there is a wall => 1 int[][] mAStarField; ArrayList<AStarNode> mAStarPath; public class AStarNode implements

我目前正在尝试实现A*(A星)算法。当我没有墙的时候,当它只需要沿着墙走的时候,我已经让它工作了。我现在的问题是,当我把起点放在墙里面时,我的算法是无限计算的,因为我认为它不会倒转。你们能帮帮我吗

以下是节点类的代码:

int[][] mMap; // if there is a wall => 1

int[][] mAStarField;
ArrayList<AStarNode> mAStarPath;

public class AStarNode implements Comparable<AStarNode>{ 
  public int x; 
  public int y; 
  public float c;
  public AStarNode p; 
  public AStarNode(int x, int y, float c, AStarNode p) { 
    this.x = x; //X pos
    this.y = y; //Y pos
    this.c = c; //Cost to get to the node
    this.p = p; //Parent of the node
  }
  //override the compareTo method 
  public int compareTo(AStarNode node) 
  { 
    if (c == node.c) 
      return 0; 
    else if (c > node.c) 
      return 1; 
    else
      return -1; 
    } 
  
  
} 

public class Node { 
  public int x; 
  public int y; 
  public int z; 
  public int w; 
  public Node(int x, int y, int z, int w) { 
    this.x = x; 
    this.y = y;
    this.z = z; 
    this.w = w;
  }
}
int[]mMap;//如果有墙=>1
int[][]mAStarField;
ArrayList

重要提示:我只能在我标记的区域内更改代码


谢谢大家!

我无法运行代码,但我对问题的根源有一点了解。看,A*算法在寻找最佳路径时不会“后退”。它解决了寻路问题,通过计算成本较低的方法来到达它所评估的每个节点的末端。它首先计算最简单的路线,然后如果它不起作用,它会扩大它的选择,直到它,呃,找到一条路,或者没有选择

封闭列表的原理,避免对一个节点进行两次求值。正如您所猜测的,这里的问题是,在寻路算法的每次迭代中,您都在为邻居创建新节点,从而使封闭列表更难正确使用

像自定义类这样的复杂对象可以通过3种方式进行比较:要么是同一个对象(它引用同一个指针(它是同一个实例,它在计算机内存中的同一个位置)),要么不管它的指针指向什么,值都是相同的,或者您可以定义一个规则来比较它们。这些方法是:通过引用进行比较、通过值进行比较和运算符重载——虽然最后一种方法在java中不可能实现,但您可以编写一个方法来实现同样的目的

执行
closedList.contains(n)
时,您是通过引用进行比较(这是此类操作的默认值)。由于所有节点都是动态创建的,即使它们的坐标相同,它们在内存中的地址也不同,这就是为什么永远不会满足此条件的原因

假设你不能弄乱导师的代码,你仍然可以解决这个问题。你第一次几乎就做对了!事实上,有很多方法可以解决这个问题,由于我错过了一些上下文,我建议的方法将非常简单:您将编写一个从列表中获取特定节点的方法(就像我所说的运算符重载,但只需付出最小的努力),从这一点开始,我们将通过引用工作

首先,创建一个包含所有
AStarNode
的主列表(如果您还没有,那么使用该列表):

最后,如果知道数组中可能有一些,请始终记住测试
null
。在这种情况下,如果离迷宫的边界太近,则
GetAStarNodeByPosition
方法可以返回
null
。您可以修改添加到邻居列表的方式,使其中不存在
null
,也可以在此行中检查null:

//openList.add(new AStarNode(mStartNode[0], mStartNode[1], 0, null));
openList.add(GetAStarNodeByPosition(mStartNode[0], mStartNode[1], nodesList));
if(n != null && n.x >= 0 && n.y >= 0 && n.x < mMap.length && n.y < mMap.length && mMap[n.x][n.y] != 1){
如果(n!=null&&n.x>=0&&n.y>=0&&n.x
老实说,我完全不会在数组中包含null,如果以后进一步修改代码,会更安全

现在,所有节点都将相互关联,您将能够克服障碍,这需要您的算法以比直线更聪明的方式进行搜索


玩得开心!

它不会倒过来
我认为在经典算法中,它会从堆栈中弹出值(以前的位置)以反转到以前的状态。如果以不同的方式实现代码,则需要做一些等效的事情。使用整数数组存储节点位置…我不赞成这种做法(我意识到这不在你身上,别担心)。请帮我做这个测试:写一行(
if(closedList.contains(n)&&cost>=n.c)continue;
)作为一个正常的if,在if中放置一个断点。如果我是对的,你就永远不会碰到那个断点。在你的回复中标记我,让我知道测试结果。@laancelot我试过了,你是对的。它永远不会碰到断点。但我不明白为什么。编辑:我想这是因为我总是在创建一个新节点,因此list从未包含新的。但是我应该如何修复它?
AStarNode GetAStarNodeByPosition(int x, int y, ArrayList<AStarNode> list) {
  for (AStarNode m : list) {
    if (m.x == x && m.y == y) {
      return m;
    }
  }

  return null;
}
ArrayList<AStarNode> neighbors = new  ArrayList<AStarNode>();
neighbors.add(GetAStarNodeByPosition(current.x - 1, current.y, nodesList));
neighbors.add(GetAStarNodeByPosition(current.x + 1, current.y, nodesList));
neighbors.add(GetAStarNodeByPosition(current.x, current.y - 1, nodesList));
neighbors.add(GetAStarNodeByPosition(current.x, current.y + 1, nodesList));
//openList.add(new AStarNode(mStartNode[0], mStartNode[1], 0, null));
openList.add(GetAStarNodeByPosition(mStartNode[0], mStartNode[1], nodesList));
if(n != null && n.x >= 0 && n.y >= 0 && n.x < mMap.length && n.y < mMap.length && mMap[n.x][n.y] != 1){