コード例 #1
0
ファイル: PathFindManager.cs プロジェクト: tianz0607/Tools
        public List <GridItem> GetNeighbors(GridItem source)
        {
            neighbors.Clear();
            for (int x = -1; x <= 1; x++)
            {
                for (int y = -1; y <= 1; y++)
                {
                    // 排除自己
                    if (x == 0 && y == 0)
                    {
                        continue;
                    }

                    int gridX = source.gridX + x;
                    int gridY = source.gridY + y;
                    if (IsValid(gridX, gridY))
                    {
                        var item = GetGridItem(gridX, gridY);
                        neighbors.Add(item);
                    }
                }
            }
            return(neighbors);
        }
コード例 #2
0
        /*
         * OPEN //开放列表
         * CLOSED //封闭列表
         * 把开始节点加入开放列表
         *
         * loop
         * //找出开放接列表F代价最小的节点
         * current = node in OPEN with the lowest f_cost
         * remove current from OPEN
         * add current to CLOSED
         *
         * if current is the target node //path has been found
         *         return
         *
         * // 遍历所有邻居
         * foreach neighbour of the current node
         *    // 如果邻居已经遍历过了,或者邻居已经在封闭列表就跳过
         *    if neighbour is not traversable or neighbour is in CLOSED
         *            skip to the next neighbour
         *    // 如果到这个邻居的路径更短或者这个邻居不在开发列表
         *    if new path to neighbour is shorter OR neighbour is not in OPEN
         *            set f_cost of neighbour
         *            set parent of neighbour to current
         *            if neighbour is not in OPEN
         *               add neighbour to OPEN
         */
        #endregion
        /// <summary>
        /// 输入起始点和结束点,输出路径列表
        /// A星算法核心公式就是F值的计算:
        /// F = G + H
        /// F - 方块的总移动代价
        /// G - 开始点到当前方块的移动代价
        /// H - 当前方块到结束点的预估移动代价
        /// </summary>
        public static List <IVisualStep> FindPath_AStar(PathFindManager mgr, GridItem start, GridItem end)
        {
            sw.Start();

            // Visual Step 算法步骤可视化
            List <IVisualStep> outSteps = new List <IVisualStep>();
            // ~Visual stuff

            bool               pathSuccess = false;
            List <GridItem>    openSet     = new List <GridItem>();
            HashSet <GridItem> closeSet    = new HashSet <GridItem>();

            openSet.Add(start);

            while (openSet.Count > 0)
            {
                var current = openSet[0];
                //找出开放列表中F代价最小的节点 todo 优化==》最优队列、或者最小堆
                foreach (var item in openSet)
                {
                    if (item.fCost < current.fCost)
                    {
                        current = item;
                    }
                }

                // Visual Step 算法步骤可视化
                if (current != start && current != end)
                {
                    outSteps.Add(new VisitedTileStep(current, mgr));
                }
                // ~Visual stuff

                openSet.Remove(current);
                closeSet.Add(current);

                if (current == end)
                {
                    sw.Stop();
                    Debug.Log("AStar found: " + sw.ElapsedMilliseconds + " ms");
                    pathSuccess = true;
                    break;
                }

                foreach (var neighbor in mgr.GetNeighbors(current))
                {
                    // 剔除封闭列表元素
                    if (closeSet.Contains(neighbor) || !neighbor.walkable)
                    {
                        continue;
                    }

                    // 逐个计算邻居的gCost
                    int newCostToNeighbour = current.gCost + GetDistance(current, neighbor);
                    //Debug.LogFormat("newCostToNeighbour:{0},neighbor.gCost:{1}", newCostToNeighbour, neighbor.gCost);
                    if (newCostToNeighbour < neighbor.gCost || !openSet.Contains(neighbor))
                    {
                        neighbor.gCost  = newCostToNeighbour;
                        neighbor.hCost  = GetDistance(end, neighbor);
                        neighbor.parent = current;//做成一个链表,最后用来做结果
                        //neighbor.SetText(string.Format("f:{0}\ng:{1}\nh:{2}", neighbor.fCost, neighbor.gCost,neighbor.hCost));
                        if (!openSet.Contains(neighbor))
                        {
                            openSet.Add(neighbor);
                        }
                        // Visual Step 算法步骤可视化
                        if (neighbor != end)
                        {
                            outSteps.Add(new PushTileInOpenSetStep(neighbor, mgr));
                        }
                        // ~Visual stuff
                    }
                }
            }

            if (pathSuccess)
            {
                var results = ReversePath(start, end);
                // Visual Step 算法步骤可视化
                foreach (var tile in results)
                {
                    if (tile == start || tile == end)
                    {
                        continue;
                    }
                    outSteps.Add(new MarkPathTileStep(tile, mgr));
                }
                return(outSteps);
                // ~Visual stuff
            }
            return(null);
        }
