JL123
JL123

Reputation: 71

A* path finding runs forever in certain cases

I've written up an A* pathfinding algorithm in java using this pseudo-code. For some cases it works fine, but for some it hangs forever and adds an infinite number of nodes to the open list. Is this a problem with my execution of the pseudo-code, or with the pseudo-code itself? I've tried a bunch of print statements for debugging, but I'm having trouble even pinning down the problem. Here is my A* code:

import java.awt.Point;
import java.util.ArrayList;
import java.util.Collections;

public class AStar {

    Point[] adjacents = {new Point(0,1),new Point(1,1), new Point(1,0), new Point(1,-1), new Point(0,-1), new Point(-1,-1), new Point(-1,0), new Point(-1,1)};

    public Node[] calculatePH(Node startNode, Node endNode, int[][] map) {
        // Initialize both open and closed list
        ArrayList<Node> open = new ArrayList<Node>();
        ArrayList<Node> closed = new ArrayList<Node>();
        // Add the start node
        open.add(startNode);
        // Loop until you find the end
        while(!open.isEmpty()) {
            // Get the current node
            Node currentNode = open.get(0);
            for(Node n : open) {
                if(n.f<currentNode.f) {
                    currentNode = n;
                }
            }

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

            // Found the goal
            if(currentNode.equals(endNode)) {
                ArrayList<Node> path = new ArrayList<Node>();
                Node current = currentNode;
                while(current!=null) {
                    path.add(current);
                    current = current.parent;
                }
                Collections.reverse(path);
                return path.toArray(new Node[path.size()]);
            }

            // Generate children

            ArrayList<Node> children = new ArrayList<Node>();
            for(Point p : adjacents) {
                Point childpos = currentNode.getLocation();
                childpos.translate(p.x, p.y);

                //Checks to ensure that the node is on the actual field, so we don't ram into a field tech lol
                if((childpos.y>(map.length-1)) || (childpos.y<0) || (childpos.x>(map[0].length-1)) || (childpos.x<0)) {
                    continue;
                }

                //Checks to ensure that the node is "walkable", or basically just not inside a wall or object.
                if(map[childpos.y][childpos.x] != 0) {
                    continue;
                }

                Node child = new Node(currentNode,childpos);
                children.add(child);
            }

            for(Node n : children) {
                // Child is on the closedList
                if(closed.indexOf(n)>-1) {
                    continue;
                }

                n.g = currentNode.g + currentNode.distance(n);
                n.h = n.distance(endNode);
                n.f = n.g+n.h;
                boolean inFlag = false;
                for(Node m : open) {
                    if((n==m) && (n.g>m.g)) {
                        inFlag = true;
                    }
                }

                if(!inFlag) {
                    open.add(n);
                }
            }
        }

        return new Node[0];
    }
}

And the Node class, which is a subclass of java.awt.Point with some extra stuff.

import java.awt.Point;
import java.util.ArrayList;

public class Node extends Point { //Extends Point for conveinince and 
    //neatness. Maybe just use a has-a relationship if this breaks.

    public Node(Node Parent, Point loc) {
        super(loc);
        this.parent = Parent;
    }

    public Node(Point loc) {
        super(loc);

    }

    void translate(Point p){
        translate(p.x,p.y);
    }

    public Node parent;

    public double f;
    public double g;
    public double h;

    public String toString() {

        return "("+x+","+y+")";
    }
}

I'm using a maze which is 27 tall and 54 wide, a start point at (0,0) and a goal at (24,24), and It currently has two obstacles. In this case it works fine:

enter image description here

But in this case it hangs forever. The only difference is that the second obstacle extends down 1 row further.

enter image description here

Any help at all would be seriously appreciated, and please let me know if I should change the question or add more info.

EDIT: It's not pretty, but here is the int[][] containing the map data for the non-functioning version.

int[][] map ={
        {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 
        {0,1,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 
        {0,1,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
        {0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 
        {0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 
        {0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 
        {0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 
        {0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
        {0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 
        {0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, 
        {0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
        {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
        {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
        {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
        {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
        {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
        {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
        {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
        {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
        {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
        {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
        {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
        {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
        {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
        {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
        {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
        {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
       };

Upvotes: 3

Views: 68

Answers (1)

JL123
JL123

Reputation: 71

Just figured this out, thanks to bracco23 for pointing me to the right section of code. Turns out I made a rookie java mistake and compared using == rather than .equals. Swapping that out fixed the issue.

Upvotes: 1

Related Questions