Beispiel #1
0
        static void Main(string[] args)
        {
            GraphViewer gv;
            string      graph1 = "...........\n" +
                                 ".OOOOOOOOO.\n" +
                                 ".O...O...O.\n" +
                                 ".OOOOOOOOO.\n" +
                                 ".O...O...O.\n" +
                                 ".OOOOOOOOO.\n" +
                                 "...........";

            string graph2 = ".......\n" +
                            ".O...O.\n" +
                            ".O...O.\n" +
                            ".OOOOO.\n" +
                            "...O...\n" +
                            "...O...\n" +
                            ".......\n";

            string graph3 = "...........\n" +
                            ".OOOOOOOOO.\n" +
                            ".O...O...O.\n" +
                            ".O...O...O.\n" +
                            ".O...O...O.\n" +
                            ".....O.....\n" +
                            ".....O.....\n" +
                            ".....O.....\n" +
                            ".OOOOOOOOO.\n" +
                            "...........\n";

            string graph4 = ".........................\n" +
                            ".O...OOOOOOOOOOOOOOO...O.\n" +
                            ".O.......O.....O.......O.\n" +
                            ".O.......O.....O.......O.\n" +
                            ".O.......O.....O.......O.\n" +
                            ".O.......O.....O.......O.\n" +
                            ".OOOOOOOOO.....OOOOOOOOO.\n" +
                            ".....O.............O.....\n" +
                            ".....O......O......O.....\n" +
                            ".....O......O......O.....\n" +
                            ".....O......O......O.....\n" +
                            ".OOOOOOOOOOOOOOOOOOOOOOO.\n" +
                            ".........................\n";

            string graph5 = "...........................\n" +
                            ".OOOOOOOOOOOOOOOOOOOOOOOOO.\n" +
                            ".O.....O.....O.....O.....O.\n" +
                            ".O.....O.....O.....O.....O.\n" +
                            ".OOOOOOOOOOOOOOOOOOOOOOOOO.\n" +
                            ".O.....O.....O.....O.....O.\n" +
                            ".O.....O.....O.....O.....O.\n" +
                            ".OOOOOOOOOOOOOOOOOOOOOOOOO.\n" +
                            ".O.....O.....O.....O.....O.\n" +
                            ".O.....O.....O.....O.....O.\n" +
                            ".OOOOOOOOOOOOOOOOOOOOOOOOO.\n" +
                            ".O.....O.....O.....O.....O.\n" +
                            ".O.....O.....O.....O.....O.\n" +
                            ".OOOOOOOOOOOOOOOOOOOOOOOOO.\n" +
                            "...........................\n";

            lowMap   = new LowLevelMap('O', '.', graph4);
            lowRobot = new LowLevelRobot(lowMap, 1, 1);

            MapNode firstNode = ExploreMap(lowRobot.CheckNode(), null, 0, null);
            double  distToSecond;

            Console.WriteLine("[DFS 결과]");
            Console.WriteLine($"Node 수 : {nodeList.Count}");
            foreach (var ele in nodeList)
            {
                Console.WriteLine($"{ele.NodeNumber} : ({ele.Position}), ({ele.Error})");
            }

            gv = new GraphViewer();
            gv.AddPoints(firstNode);
            gv.Show();

            Direction secondDir = firstNode.FindDirOf(nodeList[1]).Value;

            TurnRobot(secondDir);
            distToSecond = firstNode.GetDist(secondDir);

            lowRobot.Move(1);

            robotPos.Node1     = firstNode;
            robotPos.Node2     = nodeList[1];
            robotPos.DivRatio1 = 1;
            robotPos.DivRatio2 = distToSecond - 1;

            Console.Write("최단 거리를 탐색할 위치를 입력하세요. (입력형식: {node1} {node2} {ratio1} {ratio2}) : ");
            string[] token = Console.ReadLine().Split();

            MapPosition dest = new MapPosition();

            dest.Node1     = nodeList[int.Parse(token[0])];
            dest.Node2     = nodeList[int.Parse(token[1])];
            dest.DivRatio1 = double.Parse(token[2]);
            dest.DivRatio2 = double.Parse(token[3]);

            Queue <Command> commands = new Queue <Command>();
            double          dist;

            FindShortestRoute(dest, commands, out dist);

            Console.WriteLine($"최단 거리: {dist}");
            while (commands.Count > 0)
            {
                Console.WriteLine(commands.Dequeue().ToString());
            }

            Console.WriteLine("아무키나 누르면 디버그를 종료합니다...");
            Console.ReadKey(true);
        }
