java 无法在java中实现A Star

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5601889/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 11:51:21  来源:igfitidea点击:

Unable to implement A Star in java

javapath-findinga-star

提问by abc123

I've been trying all day to get this algorithm up and running, but I cant for the life of me. I've read many tutorials on the net, and source code in AS3, javascript, and C++; but I cannot adapt what I am seeing to my own code.

我一整天都在尝试启动并运行这个算法,但我终其一生都做不到。我在网上阅读了很多教程,以及 AS3、javascript 和 C++ 中的源代码;但我无法将我所看到的适应我自己的代码。

I have created an AStar class that has a nested class named Node. The map is a 2D array named MAP.

我创建了一个 AStar 类,它有一个名为 Node 的嵌套类。该地图是一个名为 MAP 的二维数组。

The biggest problem that I am having is pulling the F value in the pathfind function.

我遇到的最大问题是在寻路函数中拉取 F 值。

I have implemented the F = G + H, my problem is the actual AStar algorithm. Can someone please help, this is how far I've got as of yet:

我已经实现了 F = G + H,我的问题是实际的 AStar 算法。有人可以帮忙吗,这是我到目前为止的距离:

import java.util.ArrayList;

public class AStar
{
    int MAP[][];

    Node startNode, endNode;

    public AStar(int MAP[][], int startXNode, int startYNode,
                              int endXNode, int endYNode)
    {
        this.MAP = MAP;
        startNode = new Node(startXNode, startYNode);
        endNode = new Node(endXNode, endYNode);
    }

    public void pathfinder()
    {
        ArrayList openList = new ArrayList();
        ArrayList closedList = new ArrayList();



    }

    public int F(Node startNode, Node endNode)
    {
        return (H(startNode, endNode) + G(startNode));
    }

    //H or Heuristic part of A* algorithm
    public int H(Node startNode, Node endNode)
    {
        int WEIGHT = 10;
        int distance = (Math.abs(startNode.getX() - endNode.getX()) + Math.abs(startNode.getY() - endNode.getY()));

        return (distance * WEIGHT);
    }

    public int G(Node startNode)
    {
        if(MAP[startNode.getX() - 1][startNode.getY()] != 1)
        {
            return 10;
        }

        if(MAP[startNode.getX() + 1][startNode.getY()] != 1)
        {
            return 10;
        }

        if(MAP[startNode.getX()][startNode.getY() -1] != 1)
        {
            return 10;
        }

        if(MAP[startNode.getX()][startNode.getY() + 1] != 1)
        {
            return 0;
        }

        return 0;
    }

    public class Node
    {
        private int NodeX;
        private int NodeY;

        private int gScore;
        private int hScore;
        private int fScore;

        public Node(int NodeX, int NodeY)
        {
            this.NodeX = NodeX;
            this.NodeY = NodeY;
        }

        public int getX()
        {
            return NodeX;
        }

        public int getY()
        {
            return NodeY;
        }

        public int getG()
        {
            return gScore;
        }

        public void setG(int gScore)
        {
            this.gScore = gScore;
        }

        public int getH()
        {
            return hScore;
        }

        public void setH(int hScore)
        {
            this.hScore = hScore;
        }

        public int getF()
        {
            return fScore;
        }

        public void setF(int fScore)
        {
            this.fScore = fScore;
        }
    }
}

This is the furthest I can ever get with the pathfinder function:

这是我使用探路者功能所能得到的最远距离:

   public void pathfinder()
    {
        LinkedList<Node> openList = new LinkedList();
        LinkedList<Node> closedList = new LinkedList();

        Node currentNode;

        openList.add(startNode);

        while(openList.size() > 0)
        {
            currentNode = (Node) openList.get(0);
            closedList.add(currentNode);


            for(int i = 0; i < openList.size(); i++)
            {
                int cost = F(currentNode, endNode);

            }
        }

    }

回答by WhiteFang34

I recently threw this A* code together to solve a Project Eulerproblem. You'll have to fill in the details for a matrix of Nodeobjects. Use it at your own risk, however I can say it solved the problem :)

我最近把这个 A* 代码放在一起来解决一个Project Euler问题。您必须填写Node对象矩阵的详细信息。使用它需要您自担风险,但我可以说它解决了问题:)

public class Node {
    List<Node> neighbors = new ArrayList<Node>();
    Node parent;
    int f;
    int g;
    int h;
    int x;
    int y;
    int cost;
}

