【问题标题】:Problems with with A* algorithm [closed]A *算法的问题[关闭]
【发布时间】:2014-08-25 15:17:43
【问题描述】:

我正在尝试在 Java 中实现 A* 算法。我按照这个教程,特别是这个伪代码:http://theory.stanford.edu/~amitp/GameProgramming/ImplementationNotes.html

问题是我的代码不起作用。它进入一个无限循环。我真的不知道为什么会发生这种情况......我怀疑问题出在 Graph 构造函数中实现的 F = G + H 函数中。我怀疑我没有计算邻居 F 的正确性。

这是我的代码:

List<Graph> open;
    List<Graph> close;

    private void createRouteAStar(Unit u)
    {
        open = new ArrayList<Graph>();
        close = new ArrayList<Graph>();

        u.ai_route_endX = 11;
        u.ai_route_endY = 5;

        List<Graph> neigh;

        int index;
        int i;
        boolean finish = false;

        Graph current;
        int cost;
        Graph start = new Graph(u.xMap, u.yMap, 0, ManhattanDistance(u.xMap, u.yMap, u.ai_route_endX, u.ai_route_endY));

        open.add(start);
        current = start;
        while(!finish)
        {
            index = findLowerF();
            current = new Graph(open, index);
            System.out.println(current.x);
            System.out.println(current.y);
            if (current.x == u.ai_route_endX && current.y == u.ai_route_endY)
            {
                finish = true;
            }
            else
            {
                close.add(current);
                open.remove(open.indexOf(current)); //EDITED LATER
                neigh = current.getNeighbors();
                for (i = 0; i < neigh.size(); i++)
                {
                    cost = current.g + ManhattanDistance(current.x, current.y, neigh.get(i).x, neigh.get(i).y);

                    if (open.contains(neigh.get(i)) && cost < neigh.get(i).g)
                    {
                        open.remove(open.indexOf(neigh));
                    } 
                    else if (close.contains(neigh.get(i)) && cost < neigh.get(i).g)
                    {
                        close.remove(close.indexOf(neigh));
                    }
                    else if (!open.contains(neigh.get(i)) && !close.contains(neigh.get(i)))
                    {
                        neigh.get(i).g = cost;
                        neigh.get(i).f = cost + ManhattanDistance(neigh.get(i).x, neigh.get(i).y, u.ai_route_endX, u.ai_route_endY);
                        neigh.get(i).setParent(current);
                        open.add(neigh.get(i));
                    }
                }
            }

        }

        System.out.println("step");
        for (i=0; i < close.size(); i++)
        {
            if (close.get(i).parent != null)
            {
                System.out.println(i);
                System.out.println(close.get(i).parent.x);
                System.out.println(close.get(i).parent.y);
            }
        }
    }

    private int findLowerF()
    {
        int i;
        int min = 10000;
        int minIndex = -1;
        for (i=0; i < open.size(); i++)
        {
            if (open.get(i).f < min)
            {
                min = open.get(i).f;
                minIndex = i;
                System.out.println("min");
                System.out.println(min);
            }
        }
        return minIndex;
    }


    private int ManhattanDistance(int ax, int ay, int bx, int by)
    {
        return Math.abs(ax-bx) + Math.abs(ay-by);
    }

而且,正如我所说。我怀疑 Graph 类有主要问题。但是我无法检测并修复它。

public class Graph {

    int x, y;
    int f,g,h;
    Graph parent;

    public Graph(int x, int y, int g, int h)
    {
        this.x = x;
        this.y = y;
        this.g = g;
        this.h = h;
        this.f = g + h;
    }

    public Graph(List<Graph> list, int index)
    {
        this.x = list.get(index).x;
        this.y = list.get(index).y;
        this.g = list.get(index).g;
        this.h = list.get(index).h;
        this.f = list.get(index).f;
        this.parent = list.get(index).parent;
    }

    public Graph(Graph gp)
    {
        this.x = gp.x;
        this.y = gp.y;
        this.g = gp.g;
        this.h = gp.h;
        this.f = gp.f;
    }

    public Graph(Graph gp, Graph parent)
    {
        this.x = gp.x;
        this.y = gp.y;
        this.g = gp.g;
        this.h = gp.h;
        this.f = g + h;
        this.parent = parent;
    }

    public List<Graph> getNeighbors()
    {
        List<Graph> aux = new ArrayList<Graph>();
        aux.add(new Graph(x+1, y, g,h));
        aux.add(new Graph(x-1, y, g,h));
        aux.add(new Graph(x, y+1, g,h));
        aux.add(new Graph(x, y-1, g,h));
        return aux;
    }

    public void setParent(Graph g)
    {
        parent = g;
    }

    //Added later. Generated by Eclipse

    @Override
    public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + x;
    result = prime * result + y;
    return result;
}

@Override
public boolean equals(Object obj) {
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    Graph other = (Graph) obj;
    if (x != other.x)
        return false;
    if (y != other.y)
        return false;
    return true;
}
}

小编辑:

使用System.out 和调试器,我发现程序总是检查相同的“当前”图表(15,8),即(u.xMap, u.yMap) 位置。看起来它会永远保留在第一步中。

【问题讨论】:

  • 在上面放一个调试器,并跟踪执行。另见How to debug small programs.
  • 我做到了,我忘了把那个信息。它可能有用。谢谢提醒^^"
  • 您是否在Graph 上实施了equals() 以便list.contains() 正常工作? (您还应该实现hashCode(),并尽可能使用集合。)
  • 你可以看到完整的类。所以不,我没有使用equals()hashCode()。我了解equals(),但我从未使用过hashCode()。我该怎么处理它们?
  • 有大量资源详细描述了equals()hashCode() 之间的关系,以及覆盖它们时应遵循的规则 (here's one)。首先,尝试覆盖equals(),看看它是否可以帮助您解决当前的问题。

标签: java algorithm artificial-intelligence a-star


【解决方案1】:

您不会从打开列表中删除您的起始节点(我的意思是,在每个循环之后,您需要删除刚刚退出的节点)。 另外,一些提示:

  1. java 中有优先级队列。所以,你不需要自己在清单上做
  2. int f,g,h;尝试重命名变量。无法理解它们在代码中的含义。
  3. 然后创建邻居,检查它们是否在该区域内(即:x,y>0 且小于 maxX,maxY)

【讨论】:

  • 添加了开始节点的移除。那很重要。关于提示, 1.优先级队列是什么意思?我用列表做了什么坏事吗? 2. 该变量在理论上是这样称呼的,并且在许多教程中都以该名称出现,例如wikipediathis popular one。 3 你有道理,我忘记了界限。谢谢!
  • 我不同意重命名变量。一般来说,它们是不清楚的。在 A* 的上下文中,它们是标准名称。
  • 好的,我不熟悉这个特定算法中的命名约定。
  • 优先队列可帮助您通过 O(1) 获取第一个(最大/最小)元素。在您的情况下,您可以通过 O(n) 每次都考虑整个列表来获得它。见priority queue in java
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-08-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-09
  • 2016-12-20
相关资源
最近更新 更多