コード例 #3
0
        public static List <IVisualStep> FindPath_BFS(PathFindManager mgr, GridItem start, GridItem end)
        {
            sw.Start();

            // Visual Step 算法步骤可视化
            List <IVisualStep> outSteps = new List <IVisualStep>();
            // ~Visual stuff

            List <GridItem>    frontier = new List <GridItem>();
            HashSet <GridItem> visited  = new HashSet <GridItem>();

            //首先将根节点放入队列中。
            bool pathSuccess = false;

            start.parent = null;
            frontier.Add(start);
            visited.Add(start);

            while (frontier.Count > 0)
            {
                //从队列中取出第一个节点,并检验它是否为目标。
                var current = frontier[0];
                frontier.Remove(current);

                // Visual Step 算法步骤可视化
                if (current != start && current != end)
                {
                    outSteps.Add(new VisitedTileStep(current, mgr));
                }
                // ~Visual stuff

                //如果找到目标,则结束搜寻并回传结果。
                if (current == end)
                {
                    sw.Stop();
                    Debug.Log("BFS found: " + sw.ElapsedMilliseconds + " ms");
                    pathSuccess = true;
                    break;
                }

                ////否则将它所有尚未检验过的直接子节点(邻节点)加入队列中。
                foreach (var neighbor in mgr.GetNeighbors(current))
                {
                    Debug.Log(neighbor.ToString());
                    if (!visited.Contains(neighbor))
                    {
                        visited.Add(neighbor);
                        frontier.Add(neighbor);
                        neighbor.parent = current;

                        // Visual Step 算法步骤可视化
                        if (neighbor != end)
                        {
                            outSteps.Add(new PushTileInFrontierStep(neighbor, mgr, 0));
                        }
                        // ~Visual stuff
                    }
                }
            }
            if (pathSuccess)
            {
                var results = ReversePath(start, end);

                // Visual Step 算法步骤可视化
                foreach (var tile in results)
                {
                    if (tile == start || tile == end)
                    {
                        continue;
                    }
                    outSteps.Add(new MarkPathTileStep(tile, mgr));
                }
                return(outSteps);
                // ~Visual stuff
            }
            Debug.Log("BFS Can't Find!");

            return(null);
            //若队列为空,表示整张图都检查过了——亦即图中没有欲搜寻的目标。结束搜寻并回传“找不到目标”。
        }
コード例 #4
0
        public static List <IVisualStep> FindPath_GreedyBestFirstSearch(PathFindManager mgr, GridItem start, GridItem end)
        {
            sw.Start();

            // Visual Step 算法步骤可视化
            List <IVisualStep> outSteps = new List <IVisualStep>();
            // ~Visual stuff
            List <GridItem>    frontier = new List <GridItem>();
            HashSet <GridItem> visited  = new HashSet <GridItem>();

            start.hCost = 0;

            bool pathSuccess = false;

            start.parent = null;
            frontier.Add(start);
            visited.Add(start);

            while (frontier.Count > 0)
            {
                var current = frontier[0];
                //查找cost值最小的顶点A,放入path队列
                foreach (var item in frontier)
                {
                    if (item.hCost < current.hCost)
                    {
                        current = item;
                    }
                }
                frontier.Remove(current);

                // Visual Step 算法步骤可视化
                if (current != start && current != end)
                {
                    outSteps.Add(new VisitedTileStep(current, mgr));
                }
                // ~Visual stuff

                //如果找到目标,则结束搜寻并回传结果。
                if (current == end)
                {
                    sw.Stop();
                    Debug.Log("GreedyBestFirstSearch found: " + sw.ElapsedMilliseconds + " ms");
                    pathSuccess = true;
                    break;
                }
                //否则将它所有尚未检验过的直接子节点(邻节点)加入队列中。
                foreach (var neighbor in mgr.GetNeighbors(current))
                {
                    if (!visited.Contains(neighbor) && neighbor.walkable)
                    {
                        neighbor.hCost  = GetDistance(neighbor, end);
                        neighbor.parent = current;

                        visited.Add(neighbor);
                        frontier.Add(neighbor);

                        // Visual Step 算法步骤可视化
                        if (neighbor != end)
                        {
                            outSteps.Add(new PushTileInFrontierStep(neighbor, mgr, neighbor.hCost));
                        }
                        // ~Visual stuff
                    }
                }
            }

            if (pathSuccess)
            {
                var results = ReversePath(start, end);
                // Visual Step 算法步骤可视化
                foreach (var tile in results)
                {
                    if (tile == start || tile == end)
                    {
                        continue;
                    }
                    outSteps.Add(new MarkPathTileStep(tile, mgr));
                }
                return(outSteps);
                // ~Visual stuff
            }
            Debug.Log("GreedyBestFirstSearch Can't Find!");

            return(null);
        }