Beispiel #2
0
        static bool FindShortestRoute(MapPosition dest, Queue <Command> commQueue, out double resultDist)
        {
            if (dest.IsSameSection(robotPos))
            {
                if ((dest.Node1.NodeNumber > dest.Node2.NodeNumber) != (robotPos.Node1.NodeNumber > robotPos.Node2.NodeNumber))
                {
                    MapNode temp = dest.Node2;
                    dest.Node2 = dest.Node1;
                    dest.Node1 = temp;
                }

                if (dest.Dist1 < robotPos.Dist1)
                {
                    AddTurningToQueue(commQueue, lowRobot.Dir, dest.Node2.FindDirOf(dest.Node1).Value);
                    commQueue.Enqueue(new Command()
                    {
                        Act = Action.GoStraight, Dist = robotPos.Dist1 - dest.Dist1
                    });
                    resultDist = robotPos.Dist1 - dest.Dist1;
                }

                else
                {
                    AddTurningToQueue(commQueue, lowRobot.Dir, dest.Node1.FindDirOf(dest.Node2).Value);
                    commQueue.Enqueue(new Command()
                    {
                        Act = Action.GoStraight, Dist = dest.Dist1 - robotPos.Dist1
                    });
                    resultDist = dest.Dist1 - robotPos.Dist1;
                }

                return(true);
            }

            int[] route;

            // 로봇이 v1과 v2 정점 사이에 있는데, v1과 v2의 거리

            double dist = Dijkstra(robotPos.Node1.NodeNumber, robotPos.Dist1, robotPos.Node2.NodeNumber, robotPos.Dist2, dest, out route);

            if (dist == -1)
            {
                resultDist = -1;
                return(false);
            }

            Direction virtualRobotDir;

            // Node1에서 시작하는 경로일 때
            if (route[0] == robotPos.Node1.NodeNumber)
            {
                Direction dirOfNode1 = robotPos.Node2.FindDirOf(robotPos.Node1).Value;
                AddTurningToQueue(commQueue, lowRobot.Dir, dirOfNode1);

                virtualRobotDir = dirOfNode1;
            }
            // Node2에서 시작하는 경로일 때
            else
            {
                Direction dirOfNode2 = robotPos.Node1.FindDirOf(robotPos.Node2).Value;
                AddTurningToQueue(commQueue, lowRobot.Dir, dirOfNode2);

                virtualRobotDir = dirOfNode2;
            }

            commQueue.Enqueue(new Command()
            {
                Act = Action.GoToNextNode, NextExpect = nodeList[route[0]]
            });

            // route[i]와 route[i + 1]의 위치관계를 파악하여 큐 작성
            for (int i = 0; i < route.Length - 1; ++i)
            {
                Direction nextDir = nodeList[route[i]].FindDirOf(nodeList[route[i + 1]]).Value;
                AddTurningToQueue(commQueue, virtualRobotDir, nextDir);
                virtualRobotDir = nextDir;
                commQueue.Enqueue(new Command()
                {
                    Act = Action.GoToNextNode, NextExpect = nodeList[route[i + 1]]
                });
            }

            AddTurningToQueue(commQueue, virtualRobotDir, (route.Last() == dest.Node1.NodeNumber ? dest.Node1.FindDirOf(dest.Node2) : dest.Node2.FindDirOf(dest.Node1)).Value);

            commQueue.Enqueue(new Command()
            {
                Act = Action.GoStraight, Dist = (route.Last() == dest.Node1.NodeNumber ? dest.Dist1 : dest.Dist2)
            });

            resultDist = dist;
            return(true);
        }
Beispiel #3
0
        /// <summary>
        /// 로봇이 처음 실행될 때 라인의 전체 경로를 파악하기 위해 DFS 탐색을 함.
        /// </summary>
        static MapNode ExploreMap(Junction currJunc, MapNode prev, double errorAdded, Direction?cameFrom)
        {
            Console.WriteLine("ExploreMap");

            Point currPoint = new Point {
                X = lowRobot.X, Y = lowRobot.Y
            };

            Console.WriteLine($"{currPoint}, {(prev == null ? "(Null)" : (prev.Error + errorAdded).ToString())}, {errorAdded}");

            if (prev != null)
            {
                List <MapNode> nearList = new List <MapNode>();
                foreach (MapNode node in nodeList)
                {
                    if (IsSameNode(currPoint, node.Position, currJunc, node.Junction, prev.Error + errorAdded))
                    {
                        nearList.Add(node);
                    }
                }

                // 현재 위치한 정점이 이미 방문한 정점일 때, 로봇의 위치 정보와 오차를 조정하고 return.
                if (nearList.Count > 0)
                {
                    MapNode sameNode = nearList[0];

                    foreach (MapNode near in nearList)
                    {
                        if (sameNode.Position - currPoint > near.Position - currPoint)
                        {
                            sameNode = near;
                        }
                    }

                    Console.WriteLine($"FoundSame: [{sameNode}]");
                    Console.WriteLine($"(nearList: {string.Join("/", nearList)})");

                    Point  newError = sameNode.Error;
                    double maxError = Math.Max(Math.Abs(prev.Position.X - sameNode.Position.X), Math.Abs(prev.Position.Y - sameNode.Position.Y));
                    newError.X += maxError;
                    newError.Y += maxError;

                    if (newError.X < prev.Error.X || newError.Y < prev.Error.Y)
                    {
                        prev.Error = newError;
                    }

                    return(sameNode);
                }
            }

            MapNode newNode = new MapNode();

            newNode.Position   = currPoint;
            newNode.NodeNumber = nodeList.Count;
            newNode.Junction   = currJunc;
            newNode.Error      = prev == null ? new Point(errorAdded, errorAdded) : prev.Error + errorAdded;
            nodeList.Add(newNode);
            nodeConnection.Add(new List <NodeDistPair>());
            Console.WriteLine("Node Added: " + newNode);

            List <Direction> visitLater = new List <Direction>();

            foreach (Direction dirToExplore in DIRS_FOR_DFS)
            {
                if (currJunc[dirToExplore] && !(cameFrom != null && cameFrom.Value == dirToExplore) && newNode[dirToExplore] == null)
                {
                    if (usedDir[(int)dirToExplore] != 0)
                    {
                        visitLater.Add(dirToExplore);
                    }
                    else
                    {
                        ++usedDir[(int)dirToExplore];
                        ExploreDir(dirToExplore, newNode);
                        --usedDir[(int)dirToExplore];
                    }
                }
            }

            foreach (Direction dir in visitLater.OrderBy(x => usedDir[(int)x]))
            {
                ++usedDir[(int)dir];
                ExploreDir(dir, newNode);
                --usedDir[(int)dir];
            }

            return(newNode);
        }
Beispiel #4
0
 public NodeDistPair(MapNode node, double dist)
 {
     Node = node ?? throw new ArgumentNullException(nameof(node));
     Dist = dist;
 }