Пример #1
0
 /// <summary>
 /// 큐에서 해당 노드가 존재하는지 찾아 해당 노드를 반환합니다. 만약 존재하지 않는다면 -1을 반환합니다.
 /// </summary>
 /// <param name="queue">검색을 수행할 큐</param>
 /// <param name="node">찾으려는 노드</param>
 /// <returns></returns>
 private EPNode Find(IEnumerable <EPNode> queue, EPNode node)
 {
     foreach (EPNode item in queue)
     {
         if (item.Equals(node))
         {
             return(item);
         }
     }
     return(null);
 }
Пример #2
0
        /// <summary>
        /// 노드로부터 루트 까지의 경로를 콘솔 화면에 출력합니다.
        /// </summary>
        /// <param name="node"></param>
        /// <returns></returns>
        static public int PrintPath(EPNode node)
        {
            if (node == null)
            {
                return(-1);
            }

            int num = PrintPath(node.Parent) + 1;

            Console.WriteLine("Depth " + num);
            node.Print();
            return(num);
        }
Пример #3
0
        static void Main(string[] args)
        {
            Console.WriteLine("====== 8-Puzzle ================================");

            int[,] initial = new int[, ] {
                { 3, 8, 1 }, { 6, 2, 5 }, { 0, 4, 7 }
            };
            int[,] goal = new int[, ] {
                { 1, 2, 3 }, { 8, 0, 4 }, { 7, 6, 5 }
            };
            int limit = 10000;

            Console.WriteLine("Initial State : ");
            new EPNode(initial, 0, 0, 0, null).Print();
            Console.WriteLine("Goal State : ");
            new EPNode(goal, 0, 0, 0, null).Print();

            Console.WriteLine("Solve the 8-Puzzle within " + limit + " search(es).");
            Console.WriteLine("================================================");

            EightPuzzle puzzle = new EightPuzzle(initial, goal, limit)
            {
                DEBUG = false
            };
            EPNode result = puzzle.Solve();

            if (result != null)
            {
                Console.WriteLine("Solved!");
                Console.WriteLine("================================================");
                Console.WriteLine("Path : ");
                EightPuzzle.PrintPath(result);
            }
            else
            {
                Console.WriteLine("Failed!");
            }
        }
Пример #4
0
        /// <summary>
        /// A* 알고리즘을 사용한 8 퍼즐 문제 풀이를 시작합니다.
        /// </summary>
        /// <returns></returns>
        public EPNode Solve()
        {
            if (!_solvability)
            {
                return(null);
            }

            Console.WriteLine("Start searching.");

            int count = 0;

            EPNode rootNode = new EPNode(_initial, _blank[0], _blank[1], 0, null).Estimate(_goal);
            EPNode goalNode = new EPNode(_goal, 0, 0, 0, null); // for checking

            _OPEN.Enqueue(rootNode, rootNode.Distance + rootNode.Heuristic);

            while (_OPEN.Count > 0 && count < _LIMIT)
            {
                count++;
                // 예상 비용이 가장 낮은 노드 선택
                EPNode bestNode = _OPEN.Dequeue();

                // Console창 출력
                if (DEBUG)
                {
                    Console.WriteLine("Node #" + count);
                    bestNode.Print();
                }
                else
                {
                    Console.Write("Search count : " + count + " ");
                    for (int i = 0; i < (count / 200) % 10; i++)
                    {
                        Console.Write(".");
                    }
                }

                // CLOSED 큐에 추가
                _CLOSED.Add(bestNode);

                // 목표 도달
                if (bestNode.Equals(goalNode)) // Reached the goal!
                {
                    if (!DEBUG)
                    {
                        Console.WriteLine("...");
                    }
                    return(bestNode);
                }

                // 자식 노드 생성 (상, 하, 좌, 우 이동)
                EPNode[] movedNode = new EPNode[4];
                movedNode[0] = bestNode.MoveUp();
                movedNode[1] = bestNode.MoveDown();
                movedNode[2] = bestNode.MoveLeft();
                movedNode[3] = bestNode.MoveRight();

                // 각 자식 노드들에 대해 다음 연산을 수행
                for (int i = 0; i < 4; i++)
                {
                    // 해당 방향으로는 이동이 불가능한 경우. 해당 노드 무시.
                    if (movedNode[i] == null)
                    {
                        continue;                       // Hit the wall!
                    }
                    // OPEN, CLOSED 큐에서 해당 노드가 존재하는지 검색
                    EPNode nodeInOpen   = Find(_OPEN, movedNode[i]);
                    EPNode nodeInClosed = Find(_CLOSED, movedNode[i]);

                    if (nodeInOpen == null && nodeInClosed == null)   // OPEN, CLOSED 모두에 해당 노드가 존재하지 않는 경우
                    {
                        // 자식 노드의 추정값 계산
                        movedNode[i].Estimate(_goal);
                        _OPEN.Enqueue(movedNode[i], movedNode[i].Distance + movedNode[i].Heuristic);
                    }
                    else if (nodeInOpen != null)                         // OPEN 큐에 해당 노드가 존재할 경우
                    {                                                    // 만약 기존 노드보다 새로 생성한 자식 노드가 더 효율적일 때,
                        if (nodeInOpen.Distance > movedNode[i].Distance) // ( == Distance가 더 작을 때)
                        {
                            // 큐에 넣기 전 자식 노드의 추정값 계산(추정값은 큐에 이미 존재하는 노드와 같음)
                            movedNode[i].Estimate(_goal);
                            nodeInOpen = movedNode[i];                   // 새로 생성한 자식 노드로 기존 노드를 대체
                        }
                        else                                             // 그렇지 않으면,
                        {
                            continue;                                    // 그냥 무시하고 진행
                        }
                    }
                    else if (nodeInClosed != null)                    // OPEN 큐에는 없지만 CLOSED 큐에 해당 노드가 존재할 경우
                    {                                                 // 더 좋은 path가 나올 가능성이 없으므로 패스
                        continue;
                    }
                }

                if (!DEBUG)
                {
                    Console.Write("\r" + new string(' ', Console.WindowWidth - 1) + "\r");
                }
            }

            if (!DEBUG)
            {
                Console.WriteLine("...");
            }

            return(null);
        }