9

I'm in the process of making a 2D tile map and i'm now trying to implement A* pathfinding. I'm following the Wikipedia pseudocode for A*.

Things are going quite well except for some weird behaviour in the decisions taken by the algorithm.

My code so far:

void Pathfinding(Point from, Point destination) {

    goalNode = new Node(destination, 0, 0);
    startNode = new Node(from, 0, ManhattanDistance(from, destination));

    open = new List<Node>();            //list of nodes
    closed = new List<Node>();
    open.Add(startNode);                //Add starting point

    while(open.Count > 0) {

        node = getBestNode();                   //Get node with lowest F value
        if(node.position == goalNode.position) {
            Debug.Log("Goal reached");
            getPath(node);
            break;
        }
        removeNode(node, open);
        closed.Add(node);

        List<Node> neighbors = getNeighbors(node);
        foreach(Node n in neighbors) {
            float g_score = node.G + 1;
            float h_score = ManhattanDistance(n.position, goalNode.position);
            float f_score = g_score + h_score;

            if(isValueInList(n, closed) && f_score >= n.F) 
                continue;

            if(!isValueInList(n, open) || f_score < n.F) {
                n.parent = node;
                n.G = g_score;
                n.G = h_score;
                if(!isValueInList(n, open)) {
                    map_data[n.position.x, n.position.y] = 4;
                    open.Add(n);
                }
            }
        }
    }
}

The result of running this code:

Blue is the nodes from the open list and green is the path chosen to the goal node.

SOLUTION:

void Pathfinding(Point from, Point destination) {

    goalNode = new Node(destination, 0, 0);
    startNode = new Node(from, 0, ManhattanDistance(from, destination));

    open = new List<Node>();            //list of nodes
    closed = new List<Node>();
    open.Add(startNode);                //Add starting point

    while(open.Count > 0) {

        node = getBestNode();                   //Get node with lowest F value
        if(node.position == goalNode.position) {
            Debug.Log("Goal reached");
            getPath(node);
            break;
        }
        removeNode(node, open);
        closed.Add(node);

        List<Node> neighbors = getNeighbors(node);
        foreach(Node n in neighbors) {
            float g_score = node.G + 1;
            float h_score = ManhattanDistance(n.position, goalNode.position);
            float f_score = g_score + h_score;

            if(isValueInList(n, closed) && f_score >= n.F) 
                continue;

            if(!isValueInList(n, open) || f_score < n.F) {
                n.parent = node;
                n.G = g_score;
                n.H = h_score;
                if(!isValueInList(n, open)) {
                    map_data[n.position.x, n.position.y] = 4;
                    open.Add(n);
                }
            }
        }
    }
}
5
  • 2
    What weird behaviour/choices? The visualization looks good. Commented Nov 2, 2013 at 19:33
  • I'm refering to the fact that it goes straigh up and then moves left. Wouldn't it be better if it would expand to the right and then go up? I've always thought that A* will always give the shortest possible path to a goal. Commented Nov 2, 2013 at 20:00
  • 2
    The best C# A* implementation can be found here: blogs.msdn.com/b/ericlippert/archive/tags/astar Commented Nov 2, 2013 at 21:58
  • You're assigning n.G twice and never storing f_score. You probably want to overwrite n.F with f_score when it's lower. Commented Nov 2, 2013 at 23:40
  • looks like the Eric Lippert c# MSDN blog is long dead. Here is a Wayback Machine archive of it Commented Jun 23, 2021 at 2:59

1 Answer 1

4

First, your open Nodes should be sorted in descending order, while in your code - there is no ordering. You compute the distance (g) and the heuristics (h) but never actually use it. You should consider using ordered container instead of lists (as sorting lists in each iteration won't be efficient)

Second, you do not store the heuristic value in the node as

n.G = h_score;

should be

n.H = h_score;
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.