Пример #1
0
 public PFNode(INavable cube, PFNode prevNode, int cost)
 {
     this.cube     = cube;
     this.prevNode = prevNode;
     this.cost     = cost;
 }
Пример #2
0
    public void RequestAsync(INavable start, int maxDistance, Action <List <PFPath> > OnServe, Func <INavable, bool> cubeIgnore)
    {
        List <INavable> navables = new List <INavable>(mapMgr.map.Cubes);

        StartCoroutine(BFSPathfinding(start, navables, maxDistance, OnServe, cubeIgnore));
    }
Пример #3
0
    /// <summary>
    /// maxDistance로 갈수 있는 큐브들을 BFS로 찾아 OnServe콜백함수의 PFPath인자로 돌려줍니다.
    /// </summary>
    /// <param name="maxDistance">BFS로 찾을 최대 거리</param>
    /// <param name="OnServe">함수가 끝나면 호출할 함수를 전달하세요. 함수의 인자로 Path가 전달됩니다.</param>
    /// <param name="cubeIgnore">Path에 포함시키지 않을 Predicate</param>
    /// <returns></returns>
    private IEnumerator BFSPathfinding(
        INavable start, List <INavable> navables, int maxDistance,
        Action <List <PFPath> > OnServe, Func <INavable, bool> cubeIgnore)
    {
        OnSearchBegin();

        // 나중에 cost가 정해진 노드들만 path로 만들기 위함
        List <PFNode> table = new List <PFNode>();

        // BFS: Initialization
        Queue <PFNode> queue     = new Queue <PFNode>();
        PFNode         startNode = new PFNode(start, null, 0);

        queue.Enqueue(startNode);
        table.Add(startNode);

        // BFS: Traversal
        int maxLoop  = 40;
        int currLoop = 0;

        while (queue.Count > 0)
        {
            PFNode currNode = queue.Dequeue();
            if (currNode.cost >= maxDistance)
            {
                continue;
            }

            List <INavable> neighborCubes = currNode.cube.Neighbors;

            foreach (var neighborCube in neighborCubes)
            {
                if (cubeIgnore(neighborCube))
                {
                    continue;
                }
                if (table.Any(node => node.cube == neighborCube))
                {
                    continue;                                               // 이미 다른 Path에 있음
                }
                PFNode newNode = new PFNode(neighborCube, currNode, currNode.cost + 1);
                queue.Enqueue(newNode);
                table.Add(newNode);
            }
            currLoop++;

            if (currLoop >= maxLoop)
            {
                currLoop = 0;
                yield return(null);
            }
        }

        // Path Construction
        List <PFPath> paths = new List <PFPath>();

        currLoop = 0;
        foreach (var destination in table)
        {
            PFPath path = new PFPath(start, destination);
            path.Add(destination);

            PFNode currNode = destination;
            while (currNode.prevNode != null)
            {
                path.Add(currNode.prevNode);
                currNode = currNode.prevNode;
            }
            path.Reverse();

            paths.Add(path);

            currLoop++;
            if (currLoop >= maxLoop)
            {
                currLoop = 0;
                yield return(null);
            }
        }

        // return by Calling Callback Function
        OnServe(paths);
        OnSearchEnd();
    }