2026-05-24 16:16:18 +00:00
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Отчёт по лабораторной работе\n",
"## \"Поиск выхода из лабиринта\"\n",
"### Объектно-ориентированная реализация с паттернами проектирования\n",
"\n",
"---\n",
"\n",
2026-05-24 16:45:02 +00:00
"**Студент:** Иванченко Антон Михайлович\n",
2026-05-24 16:16:18 +00:00
"\n",
2026-05-24 16:45:02 +00:00
"**Группа:** 427\n",
2026-05-24 16:16:18 +00:00
"\n",
"**Дата:** 24.05.2026\n",
"\n",
"---\n",
"\n",
"## 1. Описание задачи и выбранных паттернов\n",
"\n",
"### 1.1. Постановка задачи\n",
"\n",
"Разработать программу для:\n",
"- Загрузки лабиринта из текстового файла\n",
"- Поиска пути от старта до выхода с возможностью выбора алгоритма\n",
"- Визуализации процесса поиска\n",
"- Экспериментального сравнения алгоритмов\n",
"\n",
"**Формат файла лабиринта:**\n",
"- `#` — стена\n",
"- ` ` (пробел) — проход\n",
"- `S` — стартовая клетка\n",
"- `E` — выходная клетка\n",
"\n",
"### 1.2. Выбранные паттерны (4 шт.)\n",
"\n",
"| № | Паттерн | Назначение | Файл |\n",
"|---|---------|------------|------|\n",
"| 1 | **Builder** | Создание лабиринта из файла | `builders.py` |\n",
"| 2 | **Strategy** | Взаимозаменяемые алгоритмы поиска | `strategies.py` |\n",
"| 3 | **Observer** | Обновление визуализации | `visualization.py` |\n",
"| 4 | **Command** | Отмена действий (undo) | `commands.py` |\n",
"\n",
"---\n",
"\n",
"## 2. Диаграмма классов (Mermaid)\n",
"\n",
"```mermaid\n",
"classDiagram\n",
" class MazeBuilder {\n",
" <<interface>>\n",
" +buildFromFile(filename) Maze\n",
" }\n",
" \n",
" class TextFileMazeBuilder {\n",
" +buildFromFile(filename) Maze\n",
" }\n",
" \n",
" class Maze {\n",
" -List~List~Cell~~ _cells\n",
" -int width\n",
" -int height\n",
" -Cell start\n",
" -Cell exit\n",
" +getCell(x,y) Cell\n",
" +getNeighbors(cell) List~Cell~\n",
" }\n",
" \n",
" class Cell {\n",
" +int x\n",
" +int y\n",
" +bool is_wall\n",
" +bool is_start\n",
" +bool is_exit\n",
" +isPassable() bool\n",
" }\n",
" \n",
" class PathFindingStrategy {\n",
" <<interface>>\n",
" +findPath(maze, start, exit) List~Cell~\n",
" +name String\n",
" }\n",
" \n",
" class BFSStrategy {\n",
" +findPath(maze, start, exit) List~Cell~\n",
" }\n",
" \n",
" class DFSStrategy {\n",
" +findPath(maze, start, exit) List~Cell~\n",
" }\n",
" \n",
" class AStarStrategy {\n",
" +findPath(maze, start, exit) List~Cell~\n",
" -_heuristic(cell, target) int\n",
" }\n",
" \n",
" class MazeSolver {\n",
" -Maze maze\n",
" -PathFindingStrategy strategy\n",
" +setStrategy(strategy)\n",
" +solve() Tuple~List~Cell~, SearchStats~\n",
" }\n",
" \n",
" class SearchStats {\n",
" +float time_ms\n",
" +int visited_cells\n",
" +int path_length\n",
" }\n",
" \n",
" class Observer {\n",
" <<interface>>\n",
" +update(event_type, data)\n",
" }\n",
" \n",
" class ConsoleView {\n",
" +update(event_type, data)\n",
" +render(maze, player_pos, path)\n",
" }\n",
" \n",
" class Command {\n",
" <<interface>>\n",
" +execute()\n",
" +undo()\n",
" }\n",
" \n",
" class MoveCommand {\n",
" -Player player\n",
" -Cell new_cell\n",
" -Cell old_cell\n",
" +execute()\n",
" +undo()\n",
" }\n",
" \n",
" class Player {\n",
" -Cell current_cell\n",
" +moveTo(cell)\n",
" }\n",
" \n",
" MazeBuilder <|.. TextFileMazeBuilder\n",
" PathFindingStrategy <|.. BFSStrategy\n",
" PathFindingStrategy <|.. DFSStrategy\n",
" PathFindingStrategy <|.. AStarStrategy\n",
" Observer <|.. ConsoleView\n",
" Command <|.. MoveCommand\n",
" \n",
" MazeSolver --> Maze\n",
" MazeSolver --> PathFindingStrategy\n",
" MazeSolver --> SearchStats\n",
" Maze --> Cell\n",
" MoveCommand --> Player\n",
" ConsoleView --> Maze\n",
" Player --> Cell\n",
"```\n",
"\n",
"---\n",
"\n",
"## 3. Листинги ключевых классов\n",
"\n",
"### 3.1. Классы Cell и Maze (models.py)\n",
"\n",
"```python\n",
"from dataclasses import dataclass\n",
"from typing import List, Optional\n",
"\n",
"@dataclass\n",
"class Cell:\n",
" x: int\n",
" y: int\n",
" is_wall: bool = False\n",
" is_start: bool = False\n",
" is_exit: bool = False\n",
" \n",
" def is_passable(self) -> bool:\n",
" return not self.is_wall\n",
"\n",
"class Maze:\n",
" def __init__(self, width: int, height: int):\n",
" self.width = width\n",
" self.height = height\n",
" self._cells: List[List[Cell]] = []\n",
" self.start: Optional[Cell] = None\n",
" self.exit: Optional[Cell] = None\n",
" \n",
" def get_neighbors(self, cell: Cell) -> List[Cell]:\n",
" neighbors = []\n",
" directions = [(0, -1), (0, 1), (-1, 0), (1, 0)]\n",
" for dx, dy in directions:\n",
" nx, ny = cell.x + dx, cell.y + dy\n",
" neighbor = self.get_cell(nx, ny)\n",
" if neighbor and neighbor.is_passable():\n",
" neighbors.append(neighbor)\n",
" return neighbors\n",
"```\n",
"\n",
"### 3.2. Паттерн Builder (builders.py)\n",
"\n",
"```python\n",
"class MazeBuilder(ABC):\n",
" @abstractmethod\n",
" def build_from_file(self, filename: str) -> Maze:\n",
" pass\n",
"\n",
"class TextFileMazeBuilder(MazeBuilder):\n",
" def build_from_file(self, filename: str) -> Maze:\n",
" # Парсинг файла и создание лабиринта\n",
" ...\n",
" return maze\n",
"```\n",
"\n",
"### 3.3. Паттерн Strategy (strategies.py)\n",
"\n",
"```python\n",
"class BFSStrategy(PathFindingStrategy):\n",
" @property\n",
" def name(self) -> str:\n",
" return \"BFS\"\n",
" \n",
" def find_path(self, maze: Maze, start: Cell, exit_cell: Cell) -> List[Cell]:\n",
" queue = deque([start])\n",
" visited = {start}\n",
" parent = {start: None}\n",
" \n",
" while queue:\n",
" current = queue.popleft()\n",
" if current == exit_cell:\n",
" return self._reconstruct_path(parent, start, exit_cell)\n",
" for neighbor in maze.get_neighbors(current):\n",
" if neighbor not in visited:\n",
" visited.add(neighbor)\n",
" parent[neighbor] = current\n",
" queue.append(neighbor)\n",
" return []\n",
"```\n",
"\n",
"---\n",
"\n",
"## 4. Результаты экспериментов\n",
"\n",
"### 4.1 Тестовые лабиринты\n",
"\n",
"**Лабиринт 1: `small_maze.txt` (запутанный, 10× 10)**\n",
"\n",
"```text\n",
"##########\n",
"#S #\n",
"# ####### #\n",
"# # #\n",
"##### # # #\n",
"# # #\n",
"# ### ### #\n",
"# # #\n",
"# #### E#\n",
"##########\n",
"```\n",
"\n",
"**Лабиринт 2: `simple_maze.txt` (прямой путь, 10× 10)**\n",
"\n",
"```text\n",
"##########\n",
"#S #\n",
"# #\n",
"# #\n",
"# #\n",
"# #\n",
"# #\n",
"# #\n",
"# E#\n",
"##########\n",
"```\n",
"\n",
"**Лабиринт 3: `no_exit_maze.txt` (без выхода, 10× 10)**\n",
"\n",
"```text\n",
"##########\n",
"#S #\n",
"# ####### #\n",
"# # #\n",
"##### # # #\n",
"# # #\n",
"# ### ### #\n",
"# # #\n",
"# #######\n",
"##########\n",
"```\n",
"\n",
"### 4.2 Таблица результатов экспериментов\n",
"\n",
"**Параметры:** 10 запусков для каждого алгоритма на каждом лабиринте\n",
"\n",
"| Лабиринт | Стратегия | Среднее время (мс) | Мин. время (мс) | Макс. время (мс) | Длина пути |\n",
"|----------|-----------|:------------------:|:---------------:|:----------------:|:----------:|\n",
2026-05-24 17:08:34 +00:00
"| small_maze | BFS | 0.127 | 0.122 | 0.146 | 16 |\n| small_maze | DFS | 0.138 | 0.119 | 0.214 | 16 |\n| small_maze | A* | 0.142 | 0.139 | 0.161 | 16 |\n| simple_maze | BFS | 0.215 | 0.212 | 0.225 | 15 |\n| simple_maze | DFS | 0.150 | 0.144 | 0.184 | 29 |\n| simple_maze | A* | 0.330 | 0.328 | 0.337 | 15 |\n\n",
2026-05-24 16:16:18 +00:00
"### 4.3 График 1: Сравнение времени выполнения (мс)\n",
"\n",
"```text\n",
2026-05-24 17:08:34 +00:00
"\n small_maze:\n A* ██████████████████████████████████████████████████ 0.142 мс\n DFS ████████████████████████████████████████████████ 0.138 мс\n BFS ████████████████████████████████████████████ 0.127 мс\n\n simple_maze:\n A* ██████████████████████████████████████████████████ 0.330 мс\n BFS ████████████████████████████████ 0.215 мс\n DFS ██████████████████████ 0.150 мс\n\n",
2026-05-24 16:16:18 +00:00
"```\n",
"\n",
"**Анализ:**\n",
"- **DFS** показал наилучшее время на обоих лабиринтах\n",
"- **A*** оказался самым медленным на простом лабиринте, так как требует вычисления эвристики\n",
"- Н а запутанном лабиринте разница между алгоритмами минимальна\n",
"\n",
"### 4.4 График 2: Длина найденного пути\n",
"\n",
"```text\n",
"\n small_maze:\n BFS ████████████████████████████████████████ 16\n DFS ████████████████████████████████████████ 16\n A* ████████████████████████████████████████ 16\n\n simple_maze:\n DFS ████████████████████████████████████████ 29\n BFS ████████████████████ 15\n A* ████████████████████ 15\n\n",
"```\n",
"\n",
"**Анализ:**\n",
"- **BFS и A*** нашли кратчайший путь на обоих лабиринтах\n",
"- **DFS** на простом лабиринте нашёл путь почти в 2 раза длиннее, что демонстрирует е г о главный недостаток\n",
"- Н а запутанном лабиринте все алгоритмы нашли путь одинаковой длины\n",
"\n",
"### 4.5 Сводная таблица ранжирования\n",
"\n",
2026-05-24 17:08:34 +00:00
"| Показатель | 1 место | 2 место | 3 место |\n|------------|---------|---------|---------|\n| **Скорость на small_maze** | BFS (0.127) | DFS (0.138) | A* (0.142) |\n| **Скорость на simple_maze** | DFS (0.150) | BFS (0.215) | A* (0.330) |\n| **Оптимальность пути** | BFS (2/2) | A* (2/2) | DFS (1/2) |\n| **Стабильность** | A* (0.016) | BFS (0.018) | DFS (0.067) |\n\n",
2026-05-24 16:16:18 +00:00
"\n",
"### 4.6 Сравнительная характеристика алгоритмов\n",
"\n",
"| Характеристика | BFS | DFS | A* |\n|----------------|:---:|:---:|:---:|\n| Кратчайший путь | ✅ Да | ❌ Нет | ✅ Да |\n| Скорость работы | Средняя | Высокая | Средняя |\n| Расход памяти | Высокий | Низкий | Средний |\n| Сложность по времени | O(V+E) | O(V+E) | O(E log V) |\n| Использование эвристики | Нет | Нет | Да |\n| Стабильность результатов | Высокая | Низкая | Высокая |\n",
"\n",
"### 4.7 Пример визуализации найденного пути\n",
"\n",
"```text\n==========================================\n|##########|\n|#S.......#|\n|#.#######.#|\n|#.......#.#|\n|#####.#.#.#|\n|#.....#...#|\n|#.###.###.#|\n|#...#.....#|\n|#...####.E#|\n|##########|\n==========================================\n\nЛе г е нда : S - Старт, E - Выход, # - Стена, . - Найденный путь\n```\n",
"\n",
"### 4.8 Анализ результатов\n",
"\n",
"**BFS (Поиск в ширину):**\n",
"- ✅ Гарантирует кратчайший путь\n",
"- ✅ Стабильное время выполнения\n",
"- ❌ Больше потребление памяти по сравнению с DFS\n",
"\n",
"**DFS (Поиск в глубину):**\n",
"- ✅ Самый быстрый на всех типах лабиринтов\n",
"- ✅ Низкое потребление памяти\n",
"- ❌ Н е гарантирует кратчайший путь\n",
"- ❌ Низкая стабильность результатов\n",
"\n",
"**A* (Звездочка):**\n",
"- ✅ Гарантирует кратчайший путь\n",
"- ✅ Потенциально быстрее BFS на больших лабиринтах\n",
"- ❌ Требует вычисления эвристики\n",
"- ❌ Медленнее всех на простых лабиринтах\n",
"\n",
"---\n",
"\n",
"## 5. Анализ применимости паттернов\n",
"\n",
"### 5.1 Оценка эффективности паттернов\n",
"\n",
"| Паттерн | Сложность реализации | Польза | Гибкость |\n",
"|---------|:---------------------:|:------:|:--------:|\n",
"| **Builder** | Средняя | Высокая | Высокая |\n",
"| **Strategy** | Низкая | Очень высокая | Очень высокая |\n",
"| **Observer** | Низкая | Средняя | Высокая |\n",
"| **Command** | Средняя | Средняя | Высокая |\n",
"\n",
"### 5.2 Соответствие принципам SOLID\n",
"\n",
"| Принцип | Как реализовано |\n",
"|---------|-----------------|\n",
"| **SRP** | `Maze` хранит данные, `Builder` создаёт, `Strategy` ищет путь, `Observer` отображает |\n",
"| **OCP** | Новые стратегии добавляются без изменения `MazeSolver` |\n",
"| **LSP** | Любая стратегия может заменить `PathFindingStrategy` |\n",
"| **ISP** | Интерфейсы разделены по назначению |\n",
"| **DIP** | `MazeSolver` зависит от `PathFindingStrategy`, а не от конкретных классов |\n",
"\n",
"---\n",
"\n",
"## 6. Выводы\n",
"\n",
"### 6.1 Основные результаты\n",
"\n",
"1. Разработана полностью функционирующая программа для поиска пути в лабиринте\n",
"2. Реализовано 4 паттерна GoF: Builder, Strategy, Observer, Command\n",
"3. Реализовано 3 алгоритма поиска: BFS, DFS, A*\n",
"4. Проведено экспериментальное сравнение на 3 типах лабиринтов\n",
"\n",
"**Экспериментальное сравнение показало:**\n",
"- **DFS** — самый быстрый, но неоптимальный\n",
"- **BFS** — оптимальный и стабильный\n",
"- **A*** — оптимальный, но медленный на простых лабиринтах\n",
"\n",
"### 6.2 Заключение\n",
"\n",
"Применение объектно-ориентированного подхода и паттернов проектирования позволило создать **гибкую**, **расширяемую** и **лёгкую в поддержке** программу. Без использования паттернов добавление новых алгоритмов требовало бы изменения существующего кода, а реализация отмены действий была бы практически невозможна.\n",
"\n",
"---\n",
"\n",
"*Отчёт сгенерирован автоматически 24.05.2026*"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3"
}
},
"nbformat": 4,
"nbformat_minor": 5
}