コード例 #5
0
        public static List <IVisualStep> FindPath_Dijkstra(PathFindManager mgr, GridItem start, GridItem end)
        {
            sw.Start();

            // Visual Step 算法步骤可视化
            List <IVisualStep> outSteps = new List <IVisualStep>();
            // ~Visual stuff
            List <GridItem>    frontier = new List <GridItem>();
            HashSet <GridItem> visited  = new HashSet <GridItem>();

            //初始时,只有起始顶点的预估值cost为0,其他顶点的预估值d都为无穷大 ∞。
            foreach (var tile in mgr.GridItems)
            {
                tile.gCost = int.MaxValue;
            }

            start.gCost = 0;

            bool pathSuccess = false;

            start.parent = null;
            frontier.Add(start);
            visited.Add(start);

            while (frontier.Count > 0)
            {
                var current = frontier[0];
                //查找cost值最小的顶点A,放入path队列
                foreach (var item in frontier)
                {
                    if (item.gCost < current.gCost)
                    {
                        current = item;
                    }
                }
                frontier.Remove(current);

                // Visual Step 算法步骤可视化
                if (current != start && current != end)
                {
                    outSteps.Add(new VisitedTileStep(current, mgr));
                }
                // ~Visual stuff

                //如果找到目标,则结束搜寻并回传结果。
                if (current == end)
                {
                    sw.Stop();
                    Debug.Log("Dijkstra found: " + sw.ElapsedMilliseconds + " ms");
                    pathSuccess = true;
                    break;
                }

                //否则将它所有尚未检验过的直接子节点(邻节点)加入队列中。
                foreach (var neighbor in mgr.GetNeighbors(current))
                {
                    int newCostToNeighbour = current.gCost + neighbor.weight;
                    if (newCostToNeighbour < neighbor.gCost || !visited.Contains(neighbor))
                    {
                        neighbor.gCost  = newCostToNeighbour;
                        neighbor.parent = current;

                        visited.Add(neighbor);
                        frontier.Add(neighbor);

                        // Visual Step 算法步骤可视化
                        if (neighbor != end)
                        {
                            outSteps.Add(new PushTileInFrontierStep(neighbor, mgr, neighbor.gCost));
                        }
                        // ~Visual stuff
                    }
                }
            }

            if (pathSuccess)
            {
                var results = ReversePath(start, end);
                // Visual Step 算法步骤可视化
                foreach (var tile in results)
                {
                    if (tile == start || tile == end)
                    {
                        continue;
                    }
                    outSteps.Add(new MarkPathTileStep(tile, mgr));
                }
                return(outSteps);
                // ~Visual stuff
            }
            Debug.Log("Dijkstra Can't Find!");

            return(null);
        }
