public static List <Tile> FindPath_GreedyBestFirstSearch(TileGrid grid, Tile start, Tile end, List <IVisualStep> outSteps)
        {
            // Visual stuff
            outSteps.Add(new MarkStartTileStep(start));
            outSteps.Add(new MarkEndTileStep(end));
            // ~Visual stuff

            Comparison <Tile> heuristicComparison = (lhs, rhs) =>
            {
                float lhsCost = GetEuclideanHeuristicCost(lhs, end);
                float rhsCost = GetEuclideanHeuristicCost(rhs, end);

                return(lhsCost.CompareTo(rhsCost));
            };

            MinHeap <Tile> frontier = new MinHeap <Tile>(heuristicComparison);

            frontier.Add(start);

            HashSet <Tile> visited = new HashSet <Tile>();

            visited.Add(start);

            start.PrevTile = null;

            while (frontier.Count > 0)
            {
                Tile current = frontier.Remove();

                // Visual stuff
                if (current != start && current != end)
                {
                    outSteps.Add(new VisitTileStep(current));
                }
                // ~Visual stuff

                if (current == end)
                {
                    break;
                }

                foreach (var neighbor in grid.GetNeighbors(current))
                {
                    if (!visited.Contains(neighbor))
                    {
                        frontier.Add(neighbor);
                        visited.Add(neighbor);
                        neighbor.PrevTile = current;

                        // Visual stuff
                        if (neighbor != end)
                        {
                            outSteps.Add(new PushTileInFrontierStep(neighbor, 0));
                        }
                        // ~Visual stuff
                    }
                }
            }

            List <Tile> path = BacktrackToPath(end);

            // Visual stuff
            foreach (var tile in path)
            {
                if (tile == start || tile == end)
                {
                    continue;
                }

                outSteps.Add(new MarkPathTileStep(tile));
            }
            // ~Visual stuff

            return(path);
        }
        public static List <Tile> FindPath_Dijkstra(TileGrid grid, Tile start, Tile end, List <IVisualStep> outSteps)
        {
            // Visual stuff
            outSteps.Add(new MarkStartTileStep(start));
            outSteps.Add(new MarkEndTileStep(end));
            // ~Visual stuff

            foreach (var tile in grid.Tiles)
            {
                tile.Cost = int.MaxValue;
            }

            start.Cost = 0;

            HashSet <Tile> visited = new HashSet <Tile>();

            visited.Add(start);

            MinHeap <Tile> frontier = new MinHeap <Tile>((lhs, rhs) => lhs.Cost.CompareTo(rhs.Cost));

            frontier.Add(start);

            start.PrevTile = null;

            while (frontier.Count > 0)
            {
                Tile current = frontier.Remove();

                // Visual stuff
                if (current != start && current != end)
                {
                    outSteps.Add(new VisitTileStep(current));
                }
                // ~Visual stuff

                if (current == end)
                {
                    break;
                }

                foreach (var neighbor in grid.GetNeighbors(current))
                {
                    int newNeighborCost = current.Cost + neighbor.Weight;
                    if (newNeighborCost < neighbor.Cost)
                    {
                        neighbor.Cost     = newNeighborCost;
                        neighbor.PrevTile = current;
                    }

                    if (!visited.Contains(neighbor))
                    {
                        visited.Add(neighbor);
                        frontier.Add(neighbor);

                        // Visual stuff
                        if (neighbor != end)
                        {
                            outSteps.Add(new PushTileInFrontierStep(neighbor, neighbor.Cost));
                        }
                        // ~Visual stuff
                    }
                }
            }

            List <Tile> path = BacktrackToPath(end);

            // Visual stuff
            foreach (var tile in path)
            {
                if (tile == start || tile == end)
                {
                    continue;
                }

                outSteps.Add(new MarkPathTileStep(tile));
            }
            // ~Visual stuff

            return(path);
        }
Beispiel #3
0
        private static BreadCrumb FindPathReversed(Grid world, Point start, Point end)
        {
            var openList = new MinHeap <BreadCrumb>(256);
            var brWorld  = new BreadCrumb[world.Right, world.Top];

            var current = new BreadCrumb(start)
            {
                Cost = 0
            };

            var finish = new BreadCrumb(end);

            brWorld[current.Position.X, current.Position.Y] = current;
            openList.Add(current);

            while (openList.Count > 0)
            {
                //Find best item and switch it to the 'closedList'
                current = openList.ExtractFirst();
                current.OnClosedList = true;

                //Find neighbours
                for (var i = 0; i < Surrounding.Length; i++)
                {
                    var tmp = new Point(current.Position.X + Surrounding[i].X, current.Position.Y + Surrounding[i].Y);

                    if (!world.ConnectionIsValid(current.Position, tmp))
                    {
                        continue;
                    }

                    try
                    {
                        //Check if we've already examined a neighbour, if not create a new node for it.
                        BreadCrumb node;
                        if (brWorld[tmp.X, tmp.Y] == null)
                        {
                            node = new BreadCrumb(tmp);
                            brWorld[tmp.X, tmp.Y] = node;
                        }
                        else
                        {
                            node = brWorld[tmp.X, tmp.Y];
                        }

                        //If the node is not on the 'closedList' check it's new score, keep the best
                        if (!node.OnClosedList)
                        {
                            var diff = 0;
                            if (current.Position.X != node.Position.X)
                            {
                                diff += 1;
                            }

                            if (current.Position.Y != node.Position.Y)
                            {
                                diff += 1;
                            }

                            var distance =
                                (int)Mathf.Pow(
                                    Mathf.Max(Mathf.Abs(end.X - node.Position.X), Mathf.Abs(end.Y - node.Position.Y)), 2);
                            var cost = current.Cost + diff + distance;

                            if (cost < node.Cost)
                            {
                                node.Cost = cost;
                                node.Next = current;
                            }

                            //If the node wasn't on the openList yet, add it
                            if (!node.OnOpenList)
                            {
                                //Check to see if we're done
                                if (node.Equals(finish))
                                {
                                    node.Next = current;
                                    return(node);
                                }

                                node.OnOpenList = true;
                                openList.Add(node);
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        Debug.LogWarning(tmp);
                    }
                }
            }
            return(null); //no path found
        }