public List<Node> aStar(Node start, Node goal) {
    Set<Node> open = new HashSet<Node>();
    Set<Node> closed = new HashSet<Node>();

    start.g = 0;
    start.h = estimateDistance(start, goal);
    start.f = start.h;

    open.add(start);

    while (true) {
        Node current = null;

        if (open.size() == 0) {
            throw new RuntimeException("no route");
        }

        for (Node node : open) {
            if (current == null || node.f < current.f) {
                current = node;
            }
        }

        if (current == goal) {
            break;
        }

        open.remove(current);
        closed.add(current);

        for (Node neighbor : current.neighbors) {
            if (neighbor == null) {
                continue;
            }

            int nextG = current.g + neighbor.cost;

            if (nextG < neighbor.g) {
                open.remove(neighbor);
                closed.remove(neighbor);
            }

            if (!open.contains(neighbor) && !closed.contains(neighbor)) {
                neighbor.g = nextG;
                neighbor.h = estimateDistance(neighbor, goal);
                neighbor.f = neighbor.g + neighbor.h;
                neighbor.parent = current;
                open.add(neighbor);
            }
        }
    }

    List<Node> nodes = new ArrayList<Node>();
    Node current = goal;
    while (current.parent != null) {
        nodes.add(current);
        current = current.parent;
    }
    nodes.add(start);

    return nodes;
}

public int estimateDistance(Node node1, Node node2) {
    return Math.abs(node1.x - node2.x) + Math.abs(node1.y - node2.y);
}

回答by Thediabloman

I dont know if you are trying only to use simple types, or if you just didn't think about it, but you need to have a PriorityQueue to get your A* working.

我不知道您是否只是尝试使用简单类型,或者您是否只是没有考虑过,但是您需要有一个 PriorityQueue 来让您的 A* 工作。

A good way to think is that you put your startpoint into a priority queue with distance 0, and then start a loop that only stops when the prioriy queue is empty.

一个好的思考方式是将起点放入距离为 0 的优先级队列,然后启动一个循环,该循环仅在优先级队列为空时停止。

In the loop you take the min-node out, and check to see if it hasnt been open before, or if it has, if you have now found a shorter way to it. If either these are true, you add the distance to the new node, add the edge/from-square to a map, and then add the distance + heuristic to the priority queue.

在循环中,您将最小节点取出,并检查它之前是否打开过,或者如果您现在找到了更短的方法来打开它。如果这些都为真,则将距离添加到新节点,将边/从方格添加到地图,然后将距离 + 启发式添加到优先级队列。

I have written this to work on a grid of booleans, and a constant conversion between 1D and 2D arrays, but I hope it is readable:

我写这个是为了处理布尔值网格,以及一维和二维数组之间的常量转换,但我希望它是可读的:

public void AStarRoute()
{
    gridDist = new double[rows][cols];
    System.out.println("Start of AStarRoute");
    MinPriorityQueue pq = new MinPriorityQueue(rows * cols);
    edgeTo = new HashMap<Integer, Integer>();

    gridDist[x1Dto2D(start)][y1Dto2D(start)] = 0;
    pq.insert(start, 0);
    int from;
    while (!pq.isEmpty()) {
        from = pq.delMin();
        int x = x1Dto2D(from);
        int y = y1Dto2D(from);
        for (int i = -1; i <= 1; i++) {
            for (int j = -1; j <= 1; j++) {
                int newX = x + i;
                int newY = y + j;
                if (newX >= 0 && newY >= 0 && newX < cols && newY < rows && !(i == 0 && j == 0)) {
                    if (grid[newX][newY]) {
                        //System.out.println("NewDist: " + gridDist[newX][newY] + " - OldDist+dist: " + (gridDist[x][y] + ((Math.abs(i) == Math.abs(j)) ? 1.4 : 1.0)) + ":" + (int)(gridDist[x][y] + ((Math.abs(i) == Math.abs(j)) ? 1.4 : 1.0)));
                        if (!edgeTo.containsKey(convert2Dto1D(newX, newY)) || gridDist[newX][newY] > (gridDist[x][y] + ((Math.abs(i) == Math.abs(j)) ? 14 : 10))) {
                            gridDist[newX][newY] = (int)(gridDist[x][y] + ((Math.abs(i) == Math.abs(j)) ? 14 : 10));
                            maxDistToEnd = (int)Math.max(maxDistToEnd, gridDist[newX][newY]);
                            edgeTo.put(convert2Dto1D(newX, newY), convert2Dto1D(x, y));
                            pq.insert(convert2Dto1D(newX, newY), gridDist[newX][newY] + (int)Math.sqrt(Math.pow((newX - x1Dto2D(end))*10, 2) + Math.pow((newY - y1Dto2D(end))*10, 2)));
                            if(convert2Dto1D(newX, newY) == end){
                                System.out.println("End found at (" + newX + ", " + newY + ")");
                                paintGridDist = true;

                                route = new ArrayList<Integer>();
                                int n = convert2Dto1D(newX, newY);
                                route.add(n);
                                do{
                                    n = edgeTo.get(n);
                                    route.add(n);
                                }while(start != n);

                                repaint();
                                return;
                            }
                        }
                    }
                }
            }
        }
    }

    paintGridDist = true;
    repaint();
}