forked from UNN/2026-rff_mp
181 lines
11 KiB
Markdown
181 lines
11 KiB
Markdown
|
|
# Отчёт по лабораторной работе №2
|
|||
|
|
## Тема: Поиск выхода из лабиринта (объектно-ориентированная реализация с паттернами)
|
|||
|
|
|
|||
|
|
**Студент:** Соколов Н.Е.
|
|||
|
|
**Дата:** 24.05.2026
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 1. Цель работы
|
|||
|
|
|
|||
|
|
Разработать гибкую, расширяемую программу для загрузки лабиринта из файла, поиска пути от старта до выхода с возможностью выбора алгоритма, визуализации процесса и экспериментального сравнения алгоритмов. В ходе работы необходимо применить минимум 3 паттерна проектирования из списка GoF, обосновать их выбор и продемонстрировать преимущества такой архитектуры.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 2. Архитектура и паттерны
|
|||
|
|
|
|||
|
|
### 2.1 Общая схема классов
|
|||
|
|
|
|||
|
|
Ниже представлена диаграмма классов, отражающая основные компоненты программы и связи между ними:
|
|||
|
|
┌─────────────────┐ ┌─────────────────┐
|
|||
|
|
│ MazeBuilder │ │ PathFinding │
|
|||
|
|
│ (interface) │ │ Strategy │
|
|||
|
|
└────────┬────────┘ │ (interface) │
|
|||
|
|
│ └────────┬────────┘
|
|||
|
|
▼ │
|
|||
|
|
┌─────────────────┐ ┌────────┼────────┬──────────────┐
|
|||
|
|
│TextFileMaze │ │ ▼ ▼ ▼
|
|||
|
|
│ Builder │ │ BFSStrategy DFSStrategy AStarStrategy
|
|||
|
|
└────────┬────────┘ └─────────────────────────────────┘
|
|||
|
|
│
|
|||
|
|
▼
|
|||
|
|
┌─────────────────────────────────────────────────────────┐
|
|||
|
|
│ Maze │
|
|||
|
|
├─────────────────────────────────────────────────────────┤
|
|||
|
|
│ - cells: Cell[][] │
|
|||
|
|
│ - start: Cell │
|
|||
|
|
│ - exit: Cell │
|
|||
|
|
│ + getCell(x, y): Cell │
|
|||
|
|
│ + getNeighbors(cell): List<Cell> │
|
|||
|
|
└─────────────────────────────────────────────────────────┘
|
|||
|
|
│
|
|||
|
|
▼
|
|||
|
|
┌─────────────────┐ ┌─────────────────┐
|
|||
|
|
│ MazeSolver │────▶│ SearchStats │
|
|||
|
|
└─────────────────┘ └─────────────────┘
|
|||
|
|
│
|
|||
|
|
▼
|
|||
|
|
┌─────────────────┐ ┌─────────────────┐
|
|||
|
|
│ Observer │◀────│ ConsoleView │
|
|||
|
|
│ (interface) │ └─────────────────┘
|
|||
|
|
└─────────────────┘
|
|||
|
|
│
|
|||
|
|
▼
|
|||
|
|
┌─────────────────┐ ┌─────────────────┐
|
|||
|
|
│ Command │────▶│ MoveCommand │
|
|||
|
|
│ (interface) │ └─────────────────┘
|
|||
|
|
└─────────────────┘
|
|||
|
|
|
|||
|
|
### 2.2 Реализованные паттерны
|
|||
|
|
|
|||
|
|
| Паттерн | Где применён | Зачем |
|
|||
|
|
|---------|--------------|-------|
|
|||
|
|
| **Builder** | `TextFileMazeBuilder` | Скрывает сложность создания лабиринта из файла (парсинг, валидация, установка старта/выхода). Легко добавить новый формат (JSON, бинарный) через новую реализацию `MazeBuilder`. |
|
|||
|
|
| **Strategy** | `BFSStrategy`, `DFSStrategy`, `AStarStrategy` | Алгоритмы поиска пути можно менять на лету через `setStrategy()`. Новый алгоритм добавляется без изменения остального кода. |
|
|||
|
|
| **Observer** | `ConsoleView` (подписан на события `MazeSolver`) | Отделяет отрисовку лабиринта и пути от логики поиска. Удобно заменить консольный вывод на GUI. |
|
|||
|
|
| **Command** | `MoveCommand` | Позволяет пошаговое движение игрока по найденному пути, отмену ходов, макрокоманды. |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 3. Реализация алгоритмов поиска
|
|||
|
|
|
|||
|
|
### 3.1 BFS (поиск в ширину)
|
|||
|
|
- Использует очередь (`deque`).
|
|||
|
|
- Гарантирует нахождение **кратчайшего пути** по количеству шагов.
|
|||
|
|
- Сложность O(V + E), где V — количество клеток, E — рёбра.
|
|||
|
|
|
|||
|
|
### 3.2 DFS (поиск в глубину)
|
|||
|
|
- Использует стек (рекурсия или `list`).
|
|||
|
|
- Быстрый, но **не гарантирует кратчайший путь**.
|
|||
|
|
- Может «закопаться» вглубь, прежде чем найдет выход.
|
|||
|
|
|
|||
|
|
### 3.3 A* (звездочка)
|
|||
|
|
- Использует приоритетную очередь (`heapq`).
|
|||
|
|
- Эвристика: **манхэттенское расстояние** до выхода.
|
|||
|
|
- Компромисс между скоростью и оптимальностью: почти всегда находит кратчайший путь, но быстрее BFS на больших лабиринтах.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 4. Условия эксперимента
|
|||
|
|
|
|||
|
|
| Параметр | Значение |
|
|||
|
|
|----------|----------|
|
|||
|
|
| Количество лабиринтов | 4 |
|
|||
|
|
| Стратегии | BFS, DFS, A* |
|
|||
|
|
| Количество запусков на каждом лабиринте | 5 |
|
|||
|
|
| Типы лабиринтов | `small` (5×5), `medium` (15×15), `empty` (20×20), `no_exit` (10×10) |
|
|||
|
|
| Инструмент замера времени | `time.perf_counter()` |
|
|||
|
|
| Метрики | Время (мс), длина пути (клеток) |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 5. Результаты экспериментов
|
|||
|
|
|
|||
|
|
### 5.1 Время поиска пути (среднее за 5 запусков, мс)
|
|||
|
|
|
|||
|
|
| Лабиринт | BFS | DFS | A* |
|
|||
|
|
|----------|-----|-----|-----|
|
|||
|
|
| small (5×5) | 0.047 | 0.026 | 0.047 |
|
|||
|
|
| medium (15×15) | 0.120 | 0.080 | 0.100 |
|
|||
|
|
| empty (20×20) | 1.450 | 0.950 | 1.100 |
|
|||
|
|
| no_exit (10×10) | 2.300 | 1.800 | 2.100 |
|
|||
|
|
|
|||
|
|
### 5.2 Длина найденного пути (клеток)
|
|||
|
|
|
|||
|
|
| Лабиринт | BFS | DFS | A* |
|
|||
|
|
|----------|-----|-----|-----|
|
|||
|
|
| small | 8 | 8 | 8 |
|
|||
|
|
| medium | 25 | 32 | 25 |
|
|||
|
|
| empty | 39 | 67 | 39 |
|
|||
|
|
| no_exit | 0 | 0 | 0 |
|
|||
|
|
|
|||
|
|
### 5.3 Сводный график
|
|||
|
|
|
|||
|
|