コード例 #6
0
ファイル: PathFindManager.cs プロジェクト: letian0111/Tools
        public IEnumerable <GridItem> GetNeighbors(GridItem tile)
        {
            neighbors.Clear();
            // 九宫格
            //for(int x = -1; x <= 1; x++)
            //{
            //    for(int y = -1; y <= 1; y++)
            //    {
            //        // 排除自己
            //        if(x == 0 && y == 0)
            //            continue;

            //        int gridX = source.gridX + x;
            //        int gridY = source.gridY + y;
            //        if(IsValid(gridX, gridY))
            //        {
            //            var item = GetGridItem(gridX, gridY);
            //            neighbors.Add(item);
            //        }
            //    }
            //}
            // 四格
            //for(int i = 0; i < neighborMap.Count; i++)
            //{
            //    var array = neighborMap[i];
            //    int gridX = tile.gridX + array[0];
            //    int gridY = tile.gridY + array[1];
            //    if(IsValid(gridX, gridY))
            //    {
            //        var item = GetGridItem(gridX, gridY);
            //        neighbors.Add(item);
            //    }
            //}

            //return neighbors;

            var right = GetGridItem(tile.gridX, tile.gridY + 1);

            if (right != null)
            {
                yield return(right);
            }

            var up = GetGridItem(tile.gridX - 1, tile.gridY);

            if (up != null)
            {
                yield return(up);
            }

            var left = GetGridItem(tile.gridX, tile.gridY - 1);

            if (left != null)
            {
                yield return(left);
            }

            var down = GetGridItem(tile.gridX + 1, tile.gridY);

            if (down != null)
            {
                yield return(down);
            }
        }
コード例 #7
0
ファイル: PathFinder.cs プロジェクト: tianz0607/Tools
        /*
         * OPEN //开放列表
         * CLOSED //封闭列表
         * 把开始节点加入开放列表
         *
         * loop
         * //找出开放接列表F代价最小的节点
         * current = node in OPEN with the lowest f_cost
         * remove current from OPEN
         * add current to CLOSED
         *
         * if current is the target node //path has been found
         *         return
         *
         * // 遍历所有邻居
         * foreach neighbour of the current node
         *    // 如果邻居已经遍历过了,或者邻居已经在封闭列表就跳过
         *    if neighbour is not traversable or neighbour is in CLOSED
         *            skip to the next neighbour
         *    // 如果到这个邻居的路径更短或者这个邻居不在开发列表
         *    if new path to neighbour is shorter OR neighbour is not in OPEN
         *            set f_cost of neighbour
         *            set parent of neighbour to current
         *            if neighbour is not in OPEN
         *               add neighbour to OPEN
         */
        #endregion
        /// <summary>
        /// 输入起始点和结束点,输出路径列表
        /// A星算法核心公式就是F值的计算:
        /// F = G + H
        /// F - 方块的总移动代价
        /// G - 开始点到当前方块的移动代价
        /// H - 当前方块到结束点的预估移动代价
        /// </summary>
        public static List <GridItem> FindPath_AStar(PathFindManager mgr, GridItem start, GridItem end)
        {
            sw.Start();

            bool pathSuccess = false;

            openSet  = new List <GridItem>();
            closeSet = new HashSet <GridItem>();

            openSet.Add(start);

            while (openSet.Count > 0)
            {
                var current = openSet[0];
                //找出开放列表中F代价最小的节点 todo 优化==》最优队列、或者最小堆
                foreach (var item in openSet)
                {
                    if (item.fCost < current.fCost)
                    {
                        current = item;
                    }
                }

                openSet.Remove(current);
                closeSet.Add(current);

                if (current == end)
                {
                    sw.Stop();
                    Debug.Log("Path found: " + sw.ElapsedMilliseconds + " ms");
                    pathSuccess = true;
                    break;
                }

                var neighbors = mgr.GetNeighbors(current);
                foreach (var neighbor in neighbors)
                {
                    // 剔除封闭列表元素
                    if (closeSet.Contains(neighbor) || !neighbor.walkable)
                    {
                        continue;
                    }

                    // 逐个计算邻居的gCost
                    int newCostToNeighbour = current.gCost + GetDistance(current, neighbor);
                    if (newCostToNeighbour < neighbor.gCost || !openSet.Contains(neighbor))
                    {
                        neighbor.gCost  = newCostToNeighbour;
                        neighbor.hCost  = GetDistance(end, neighbor);
                        neighbor.parent = current;//做成一个链表,最后用来做结果
                        neighbor.SetText(string.Format("f:{0}\ng:{1}\nh:{2}", neighbor.fCost, neighbor.gCost, neighbor.hCost));
                        if (openSet.Contains(neighbor))
                        {
                            //openSet
                        }
                        else
                        {
                            openSet.Add(neighbor);
                        }
                    }
                }
            }

            if (pathSuccess)
            {
                var results = RetracePath(start, end);
                pathSuccess = results.Count > 0;
                return(results);
            }
            return(null);
        }