示例#1
0
文件: ANode.cs 项目: Cynnexis/PacPac
 public ANode(int g = 0, int h = 0, Vector2?position = null, ANode parent = null)
 {
     G        = g;
     H        = h;
     Position = position != null ? (Vector2)position : new Vector2(-1, -1);
     Parent   = parent;
 }
示例#2
0
文件: ANode.cs 项目: Cynnexis/PacPac
        public override bool Equals(object obj)
        {
            if (obj == null)
            {
                return(false);
            }

            if (!(obj is ANode))
            {
                return(false);
            }

            ANode n = (ANode)obj;

            return(Position.Equals(n.Position));
        }
示例#3
0
        public Path ComputePath(Vector2 start, Vector2 end)
        {
            if (Path == null)
            {
                throw new InvalidOperationException();
            }

            if (/*start.Equals(Path.Origin) && */ end.Equals(Path.Goal))
            {
                return(Path);
            }

            if (start == null || end == null)
            {
                throw new ArgumentNullException();
            }

            if (start.X < 0 || start.X >= Map.Width || start.Y < 0 || start.Y >= Map.Height ||
                end.X < 0 || end.X >= Map.Width || end.Y < 0 || end.Y >= Map.Height)
            {
                throw new ArgumentException();
            }

            Open   = new List <ANode>(1);
            Closed = new List <ANode>();
            Path   = new Path();

            // Add the starting point to the path
            Path.Add(start);

            // Add the starting point to the Open nodes
            Open.Add(new ANode(0, ManhattanDistance(start, end), start));

            Dictionary <Vector2, Vector2> map = new Dictionary <Vector2, Vector2>();

            // While Open is not empty
            int rec = 0;

            while (Open.Count > 0)
            {
                int q_index = minF(Open);
                // q is the node which has the minimum F in the Open nodes. This is THIS node which will be evaluated in this iteration.
                ANode q = Open[q_index];

                if (q.Position.Equals(end))
                {
                    /*if (!Path.Contains(q.Position))
                     *      Path.Add(q.Position);*/
                    return(ReconstructPath(map, q.Position));
                }

                // Remove q from the Open nodes
                Open.Remove(q);

                Closed.Add(q);

                // Generate q's 4 successors (neighbors)
                List <ANode> successors = new List <ANode>(4);
                //successors.Add(new ANode(ANode.INFINITY, 0, new Vector2(q.Position.X - 1, q.Position.Y - 1), q));
                successors.Add(new ANode(ANode.INFINITY, 0, new Vector2(q.Position.X, q.Position.Y - 1), q));
                //successors.Add(new ANode(ANode.INFINITY, 0, new Vector2(q.Position.X + 1, q.Position.Y - 1), q));
                successors.Add(new ANode(ANode.INFINITY, 0, new Vector2(q.Position.X + 1, q.Position.Y), q));
                //successors.Add(new ANode(ANode.INFINITY, 0, new Vector2(q.Position.X + 1, q.Position.Y + 1), q));
                successors.Add(new ANode(ANode.INFINITY, 0, new Vector2(q.Position.X, q.Position.Y + 1), q));
                //successors.Add(new ANode(ANode.INFINITY, 0, new Vector2(q.Position.X - 1, q.Position.Y + 1), q));
                successors.Add(new ANode(ANode.INFINITY, 0, new Vector2(q.Position.X - 1, q.Position.Y), q));

                // TODO: Merge the two for-loop in one, and replace the Remove and i-- by 'continue'
                // Check if all successors are correct

                /*
                 * for (int i = 0; i < successors.Count; i++)
                 * {
                 *      Vector2 p = successors[i].Position;
                 *
                 *      // If the node is in Closed, then the node is already evaluated
                 *      /*if (Closed.Contains(successors[i]))
                 *      {
                 *              successors.RemoveAt(i);
                 *              i--;
                 *      }
                 *
                 *      if (i < 0)
                 *              i = 0;*
                 *
                 *      // Check if position is correct
                 *      if ((p.X < 0 || p.X >= Map.Width || p.Y < 0 || p.Y >= Map.Height ||
                 *               p.X < 0 || p.X >= Map.Width || p.Y < 0 || p.Y >= Map.Height) && i <= successors.Count - 1)
                 *      {
                 *              successors.RemoveAt(i);
                 *              i--;
                 *      }
                 *
                 *      if (i < 0)
                 *              i = 0;
                 *
                 *      // Check if the node in the maze is not a block
                 *      if (Cell.IsTileTypeBlock(Map[p].Tile) && i <= successors.Count - 1)
                 *      {
                 *              successors.RemoveAt(i);
                 *              i--;
                 *      }
                 *
                 *      if (i < 0)
                 *              i = 0;
                 *
                 *      // Finally, after all those checks, add the successor in Open:
                 *      /*if (i <= successors.Count - 1 && !Open.Contains(successors[i]))
                 *              Open.Add(successors[i]);*
                 * }*/


                // Now that successors contains valid nodes, continue the A* algorithm
                // For each succesor 's', update its variables G and H
                ANode s = null;
                for (int i = 0; i < successors.Count; i++)
                {
                    s = successors[i];
                    Vector2 p = s.Position;
                    // Check if position is correct
                    if (p.X < 0 || p.X >= Map.Width || p.Y < 0 || p.Y >= Map.Height)
                    {
                        continue;
                    }

                    if (Cell.IsTileTypeBlock(Map[p].Tile))
                    {
                        continue;
                    }

                    /*if (s.Equals(end))
                     *      break;*/

                    /* mit.edu solution : */

                    /*
                     * //          distance between s and q
                     * s.G = q.G + ManhattanDistance(s.Position, q.Position);
                     *
                     * //    distance between goal and s
                     * s.H = ManhattanDistance(end, s.Position);
                     *
                     * // s.F is automatically calculated (see ANode.G and ANode.H properties for more details)
                     * List<ANode> openUclosed = new List<ANode>(Open.Count + Closed.Count);
                     * openUclosed.AddRange(Open);
                     * openUclosed.AddRange(Closed);
                     * foreach (ANode n in openUclosed)
                     *      if (s.Position.Equals(n.Position) && n.F < s.F)
                     *              continue;
                     */

                    /* Wikipedia solution: */
                    if (Closed.Contains(s))
                    {
                        continue;
                    }

                    if (!Open.Contains(s))
                    {
                        Open.Add(s);
                    }

                    //                      distance between s and q
                    int tentative_g = q.G + ManhattanDistance(s.Position, q.Position);
                    if (tentative_g >= s.G)
                    {
                        continue;
                    }

                    if (!Path.Contains(q.Position))
                    {
                        Path.Add(s.Position);
                    }
                    map[s.Position] = q.Position;
                    s.G             = tentative_g;
                    //    distance between goal and s
                    s.H = ManhattanDistance(end, s.Position);
                }

                // q is now evaluated, it can be stored in Closed
                //Closed.Add(q);

                rec++;
                if (rec >= 100)
                {
                    throw new InfiniteLoopException();
                }
            }

            return(Path);
        }