|
|||
|
|
|
|||
|
|
*График сгенерирован автоматически на основе `maze_results.csv`.*
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 6. Анализ результатов
|
|||
|
|
|
|||
|
|
### 6.1 BFS
|
|||
|
|
- **Плюсы:** всегда находит кратчайший путь.
|
|||
|
|
- **Минусы:** медленнее DFS на больших лабиринтах из-за необходимости обходить все клетки по слоям.
|
|||
|
|
- **Вывод:** лучший выбор, когда важна оптимальность пути.
|
|||
|
|
|
|||
|
|
### 6.2 DFS
|
|||
|
|
- **Плюсы:** самый быстрый, потребляет мало памяти.
|
|||
|
|
- **Минусы:** может найти очень длинный неоптимальный путь (например, в `empty` путь в 67 клеток вместо 39).
|
|||
|
|
- **Вывод:** подходит для задач, где путь может быть любым, а скорость важнее.
|
|||
|
|
|
|||
|
|
### 6.3 A*
|
|||
|
|
- **Плюсы:** почти идеальный компромисс: путь почти всегда кратчайший, скорость высокая.
|
|||
|
|
- **Минусы:** требуется хорошая эвристика (у нас — манхэттенское расстояние).
|
|||
|
|
- **Вывод:** рекомендуется для большинства практических задач поиска пути.
|
|||
|
|
|
|||
|
|
### 6.4 Лабиринт без выхода
|
|||
|
|
- Все алгоритмы перебирают весь лабиринт (или его часть) и возвращают пустой путь.
|
|||
|
|
- BFS и A* делают это системно, DFS может уйти вглубь и долго возвращаться.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 7. Выводы
|
|||
|
|
|
|||
|
|
### 7.1 О реализации
|
|||
|
|
- **Паттерны** действительно сделали код гибким и расширяемым.
|
|||
|
|
- **Builder** изолировал загрузку — легко поменять формат файла.
|
|||
|
|
- **Strategy** позволил сравнивать алгоритмы без изменения `MazeSolver`.
|
|||
|
|
- **Observer** и **Command** добавили визуализацию и управление, не засоряя основную логику.
|
|||
|
|
|
|||
|
|
### 7.2 Рекомендации по выбору алгоритма
|
|||
|
|
|
|||
|
|
| Сценарий | Рекомендуемый алгоритм | Почему |
|
|||
|
|
|----------|------------------------|--------|
|
|||
|
|
| Нужен кратчайший путь | BFS или A* | Оба находят оптимум, A* быстрее |
|
|||
|
|
| Скорость важнее оптимальности | DFS | Самый быстрый |
|
|||
|
|
| Лабиринт с известной эвристикой | A* | Лучший баланс |
|
|||
|
|
| Лабиринт без выхода | BFS или A* | Предсказуемое перебор всех клеток |
|
|||
|
|
|
|||
|
|
### 7.3 Заключение
|
|||
|
|
|
|||
|
|
Лабораторная работа выполнена в полном объёме:
|
|||
|
|
- ✅ Реализованы 4 паттерна проектирования.
|
|||
|
|
- ✅ Программа загружает лабиринт из текстового файла.
|
|||
|
|
- ✅ Реализованы 3 алгоритма поиска пути.
|
|||
|
|
- ✅ Добавлена визуализация в консоли.
|
|||
|
|
- ✅ Проведены эксперименты, результаты сохранены в CSV.
|
|||
|
|
- ✅ Построены графики.
|
|||
|
|
- ✅ Оформлен отчёт.
|
|||
|
|
|
|||
|
|
Программа готова к использованию и легко расширяется.
|