예제 #1
0
    public Path ComputeInternalPathFromTo(Tile _StartTile, Tile _EndTile)
    {
        List <PathLinkHeuristic> openList = new List <PathLinkHeuristic>();
        HashSet <Tile>           closeSet = new HashSet <Tile>();

        openList.Add(new PathLinkHeuristic(_StartTile, Tile.GetManhattanDistance(_StartTile, _EndTile)));
        CustomComparer <PathLinkHeuristic> comparer = new CustomComparer <PathLinkHeuristic>(false);

        while (openList.Count > 0)
        {
            PathLinkHeuristic linkToExtend = openList.Last();
            if (linkToExtend.Tile == _EndTile)
            {
                return(Path.CreatePath(linkToExtend));
            }
            openList.RemoveAt(openList.Count - 1);
            Tile tileToExtend = linkToExtend.Tile;
            if (closeSet.Contains(tileToExtend))
            {
                continue;
            }

            closeSet.Add(tileToExtend);
            for (int i = 0; i < tileToExtend.Neighbors.Count; i++)
            {
                Tile neighbor = tileToExtend.Neighbors[i];
                if (!neighbor.IsAccessible || !IsTileInside(neighbor) || closeSet.Contains(neighbor))
                {
                    continue;
                }

                //PathLinkHeuristic extension = new PathLinkHeuristic(linkToExtend, neighbor, Tile.GetManhattanDistance(neighbor, _EndTile));
                PathLinkHeuristic extension = linkToExtend.MakeExtensionWith(neighbor, Tile.GetManhattanDistance(neighbor, _EndTile));
                int indexInsertion          = openList.BinarySearch(extension, comparer);
                if (indexInsertion < 0)
                {
                    indexInsertion = ~indexInsertion;
                }
                openList.Insert(indexInsertion, extension);
            }
        }

        return(null);
    }
예제 #2
0
    /// <summary>
    /// Search a path with custom AStar algorithm
    /// (PathLink is use to explore the grid. this way, there's no duplicate of tile array when we extend open list)
    /// </summary>
    /// <param name="_Start">Tile to start from</param>
    /// <param name="_End">Tile to reach</param>
    /// <param name="_ChronoInfos">Struct with times value to evaluate performance</param>
    /// <param name="_MaxSeconds">Max time allowed to search a solution. If value is negative, no time limit applied</param>
    /// <returns>the shortest path from start tile to end tile if it exists, null otherwise</returns>
    public static Path AStar_LinkOpti(Tile _Start, Tile _End, out ChronoInfos _ChronoInfos, float _MaxSeconds)
    {
        StartChrono();

        if (_Start == null || !_Start.IsAccessible || _End == null || !_End.IsAccessible)
        {
            _ChronoInfos = ChronoInfos.InfosNone;
            return(null);
        }

        List <PathLinkHeuristic> openList = new List <PathLinkHeuristic>(100)
        {
            new PathLinkHeuristic(_Start, Tile.GetManhattanDistance(_Start, _End))
        };
        HashSet <Tile> closeHashSet = new HashSet <Tile>();
        CustomComparer <PathLinkHeuristic> customComparer = new CustomComparer <PathLinkHeuristic>(true);

        while (openList.Count > 0)
        {
            if (_MaxSeconds > 0 && chrono.Elapsed.TotalSeconds > _MaxSeconds)
            {
                _ChronoInfos = StopChrono(_Start, _End, false);
                return(null);
            }

            PathLinkHeuristic linkToExtend = openList.First();
            if (linkToExtend.Tile == _End)
            {
                _ChronoInfos          = StopChrono(_Start, _End, true);
                createSolutionChrono -= chrono.ElapsedMilliseconds;
                Path solution = Path.CreatePath(linkToExtend);
                createSolutionChrono += chrono.ElapsedMilliseconds;
                return(solution);
            }

            removeFromOpenChrono -= chrono.ElapsedMilliseconds;
            openList.RemoveAt(0);
            removeFromOpenChrono += chrono.ElapsedMilliseconds;

            if (closeHashSet.Contains(linkToExtend.Tile))
            {
                continue;
            }

            closeHashSet.Add(linkToExtend.Tile);
            Tile tileToExtend = linkToExtend.Tile;

            foreachNeighborsChrono -= chrono.ElapsedMilliseconds;
            for (int i = 0; i < tileToExtend.Neighbors.Count; i++)
            {
                Tile neighbor = tileToExtend.Neighbors[i];

                searchInCloseListChrono -= chrono.ElapsedMilliseconds;
                bool existInCloseList = closeHashSet.Contains(neighbor);
                searchInCloseListChrono += chrono.ElapsedMilliseconds;

                if (!neighbor.IsAccessible || existInCloseList)
                {
                    continue;
                }

                extendPathChrono -= chrono.ElapsedMilliseconds;
                //PathLinkHeuristic extendedLink = new PathLinkHeuristic(linkToExtend, neighbor, Tile.GetManhattanDistance(neighbor, _End));
                PathLinkHeuristic extendedLink = linkToExtend.MakeExtensionWith(neighbor, Tile.GetManhattanDistance(neighbor, _End));
                extendPathChrono += chrono.ElapsedMilliseconds;

                searchInsertionChrono -= chrono.ElapsedMilliseconds;
                int indexInsertion = openList.BinarySearch(extendedLink, customComparer);
                if (indexInsertion < 0)
                {
                    indexInsertion = ~indexInsertion;
                }
                searchInsertionChrono += chrono.ElapsedMilliseconds;

                insertToOpenListChrono -= chrono.ElapsedMilliseconds;
                openList.Insert(indexInsertion, extendedLink);
                insertToOpenListChrono += chrono.ElapsedMilliseconds;
            }
            foreachNeighborsChrono += chrono.ElapsedMilliseconds;
        }

        _ChronoInfos = StopChrono(_Start, _End, false);
        return(null);
    }