0

I'm currently implementing an A* pathfinding algorithm in my 2D side-scroller, but I'm having some difficulty.

I thought I implemented it correctly, but obviously not, because it doesn't work.

I'm using a priority queue for efficiency, and followed the algorithm discussed here:

http://www.codeproject.com/Articles/5758/Path-finding-in-C

I did not use their priority queue, however, as many of the comments pointed out that it has some issues. Instead, I use the following priority queue:

https://bitbucket.org/BlueRaja/high-speed-priority-queue-for-c/src

Here's my function, and then I'll discuss the issue:

List<Waypoint> FindPathTo(Waypoint Goal)
{
    TileMath goalMath = TileMath.GetTileMath((int)Goal.x, (int)Goal.y);

    Waypoint startPt = new Waypoint((Vector2)this.transform.position);
    HeapPriorityQueue<Waypoint> OpenList = new HeapPriorityQueue<Waypoint>(MAX_NODES);
    HeapPriorityQueue<Waypoint> ClosedList = new HeapPriorityQueue<Waypoint>(MAX_NODES);

    List<Waypoint> Solution = new List<Waypoint>();

    OpenList.Enqueue(startPt, openPriority);
    openPriority--;

    print(Goal.GetPoint()); //testing
    print(OpenList.Count); //testing

    while (OpenList.Count > 0)
    {
        Waypoint CurrNode = OpenList.Dequeue();

        TileMath currMath = TileMath.GetTileMath((int)CurrNode.x, (int)CurrNode.y);

        if (currMath.GetXY() == goalMath.GetXY() && currMath.GetBlockID() == goalMath.GetBlockID()) // checks if the current node is the goal
        {
            while (CurrNode != null)
            {
                Solution.Insert(0, CurrNode);

                CurrNode = CurrNode.prev;

            }
            break;
        }

        List<Waypoint> successors = CurrNode.GetSuccessors();

        print(successors.Count);

        foreach (Waypoint w in successors)
        {
            Waypoint OpenWp = null;
            Waypoint ClosedWp = null;
            if(OpenList.Contains(w))
            {

                IEnumerator<Waypoint> ie = OpenList.GetEnumerator();

                while((int)ie.Current.x != (int)w.x && (int)ie.Current.y != (int)w.y && ie.Current != null)
                {
                    ie.MoveNext();
                }

                if (ie.Current == null)
                    print("IE ERROR. CHECK CONTAINS IN OPENLIST.");
                else
                    OpenWp = ie.Current;



                if (OpenWp != null && w.totalCost > OpenWp.totalCost)
                    continue;



            }
            if(ClosedList.Contains(w))
            {

                IEnumerator<Waypoint> ie = ClosedList.GetEnumerator();

                while ((int)ie.Current.x != (int)w.x && (int)ie.Current.y != (int)w.y && ie.Current != null)
                {
                    ie.MoveNext();
                }

                if (ie.Current == null)
                    print("IE ERROR. CHECK CONTAINS IN CLOSEDLIST.");
                else
                    ClosedWp = ie.Current;



                if (ClosedWp != null && w.totalCost > ClosedWp.totalCost)
                    continue;
            }

            if (OpenWp != null)
                OpenList.Remove(OpenWp);
            if (ClosedWp != null)
                ClosedList.Remove(ClosedWp);

            OpenList.Enqueue(w, openPriority);
            openPriority--;
            ClosedList.Enqueue(w, closedPriority);
            closedPriority--;


        }
    }

    return Solution;

}

Basically, I have the method returning a List of Waypoints (very simple class, here's a pastebin of it if you're interested: http://pastebin.com/Sch5vRY3), however in my function the List has a Count of 0 upon returning, thus (incorrectly) indicating there's no path to the point.

I've done the usual debugging, but A* is a bit confusing to me, so if anyone could help me with common pitfalls, I'd appreciate it.

I'm definitely a novice at Artificial Intelligence and Path-finding, so if you have any other miscellaneous pointers, I'm all ears!

Thanks.

Jestus
  • 623
  • 2
  • 9
  • 25
  • where are you putting this method ? and there are some variables which we don't see where are they assigned – niceman Jan 04 '15 at 21:11
  • 1
    Make a testcase. Then make a smaller testcase that still fails. Try to find the smallest/simplest input that produces wrong output. – Ben Voigt Jan 04 '15 at 21:17
  • The post shows us some incomplete code and no idea of the input data. You can't expect a serious answer on this. – H H Jan 04 '15 at 21:28
  • @HenkHolterman yes , maybe the code is big to post, Anyway big or small, we can't give exact answer to this question – niceman Jan 04 '15 at 21:32
  • @HenkHolterman what do I need to add to make this complete? I've been attempting to test profusely, however my lack of understanding of A* has made it difficult, as I'm not even sure I understand the algorithm correctly. – Jestus Jan 04 '15 at 22:01

1 Answers1

0

Well I won't tell the exact code but I'll tell what is an A* algorithm and what is it in your case:
In A* we define two functions of state: the cost and the heuristic, the cost means "what is the cost of transferring from the current state to another state", in your case it should be the distance of the path between the current point and the point I'll try.
The heuristic means "How far am I from the goal", in your case maybe the distance from my location to the goal would be great.
After writing these two functions, you write a function let's call it "f" which sums the two.
The A* algorithm is actually a greedy backtracking algorithm in which you try the least "f".

niceman
  • 2,653
  • 29
  • 57
  • Do you think the link I used above (http://www.codeproject.com/Articles/5758/Path-finding-in-C) is a good resource for building it? Or are there simpler resources? I'm debating scrapping the function and redoing it more methodically. I already have a heuristic, and the ability to store the cost, but I've had difficulty understanding the way many resources explain A*. – Jestus Jan 04 '15 at 22:54
  • @Jestus your resourse is specific, it doesn't explain A* in general. – niceman Jan 05 '15 at 15:39
  • @Jestus "but I've had difficulty understanding the way many resources explain A*" maybe because they explain it specifically to one problem, you need one that explains it in general, I know it from college and learnt it this year and used it in a project. – niceman Jan 05 '15 at 15:41
  • Would you recommend any specific online resource? – Jestus Jan 05 '15 at 15:42
  • @Jestus sorry but I counted on College and it was enough for me , I don't know any online resources :). – niceman Jan 05 '15 at 20:24
  • @Jestus but I think if you looked upon Famous AI problems, like Image processing, Expert systems, face recognition you can find what you want, Anyway we were advised to use languages like lisp or prolog not C#. – niceman Jan 05 '15 at 20:26
  • Interesting, thanks. I'll check it out. Why were you advised to not use C#? I'm developing in unity so that's my only real choice. – Jestus Jan 05 '15 at 20:27
  • @Jestus well you can develop a lisp program and use it in C# as the AI engine, I think C# has this feature – niceman Jan 05 '15 at 20:37
  • @Jestus I searched for why lisp is better and found this [question](http://stackoverflow.com/questions/130475/why-is-lisp-used-for-ai) – niceman Jan 05 '15 at 20:38
  • Hmm. The top answer seems to suggest that Lisp stopped being largely used in the 80s...do you find that to be true? – Jestus Jan 05 '15 at 21:27
  • @Jestus but the second answer lists programs which were written in lisp – niceman Jan 05 '15 at 22:32