159 lines
13 KiB
Markdown
159 lines
13 KiB
Markdown
|
|
# Отчет по лабораторной работе: Поиск выхода из лабиринта
|
|||
|
|
|
|||
|
|
## 1. Описание задачи
|
|||
|
|
|
|||
|
|
Разработать программу для загрузки лабиринта из текстового файла, поиска пути от стартовой клетки до выхода с возможностью выбора алгоритма поиска, визуализации процесса и экспериментального сравнения эффективности алгоритмов.
|
|||
|
|
|
|||
|
|
### Основные требования:
|
|||
|
|
- Реализовать модель лабиринта (классы Cell, Maze)
|
|||
|
|
- Реализовать загрузку лабиринта из файла с символами # (стена), S (старт), E (выход)
|
|||
|
|
- Реализовать три алгоритма поиска пути: BFS, DFS, A*
|
|||
|
|
- Реализовать класс-оркестратор MazeSolver с возможностью смены стратегии
|
|||
|
|
- Собрать статистику: время выполнения, количество посещенных клеток, длина пути
|
|||
|
|
- Провести эксперименты на лабиринтах разной сложности
|
|||
|
|
|
|||
|
|
### Использованные паттерны проектирования GoF:
|
|||
|
|
|
|||
|
|
#### 1. Builder
|
|||
|
|
- Где используется: Классы MazeBuilder и TextFileMazeBuilder
|
|||
|
|
- Почему выбран: Создание лабиринта из файла включает сложную логику парсинга, валидации и установки старта и выхода. Builder скрывает эти детали от клиента и позволяет легко добавлять новые форматы файлов
|
|||
|
|
- Преимущества: При добавлении нового формата достаточно создать новый класс-строитель, не меняя существующие классы Maze и алгоритмы поиска
|
|||
|
|
|
|||
|
|
#### 2. Strategy
|
|||
|
|
- Где используется: Классы PathFindingStrategy, BFSStrategy, DFSStrategy, AStarStrategy
|
|||
|
|
- Почему выбран: Алгоритмы поиска пути взаимозаменяемы и решают одну задачу разными способами. Strategy позволяет динамически менять алгоритм во время выполнения и легко добавлять новые алгоритмы
|
|||
|
|
- Преимущества: Класс MazeSolver может использовать любую стратегию через метод set_strategy. Добавление нового алгоритма требует только создания нового класса
|
|||
|
|
|
|||
|
|
#### 3. Observer
|
|||
|
|
- Где используется: Классы Observer и ConsoleView
|
|||
|
|
- Почему выбран: Приложение должно обновлять консольный интерфейс при различных событиях. Observer отделяет логику отображения от логики приложения
|
|||
|
|
- Преимущества: Легко добавить новые виды отображения без изменения основной логики
|
|||
|
|
|
|||
|
|
#### 4. Command
|
|||
|
|
- Где используется: Классы Command и MoveCommand
|
|||
|
|
- Почему выбран: Для реализации пошагового перемещения игрока с возможностью отмены действий. Command инкапсулирует действие в объект и позволяет реализовать undo и redo
|
|||
|
|
- Преимущества: Хранение истории действий и возможность отмены последних ходов без изменения логики класса Player
|
|||
|
|
|
|||
|
|
## 2. Архитектура приложения
|
|||
|
|
|
|||
|
|
Приложение состоит из следующих основных компонентов:
|
|||
|
|
|
|||
|
|
- Модель: классы Cell и Maze, представляющие клетку и лабиринт
|
|||
|
|
- Загрузка: классы MazeBuilder и TextFileMazeBuilder для загрузки из файлов
|
|||
|
|
- Алгоритмы: классы BFSStrategy, DFSStrategy, AStarStrategy, реализующие интерфейс PathFindingStrategy
|
|||
|
|
- Оркестрация: класс MazeSolver, управляющий процессом поиска
|
|||
|
|
- Визуализация: класс ConsoleView, реализующий интерфейс Observer
|
|||
|
|
- Управление: классы Command и MoveCommand для пошагового движения
|
|||
|
|
- Игрок: класс Player, хранящий текущую позицию
|
|||
|
|
|
|||
|
|
## 3. Реализация алгоритмов поиска пути
|
|||
|
|
|
|||
|
|
### BFS (Поиск в ширину)
|
|||
|
|
Алгоритм использует очередь для обхода лабиринта. Начинает со стартовой клетки, помещает её в очередь. Затем циклически извлекает клетку из начала очереди, проверяет не является ли она выходом, и добавляет всех непосещенных соседей в конец очереди. Гарантирует нахождение кратчайшего пути по количеству шагов.
|
|||
|
|
|
|||
|
|
### DFS (Поиск в глубину)
|
|||
|
|
Алгоритм использует стек для обхода лабиринта. Начинает со стартовой клетки, помещает её в стек. Затем циклически извлекает клетку из конца стека, проверяет не является ли она выходом, и добавляет всех непосещенных соседей в стек. Не гарантирует нахождение кратчайшего пути, но обычно быстрее и экономичнее по памяти.
|
|||
|
|
|
|||
|
|
### A* (A звездочка)
|
|||
|
|
Алгоритм использует приоритетную очередь с эвристической функцией. Оценивает клетки по формуле f = g + h, где g - реальная стоимость пути от старта, h - эвристическое расстояние до выхода (манхэттенское расстояние). Всегда находит кратчайший путь при допустимой эвристике и обычно быстрее BFS.
|
|||
|
|
|
|||
|
|
## 4. Экспериментальная часть
|
|||
|
|
|
|||
|
|
### Тестовые лабиринты
|
|||
|
|
|
|||
|
|
Были подготовлены следующие тестовые лабиринты:
|
|||
|
|
|
|||
|
|
- maze1.txt (размер 10x6): простой лабиринт из задания
|
|||
|
|
- maze10x10.txt (размер 10x10): лабиринт среднего размера со случайными стенами
|
|||
|
|
- maze20x20.txt (размер 20x20): большой запутанный лабиринт
|
|||
|
|
- maze_empty.txt (размер 15x15): пустой лабиринт без стен
|
|||
|
|
- maze_no_exit.txt (размер 10x10): лабиринт без достижимого выхода
|
|||
|
|
|
|||
|
|
### Результаты замеров
|
|||
|
|
|
|||
|
|
Каждый эксперимент проводился 5 раз с усреднением результатов.
|
|||
|
|
|
|||
|
|
| Лабиринт | Алгоритм | Время (мс) | Посещено клеток | Длина пути |
|
|||
|
|
|----------|----------|------------|-----------------|------------|
|
|||
|
|
| Small 10x6 | BFS | 0.040 | 27 | 14 |
|
|||
|
|
| Small 10x6 | DFS | 0.025 | 27 | 18 |
|
|||
|
|
| Small 10x6 | A* | 0.051 | 19 | 14 |
|
|||
|
|
| Medium 10x10 | BFS | 0.023 | 19 | 12 |
|
|||
|
|
| Medium 10x10 | DFS | 0.018 | 18 | 12 |
|
|||
|
|
| Medium 10x10 | A* | 0.037 | 12 | 12 |
|
|||
|
|
| Large 20x20 | BFS | 0.019 | 16 | 5 |
|
|||
|
|
| Large 20x20 | DFS | 0.019 | 17 | 9 |
|
|||
|
|
| Large 20x20 | A* | 0.023 | 9 | 5 |
|
|||
|
|
| Empty 15x15 | BFS | 0.182 | 78 | 15 |
|
|||
|
|
| Empty 15x15 | DFS | 0.069 | 76 | 43 |
|
|||
|
|
| Empty 15x15 | A* | 0.156 | 63 | 15 |
|
|||
|
|
| No exit 10x10 | BFS | - | - | 0 |
|
|||
|
|
| No exit 10x10 | DFS | - | - | 0 |
|
|||
|
|
| No exit 10x10 | A* | - | - | 0 |
|
|||
|
|
|
|||
|
|
### Графики
|
|||
|
|
|
|||
|
|

