forked from UNN/2026-rff_mp
250 lines
13 KiB
Markdown
250 lines
13 KiB
Markdown
# Отчёт по работе «Поиск выхода из лабиринта»
|
||
|
||
## 1. Цель работы
|
||
Разработать гибкую программу для загрузки лабиринта из файла, поиска пути от старта до выхода с возможностью выбора алгоритма, визуализации процесса и экспериментального сравнения алгоритмов. В работе использованы паттерны проектирования, чтобы отделить логику представления лабиринта, его загрузки, поиска пути и вывода результатов.
|
||
|
||
## 2. Описание задачи
|
||
Лабиринт задаётся в текстовом файле символами:
|
||
- `#` — стена;
|
||
- пробел — проход;
|
||
- `S` — старт;
|
||
- `E` — выход.
|
||
|
||
Программа должна:
|
||
- загружать лабиринт;
|
||
- строить его внутреннюю модель;
|
||
- искать путь разными алгоритмами;
|
||
- собирать статистику поиска;
|
||
- визуализировать результат в консоли;
|
||
- сравнивать стратегии на разных типах лабиринтов.
|
||
|
||
## 3. Выбранные паттерны проектирования
|
||
|
||
### 3.1 Builder
|
||
Паттерн Builder используется для загрузки лабиринта из файла. Он скрывает детали парсинга и валидации, а клиент получает готовый объект `Maze`.
|
||
|
||
Преимущества:
|
||
- легко добавить новый формат загрузки;
|
||
- клиентский код не зависит от формата файла;
|
||
- создание лабиринта можно расширять без переписывания остальной программы.
|
||
|
||
### 3.2 Strategy
|
||
Паттерн Strategy используется для выбора алгоритма поиска пути. В программе реализованы `BFS`, `DFS`, `A*`, а при необходимости можно добавить Дейкстру или любую другую стратегию.
|
||
|
||
Преимущества:
|
||
- алгоритм можно менять во время выполнения;
|
||
- код оркестратора не зависит от конкретного метода поиска;
|
||
- новые алгоритмы добавляются без изменения существующего кода.
|
||
|
||
### 3.3 Observer
|
||
Паттерн Observer используется для обновления консольного интерфейса при изменении состояния программы: загрузка лабиринта, поиск пути, движение игрока.
|
||
|
||
Преимущества:
|
||
- вывод отделён от логики;
|
||
- можно заменить консольный интерфейс на графический без изменения поискового кода;
|
||
- упрощается расширение визуализации.
|
||
|
||
### 3.4 Command
|
||
Паттерн Command используется для пошагового перемещения игрока и отмены последнего хода.
|
||
|
||
Преимущества:
|
||
- каждое действие оформляется как отдельный объект;
|
||
- легко реализовать undo;
|
||
- история ходов хранится отдельно от логики перемещения.
|
||
|
||
## 4. Диаграмма классов
|
||
Ниже приведена упрощённая диаграмма классов в формате Mermaid:
|
||
|
||
```mermaid
|
||
classDiagram
|
||
class Cell {
|
||
+int x
|
||
+int y
|
||
+bool isWall
|
||
+bool isStart
|
||
+bool isExit
|
||
+isPassable()
|
||
}
|
||
|
||
class Maze {
|
||
+cells
|
||
+width
|
||
+height
|
||
+startCell
|
||
+exitCell
|
||
+getCell(x, y)
|
||
+getNeighbors(cell)
|
||
}
|
||
|
||
class MazeBuilder {
|
||
<<interface>>
|
||
+buildFromFile(filename)
|
||
}
|
||
|
||
class TextFileMazeBuilder {
|
||
+buildFromFile(filename)
|
||
}
|
||
|
||
class PathFindingStrategy {
|
||
<<interface>>
|
||
+findPath(maze, start, exitCell)
|
||
}
|
||
|
||
class BFSStrategy {
|
||
+findPath(maze, start, exitCell)
|
||
}
|
||
|
||
class DFSStrategy {
|
||
+findPath(maze, start, exitCell)
|
||
}
|
||
|
||
class AStarStrategy {
|
||
+findPath(maze, start, exitCell)
|
||
}
|
||
|
||
class SearchStats {
|
||
+timeMs
|
||
+visitedCells
|
||
+pathLength
|
||
+path
|
||
}
|
||
|
||
class MazeSolver {
|
||
+maze
|
||
+strategy
|
||
+setStrategy(strategy)
|
||
+solve()
|
||
}
|
||
|
||
class Observer {
|
||
<<interface>>
|
||
+update(event)
|
||
}
|
||
|
||
class ConsoleView {
|
||
+update(event)
|
||
+render(maze, player_position, path)
|
||
}
|
||
|
||
class Command {
|
||
<<interface>>
|
||
+execute()
|
||
+undo()
|
||
}
|
||
|
||
class MoveCommand {
|
||
+execute()
|
||
+undo()
|
||
}
|
||
|
||
class Player {
|
||
+currentCell
|
||
+setCell(cell)
|
||
}
|
||
|
||
Maze <|-- TextFileMazeBuilder : creates
|
||
MazeBuilder <|.. TextFileMazeBuilder
|
||
PathFindingStrategy <|.. BFSStrategy
|
||
PathFindingStrategy <|.. DFSStrategy
|
||
PathFindingStrategy <|.. AStarStrategy
|
||
MazeSolver --> Maze
|
||
MazeSolver --> PathFindingStrategy
|
||
MazeSolver --> SearchStats
|
||
Observer <|.. ConsoleView
|
||
Command <|.. MoveCommand
|
||
MoveCommand --> Player
|
||
MoveCommand --> Maze
|
||
ConsoleView --> Maze
|
||
Maze --> Cell
|
||
```
|
||
|
||
## 5. Ключевые классы и их роль
|
||
|
||
### Cell
|
||
Хранит координаты клетки и её тип. Позволяет быстро проверять, является ли клетка проходимой.
|
||
|
||
### Maze
|
||
Содержит двумерную карту клеток, размер лабиринта, а также ссылки на старт и выход. Даёт доступ к соседним клеткам по четырём направлениям.
|
||
|
||
### TextFileMazeBuilder
|
||
Читает текстовый файл, создаёт объекты `Cell`, определяет старт и выход, затем возвращает готовый `Maze`.
|
||
|
||
### BFSStrategy
|
||
Ищет кратчайший путь по числу шагов. Подходит для случая, когда все переходы одинаковой стоимости.
|
||
|
||
### DFSStrategy
|
||
Быстро исследует пространство, но не гарантирует кратчайший путь. Полезен как сравнительный алгоритм.
|
||
|
||
### AStarStrategy
|
||
Использует эвристику Манхэттенского расстояния. Обычно посещает меньше клеток, чем BFS, если эвристика удачно направляет поиск к цели.
|
||
|
||
### MazeSolver
|
||
Оркестратор, который хранит лабиринт и текущую стратегию. Вызывает поиск, измеряет время и собирает статистику.
|
||
|
||
### SearchStats
|
||
Содержит итог поиска: время выполнения, количество посещённых клеток и длину пути.
|
||
|
||
### ConsoleView
|
||
Реализует наблюдателя и умеет выводить лабиринт и найденный путь в консоль.
|
||
|
||
### MoveCommand
|
||
Оформляет ход игрока как объект-команду. Поддерживает отмену последнего перемещения.
|
||
|
||
## 6. Экспериментальная часть
|
||
|
||
### 6.1 Подготовка тестовых лабиринтов
|
||
Для сравнения стратегий использовались следующие типы лабиринтов:
|
||
- маленький 10×10 с простым путём;
|
||
- средний 50×50 с тупиками;
|
||
- большой 100×100 со сложной структурой;
|
||
- пустой лабиринт без стен;
|
||
- лабиринт без выхода.
|
||
|
||
### 6.2 Методика измерений
|
||
Для каждой стратегии и каждого лабиринта поиск запускался несколько раз, после чего вычислялись средние значения:
|
||
- время поиска в миллисекундах;
|
||
- количество посещённых клеток;
|
||
- длина найденного пути.
|
||
|
||
Результаты сохранялись в CSV-файл в двух вариантах:
|
||
- сырой набор измерений;
|
||
- усреднённая таблица.
|
||
|
||
## 7. Анализ эффективности
|
||
|
||
### BFS
|
||
BFS гарантирует кратчайший путь по числу шагов, если все переходы имеют одинаковую стоимость. На простых и пустых лабиринтах работает стабильно и предсказуемо. Минус — может посещать много клеток, особенно на больших лабиринтах.
|
||
|
||
### DFS
|
||
DFS может быстро найти какой-то путь, но он не обязательно будет кратчайшим. На сложных лабиринтах иногда работает быстро, но на других может уйти далеко от цели и пройти лишние области.
|
||
|
||
### A*
|
||
A* использует эвристику и обычно показывает хороший баланс между скоростью и качеством пути. На больших и запутанных лабиринтах часто посещает меньше клеток, чем BFS, потому что поиск направлен в сторону выхода.
|
||
|
||
### Лабиринт без пути
|
||
Если пути нет, все алгоритмы вынуждены исследовать доступную область. В этом случае длина пути равна 0, а различия между алгоритмами проявляются в количестве просмотренных клеток и времени выполнения.
|
||
|
||
### Вывод по выбору алгоритма
|
||
- BFS стоит выбирать, когда нужен гарантированно кратчайший путь и веса переходов одинаковы.
|
||
- DFS полезен как простой и быстрый по реализации вариант, но без гарантии оптимальности.
|
||
- A* подходит для практических задач, где нужно ускорить поиск и сократить число посещённых клеток.
|
||
- При взвешенных переходах лучше использовать Дейкстру или взвешенный A*.
|
||
|
||
## 8. Роль ООП и паттернов
|
||
ООП и паттерны сделали код более гибким и расширяемым. Благодаря этому:
|
||
- можно заменить алгоритм поиска без переписывания логики программы;
|
||
- можно добавить новый формат загрузки лабиринта;
|
||
- можно поменять способ визуализации;
|
||
- можно расширить управление игроком и добавить отмену действий.
|
||
|
||
Без паттернов пришлось бы связывать загрузку, поиск, отображение и управление в один большой блок кода. Это усложнило бы отладку и дальнейшие изменения.
|
||
|
||
## 9. Вывод
|
||
В ходе работы была создана расширяемая программа для поиска пути в лабиринте. Использование паттернов Builder, Strategy, Observer и Command позволило разделить обязанности между классами, упростить поддержку кода и сделать архитектуру удобной для дальнейшего развития. Эксперименты показали, что выбор алгоритма сильно зависит от типа лабиринта: BFS даёт кратчайший путь, DFS иногда быстрее в реализации, а A* чаще всего наиболее практичен на больших картах.
|
||
|
||
## 10. Приложения
|
||
- Листинги ключевых классов.
|
||
- CSV-файлы с результатами экспериментов.
|
||
- Графики сравнений.
|
||
- Файлы с тестовыми лабиринтами.
|