Example #1
0
 /// <summary>
 /// Метод FindCell() возвращает
 /// направление по которому нужно пойти роботу, чтобы попасть в искомую соседнюю клетку.
 /// </summary>
 /// <param name="RequiredCell">Аргумент представляет искомую клетку
 /// </param>
 /// <returns>Возвращает направление по которому должен пойти робот,
 /// чтобы попасть в нужную соседнюю клетку и null,
 /// если по соседству такой клетки не найдено</returns>
 static Direction?FindCell(IRobot robot, Cell RequiredCell)
 {
     foreach (Direction neighbor in Enum.GetValues(typeof(Direction)))
     {
         Cell tmp = robot.AdjacentCell(neighbor);
         if (tmp == RequiredCell)
         {
             return(neighbor);
         }
     }
     return(null);
 }
Example #2
0
 static Direction?GetExitNeighbor(IRobot robot, List <Direction> UnvisitedNeighbors)
 {
     foreach (Direction neighbor in UnvisitedNeighbors)
     {
         Cell cell = robot.AdjacentCell(neighbor);
         if (cell.Type == CellType.Exit)
         {
             return(neighbor);
         }
     }
     return(null);
 }
Example #3
0
        /// <summary>
        /// Метод GetUnvisitedNeighbors() возвращает
        /// список направлений в которых находятся не посещенные клетки, которые не яляются стенами
        /// </summary>
        /// <param name="VisitedCells">Аргумент представляющий коллекцию посещенных клеток.
        /// Используется, чтобы проверить, что соседние клетки не были посещены ранее.
        /// </param>
        /// <param name="robot">Объект, реализующий интерфейс IRobot.
        /// Необходим для вызова метода AdjacentCell для просмотра соседних клеток по всем направлениям.
        /// </param>
        /// <returns>Возвращает список возможных направлений в виде списка объектов перечисления Direction</returns>
        static List <Direction> GetUnvisitedNeighbors(IRobot robot, List <Cell> VisitedCells)
        {
            List <Direction> UnvisitedNeighbors = new List <Direction>();

            foreach (Direction neighbor in Enum.GetValues(typeof(Direction)))
            {
                Cell tmp = robot.AdjacentCell(neighbor);
                if (tmp.Type != CellType.Wall && !VisitedCells.Contains(tmp))
                {
                    UnvisitedNeighbors.Add(neighbor);
                }
            }
            return(UnvisitedNeighbors);
        }
Example #4
0
        // алгоритм поиска выхода роботом
        // он основан на алгоритме обхода графа в ширину с трекингом положений робота при помощи стека

        public static void FindExit(IRobot robot)
        {
            //если уже находимся в выходе то выходим
            if (robot.CurrentCell.Type == CellType.Exit)
            {
                return;
            }

            List <Cell> opened = new List <Cell>();                                         // открытые вершины - чьи соседи не просмотрены
            List <Cell> closed = new List <Cell>();                                         // закрыте вершины  - чьи соседи просмотерны

            Stack <Tuple <Cell, Direction> > path = new Stack <Tuple <Cell, Direction> >(); // следим за роботом

            path.Push(new Tuple <Cell, Direction>(robot.CurrentCell, Direction.Left));      // для начальной вершины любое направление

            opened.Add(robot.CurrentCell);

            while (opened.Count > 0)
            {
                opened.Remove(robot.CurrentCell);
                closed.Add(robot.CurrentCell);

                bool move = false;

                Direction dir = Direction.Left;

                Cell cell2Move = null;

                // просмотрим все направления в порядке их объявления в перечислении Direction
                foreach (Direction d in Enum.GetValues(typeof(Direction)))
                {
                    // получить ячейку
                    var c = robot.AdjacentCell(d);

                    // ячейка является стеной или cоседи ячейки просмотрены
                    if (c.Type == CellType.Wall || closed.FirstOrDefault(item => item == c) != null)
                    {
                        continue;
                    }

                    // нашли выход
                    if (c.Type == CellType.Exit)
                    {
                        // перемешаемся в ячейку
                        robot.Move(d);
                        move = true;
                        // завершаем работу
                        return;
                    }

                    // добавляем ячейку в список на рассмотрение
                    opened.Add(c);

                    // запоминаем куда двигать робота
                    if (move == false)
                    {
                        dir       = d;
                        cell2Move = c;
                        move      = true;
                    }
                }

                // двигаем робота
                if (move == true && cell2Move != null)
                {
                    robot.Move(dir);
                    path.Push(new Tuple <Cell, Direction>(cell2Move, dir));
                }

                // если робот не был сдвинут, значит нужно вернуться в одну из оставшихся открытых вершин
                if (move == false && opened.Count > 0)
                {
                    while (path.Count > 0)
                    {
                        var t = path.Pop(); // находим предыдущую ячейку и двигаемся к ней

                        if (closed.FirstOrDefault(item => t.Item1 == item) == null)
                        {
                            throw new Exception("Открытая ячейка в пути!?");
                        }

                        // двигаем робота в обратном направлении
                        switch (t.Item2)
                        {
                        case Direction.Left:
                            robot.Move(Direction.Right);
                            break;

                        case Direction.Right:
                            robot.Move(Direction.Left);
                            break;

                        case Direction.Up:
                            robot.Move(Direction.Down);
                            break;

                        case Direction.Down:
                            robot.Move(Direction.Up);
                            break;
                        }

                        Cell cur = robot.CurrentCell;

                        // проверим есть ли открытые ячейки рядом
                        foreach (Direction d in Enum.GetValues(typeof(Direction)))
                        {
                            var c = robot.AdjacentCell(d);

                            if (opened.FirstOrDefault(item => item == c) != null) // переместимся в открытую ячейку
                            {
                                robot.Move(d);
                                path.Push(new Tuple <Cell, Direction>(c, d));
                                break;
                            }
                        }

                        if (cur != robot.CurrentCell)
                        {
                            break; //  робот пришел в открытую ячейку
                        }
                        if (path.Count == 0)
                        {
                            throw new Exception("Путь не может быть пустым, если еще остались открытые вершины");
                        }
                    }
                }
            }

            throw new ExitNotFoundException("Выход достичь нельзя!");
        }