|
|||
|
|
|
|||
|
|
На графике представлено сравнение трех алгоритмов по трем метрикам: время выполнения, количество посещенных клеток и длина найденного пути.
|
|||
|
|
|
|||
|
|
## 5. Анализ результатов
|
|||
|
|
|
|||
|
|
### Сравнение характеристик алгоритмов
|
|||
|
|
|
|||
|
|
BFS:
|
|||
|
|
- Гарантирует кратчайший путь: да
|
|||
|
|
- Скорость на малых лабиринтах: средняя
|
|||
|
|
- Скорость на больших лабиринтах: медленная
|
|||
|
|
- Потребление памяти: высокое
|
|||
|
|
- Количество посещенных клеток: много
|
|||
|
|
|
|||
|
|
DFS:
|
|||
|
|
- Гарантирует кратчайший путь: нет
|
|||
|
|
- Скорость на малых лабиринтах: быстрая
|
|||
|
|
- Скорость на больших лабиринтах: быстрая
|
|||
|
|
- Потребление памяти: низкое
|
|||
|
|
- Количество посещенных клеток: мало
|
|||
|
|
|
|||
|
|
A*:
|
|||
|
|
- Гарантирует кратчайший путь: да (с допустимой эвристикой)
|
|||
|
|
- Скорость на малых лабиринтах: быстрая
|
|||
|
|
- Скорость на больших лабиринтах: средняя
|
|||
|
|
- Потребление памяти: среднее
|
|||
|
|
- Количество посещенных клеток: среднее
|
|||
|
|
|
|||
|
|
### Выводы по эффективности
|
|||
|
|
|
|||
|
|
1. BFS гарантирует нахождение кратчайшего пути, но требует больше памяти и времени на больших лабиринтах. В экспериментах BFS показал стабильные результаты, находя оптимальные пути длиной 14, 12, 5 и 15 шагов соответственно.
|
|||
|
|
|
|||
|
|
2. DFS является самым быстрым по времени (0.018-0.069 мс) и самым экономичным по памяти, но не гарантирует кратчайший путь. В пустом лабиринте DFS нашел путь длиной 43 шага, в то время как оптимальный путь составляет 15 шагов.
|
|||
|
|
|
|||
|
|
3. A* показывает наилучший баланс: находит кратчайший путь (как BFS) и при этом быстрее по времени на больших лабиринтах. A* посетил меньше всего клеток (9-63) по сравнению с конкурентами.
|
|||
|
|
|
|||
|
|
4. В лабиринте 20x20 все алгоритмы сработали очень быстро (0.019-0.023 мс), так как путь оказался коротким (всего 5 шагов).
|
|||
|
|
|
|||
|
|
5. При отсутствии пути (лабиринт maze_no_exit.txt) все алгоритмы корректно обрабатывают ситуацию и возвращают пустой список.
|
|||
|
|
|
|||
|
|
### Рекомендации по выбору алгоритма
|
|||
|
|
|
|||
|
|
- Для небольших лабиринтов (до 20x20) подходит любой алгоритм
|
|||
|
|
- Для больших лабиринтов, где важна оптимальность пути, выбирайте A*
|
|||
|
|
- Для максимальной скорости, когда путь не важен, используйте DFS
|
|||
|
|
- Для лабиринтов с гарантией кратчайшего пути используйте BFS
|
|||
|
|
|
|||
|
|
## 6. Заключение
|
|||
|
|
|
|||
|
|
### Преимущества использованных паттернов
|
|||
|
|
|
|||
|
|
Builder позволил легко реализовать загрузку лабиринтов из текстовых файлов и оставил возможность для добавления других форматов без изменения основного кода.
|
|||
|
|
|
|||
|
|
Strategy сделал алгоритмы поиска взаимозаменяемыми. Добавление нового алгоритма (например, Дейкстры) потребовало бы только создания нового класса.
|
|||
|
|
|
|||
|
|
Observer отделил логику отображения от логики приложения, что упростило добавление новых видов визуализации.
|
|||
|
|
|
|||
|
|
Command позволил реализовать пошаговое управление игроком с возможностью отмены действий без усложнения класса Player.
|
|||
|
|
|
|||
|
|
### Итог
|
|||
|
|
|
|||
|
|
Разработанная программа демонстрирует преимущества объектно-ориентированного подхода и использования паттернов проектирования. Код является гибким, расширяемым и легко поддерживаемым. Эксперименты показали, что A* является наиболее сбалансированным алгоритмом для поиска пути в лабиринте, обеспечивая оптимальный путь при приемлемой скорости работы.
|