예제 #1
0
        /// <summary>
        ///     Performs path search using A* algorithm for a given start and list of goals.
        ///     <para>Returns list of nodes from best ending node to starting node.</para>
        ///     <para>Returns null if there is no path to any of the goals.</para>
        /// </summary>
        /// <param name="start">Starting node</param>
        /// <param name="goals">List of ending nodes</param>
        /// <param name="limiter">Maximum length of path to search for</param>
        public static List <MainNode> MultiAStar(MainNode start, List <T> goals, int limiter = int.MaxValue)
        {
            if (goals.All(g => g == null) || start == null)
            {
                return(null);
            }
            Stopwatch s    = Stopwatch.StartNew();
            var       open = new Heap <MainNode> {
                MinHeap = true
            };
            var closed   = new HashSet <MainNode>();
            var gs       = new Dictionary <MainNode, float>();
            var fs       = new Dictionary <MainNode, float>();
            var cameFrom = new Dictionary <MainNode, MainNode>();

            open.Add(start, 0.0f);
            while (open.Count > 0)
            {
                MainNode current = open.PopFirst().Object;
                if (goals.Exists(t => current.NodeEqual(t)))
                {
                    open.Clear();
                    closed.Clear();
                    var t = ToList(current, cameFrom);
                    s.Stop();
                    Add(ref _at, s.Elapsed.TotalMilliseconds);
                    return(t);
                }
                closed.Add(current);
                if (gs.GetValueOrDefault(current, 0f) > limiter)
                {
                    continue;
                }
                foreach (MainNode neighbor in current.GetNeighbors())
                {
                    var num = gs.GetValueOrDefault(current, 0f) + current.Distance(neighbor);
                    if ((closed.Contains(neighbor) ||
                         open.Contains(neighbor)) && num >= gs.GetValueOrDefault(neighbor, 0f))
                    {
                        continue;
                    }
                    cameFrom[neighbor] = current;
                    gs[neighbor]       = num;
                    fs[neighbor]       = gs[neighbor] + goals.Min(t => neighbor.Heuristic(t));
                    if (!open.Contains(neighbor))
                    {
                        open.Add(neighbor, fs[neighbor]);
                    }
                }
            }
            open.Clear();
            closed.Clear();
            s.Stop();
            Add(ref _at, s.Elapsed.TotalMilliseconds);
            return(null);
        }
예제 #2
0
        /// <summary>
        ///     Performs path search using Dijkstra's algorithm for a given predicate.
        ///     <para>Returns list of nodes from ending to starting node.</para>
        ///     <para>Returns null if there is no path to goal.</para>
        /// </summary>
        /// <param name="start">Starting node</param>
        /// <param name="targeting">Predicate distinguishing end nodes from the rest</param>
        /// <param name="limiter">Maximum length of path to search for</param>
        public static List <MainNode> Dijkstra(MainNode start, Predicate <MainNode> targeting, int limiter = int.MaxValue)
        {
            if (start == null)
            {
                return(null);
            }
            Stopwatch s    = Stopwatch.StartNew();
            var       open = new Heap <MainNode> {
                MinHeap = true
            };
            var closed   = new HashSet <MainNode>();
            var gs       = new Dictionary <MainNode, float>();
            var cameFrom = new Dictionary <MainNode, MainNode>();

            open.Add(start, 0.0f);
            while (open.Count > 0)
            {
                MainNode current = open.PopFirst().Object;
                if (targeting.Invoke(current))
                {
                    open.Clear();
                    closed.Clear();
                    var t = ToList(current, cameFrom);
                    s.Stop();
                    Add(ref _dt, s.Elapsed.TotalMilliseconds);
                    return(t);
                }
                closed.Add(current);
                if (gs.GetValueOrDefault(current, 0f) > limiter)
                {
                    continue;
                }
                foreach (MainNode neighbor in current.GetNeighbors())
                {
                    var num = gs.GetValueOrDefault(current, 0f) + current.Distance(neighbor);
                    if ((closed.Contains(neighbor) ||
                         open.Contains(neighbor)) && num >= gs.GetValueOrDefault(neighbor, 0f))
                    {
                        continue;
                    }
                    cameFrom[neighbor] = current;
                    gs[neighbor]       = num;
                    if (!open.Contains(neighbor))
                    {
                        open.Add(neighbor, gs.GetValueOrDefault(neighbor, 0f));
                    }
                }
            }
            open.Clear();
            closed.Clear();
            s.Stop();
            Add(ref _dt, s.Elapsed.TotalMilliseconds);
            return(null);
        }