diff --git a/KuznetsovMA/lab2/docs/data/dead_time.png b/KuznetsovMA/lab2/docs/data/dead_time.png new file mode 100644 index 00000000..d440812f Binary files /dev/null and b/KuznetsovMA/lab2/docs/data/dead_time.png differ diff --git a/KuznetsovMA/lab2/docs/data/empty_time.png b/KuznetsovMA/lab2/docs/data/empty_time.png new file mode 100644 index 00000000..573b627b Binary files /dev/null and b/KuznetsovMA/lab2/docs/data/empty_time.png differ diff --git a/KuznetsovMA/lab2/docs/data/large_time.png b/KuznetsovMA/lab2/docs/data/large_time.png new file mode 100644 index 00000000..6d99e657 Binary files /dev/null and b/KuznetsovMA/lab2/docs/data/large_time.png differ diff --git a/KuznetsovMA/lab2/docs/data/noexit_time.png b/KuznetsovMA/lab2/docs/data/noexit_time.png new file mode 100644 index 00000000..8ac5ef66 Binary files /dev/null and b/KuznetsovMA/lab2/docs/data/noexit_time.png differ diff --git a/KuznetsovMA/lab2/docs/data/results.csv b/KuznetsovMA/lab2/docs/data/results.csv new file mode 100644 index 00000000..dfcc7272 --- /dev/null +++ b/KuznetsovMA/lab2/docs/data/results.csv @@ -0,0 +1,16 @@ +maze,strategy,time_ms,visited_cells,path_length +simple.txt,BFS,0.01464000015403144,11.0,6.0 +simple.txt,DFS,0.010180000390391797,9.0,8.0 +simple.txt,A*,0.017740000475896522,9.0,6.0 +dead.txt,BFS,0.3642999996372964,307.0,35.0 +dead.txt,DFS,0.23493999906349927,279.0,151.0 +dead.txt,A*,0.38374000068870373,235.0,35.0 +large.txt,BFS,23.894459999428364,6812.0,2329.0 +large.txt,DFS,84.77875999960816,6796.0,4537.0 +large.txt,A*,28.69542000044021,6791.0,2329.0 +empty.txt,BFS,1.2770400004228577,1176.0,48.0 +empty.txt,DFS,7.602279999264283,2304.0,1176.0 +empty.txt,A*,0.10093999881064519,48.0,48.0 +noexit.txt,BFS,0.003699999797390774,1.0,0.0 +noexit.txt,DFS,0.0032000003557186574,1.0,0.0 +noexit.txt,A*,0.004120000085094944,1.0,0.0 diff --git a/KuznetsovMA/lab2/docs/data/simple_time.png b/KuznetsovMA/lab2/docs/data/simple_time.png new file mode 100644 index 00000000..ecac6ff6 Binary files /dev/null and b/KuznetsovMA/lab2/docs/data/simple_time.png differ diff --git a/KuznetsovMA/lab2/docs/report.md b/KuznetsovMA/lab2/docs/report.md new file mode 100644 index 00000000..bb0e596d --- /dev/null +++ b/KuznetsovMA/lab2/docs/report.md @@ -0,0 +1,212 @@ +Лабораторная работа 2 + +Поиск выхода из лабиринта + +Цель работы +----------- +Цель работы состоит в реализации программы для поиска выхода из лабиринта с использованием объектно ориентированного подхода и паттернов проектирования + +В программе реализована загрузка лабиринта из файла несколько алгоритмов поиска и сравнение их работы + +Структура программы +------------------- +В программе используются классы Cell для отдельной клетки лабиринта и Maze для самого лабиринта + +Для загрузки используется MazeBuilder и его реализация TextFileMazeBuilder + +Для поиска пути используется общий класс PathFindingStrategy и три алгоритма BFSStrategy DFSStrategy и AStarStrategy + +За хранение результатов отвечает SearchStats а запуск поиска выполняет MazeSolver + +Для вывода информации используются Observer и ConsoleView + +Использованные паттерны +----------------------- +В работе использованы три паттерна Builder Strategy и Observer + +Builder используется для загрузки лабиринта из текстового файла + +TextFileMazeBuilder читает файл и создаёт объект Maze + +В файле символ # обозначает стену пробел обозначает свободную клетку S является началом а E выходом + +Использование Builder позволяет отдельно реализовать загрузку лабиринта и сам класс лабиринта + +Strategy используется для выбора алгоритма поиска + +В программе реализованы BFS DFS и A* + +Все алгоритмы имеют общий интерфейс PathFindingStrategy поэтому в MazeSolver можно менять алгоритм без изменения самого решателя + +Observer используется для вывода информации о поиске + +MazeSolver отправляет события а ConsoleView получает их и выводит информацию в консоль + +Таким образом вывод отделён от основной логики поиска + +Алгоритмы поиска +---------------- +BFS использует очередь и при обычных условиях находит кратчайший путь в лабиринте без весов + +DFS использует стек и может найти путь быстрее но найденный путь не обязательно будет кратчайшим + +A* использует очередь с приоритетом и манхэттенскую эвристику поэтому старается в первую очередь проверять клетки которые находятся ближе к выходу + +Схема классов +------------- +classDiagram + +class Cell { + x + y + is_wall + is_start + is_exit + is_passable() +} + +class Maze { + width + height + cells + start + exit + get_cell() + get_neighbors() +} + +class MazeBuilder { + build_from_file() +} + +class TextFileMazeBuilder { + build_from_file() +} + +class PathFindingStrategy { + find_path() +} + +class BFSStrategy { + find_path() +} + +class DFSStrategy { + find_path() +} + +class AStarStrategy { + find_path() +} + +class SearchStats { + path + time_ms + visited_count + path_length +} + +class MazeSolver { + maze + strategy + set_strategy() + solve() +} + +class Observer { + update() +} + +class ConsoleView { + update() +} + +MazeBuilder <|-- TextFileMazeBuilder +PathFindingStrategy <|-- BFSStrategy +PathFindingStrategy <|-- DFSStrategy +PathFindingStrategy <|-- AStarStrategy +Observer <|-- ConsoleView +MazeSolver --> Maze +MazeSolver --> PathFindingStrategy +MazeSolver --> Observer +Maze --> Cell +Тестирование +------------ +Для проверки использовалось пять разных лабиринтов + +simple.txt представляет простой лабиринт dead.txt содержит тупики large.txt является большим запутанным лабиринтом empty.txt не содержит стен а в noexit.txt выход недостижим + +Каждый алгоритм запускался пять раз + +Во время эксперимента измерялось время поиска количество посещённых клеток и длина найденного пути + +Результаты сохранялись в файл results.csv + +Результаты +---------- +simple.txt +Алгоритм Время мс Посещено Путь +BFS 0.01464 11 6 +DFS 0.01018 9 8 +A* 0.01774 9 6 + +Все алгоритмы работают быстро + +BFS и A* нашли более короткий путь чем DFS + +dead.txt +Алгоритм Время мс Посещено Путь +BFS 0.36430 307 35 +DFS 0.23494 279 151 +A* 0.38374 235 35 + +DFS работал немного быстрее но нашёл более длинный путь + +BFS и A* нашли короткий путь + +large.txt +Алгоритм Время мс Посещено Путь +BFS 23.89446 6812 2329 +DFS 84.77876 6796 4537 +A* 28.69542 6791 2329 + +На большом лабиринте DFS показал худшее время и самый длинный путь + +BFS и A* нашли одинаковый путь + +empty.txt +Алгоритм Время мс Посещено Путь +BFS 1.277 + + +04 1176 48 +DFS 7.60228 2304 1176 +A* 0.10094 48 48 + +В лабиринте без стен лучше всего показал себя A* + +Он посетил меньше всего клеток и работал быстрее + +noexit.txt +Алгоритм Время мс Посещено Путь +BFS 0.00370 1 0 +DFS 0.00320 1 0 +A* 0.00412 1 0 + +В этом лабиринте выход недостижим поэтому все алгоритмы быстро закончили поиск + +Графики +------- +Для сравнения времени работы были построены графики для каждого лабиринта + +Графики находятся в папке docs/data + +simple_time.png dead_time.png large_time.png empty_time.png и noexit_time.png + +Вывод +----- +В работе была создана программа для поиска выхода из лабиринта + +Были реализованы BFS DFS и A* а также использованы паттерны Builder Strategy и Observer + +По результатам эксперимента BFS хорошо подходит для поиска кратчайшего пути DFS может найти путь быстрее но он не всегда получается коротким A* хорошо показывает себя на больших и открытых лабиринтах diff --git a/KuznetsovMA/lab2/experiments.py b/KuznetsovMA/lab2/experiments.py new file mode 100644 index 00000000..f6693224 --- /dev/null +++ b/KuznetsovMA/lab2/experiments.py @@ -0,0 +1,93 @@ +import csv +import os + +from maze_solver import ( + TextFileMazeBuilder, + MazeSolver, + BFSStrategy, + DFSStrategy, + AStarStrategy +) + +REPEATS = 5 + +MAZES = [ + "simple.txt", + "dead.txt", + "large.txt", + "empty.txt", + "noexit.txt" +] + +STRATEGIES = [ + ("BFS", BFSStrategy()), + ("DFS", DFSStrategy()), + ("A*", AStarStrategy()) +] + +def average(values): + return sum(values) / len(values) + +def run(): + builder = TextFileMazeBuilder() + results = [] + + for maze_name in MAZES: + filename = os.path.join("lab2", "mazes", maze_name) + + print("Maze:", maze_name) + + for strategy_name, strategy in STRATEGIES: + times = [] + visited = [] + path_lengths = [] + + for _ in range(REPEATS): + maze = builder.build_from_file(filename) + + solver = MazeSolver(maze, strategy) + stats = solver.solve() + + times.append(stats.time_ms) + visited.append(stats.visited_count) + path_lengths.append(stats.path_length) + + results.append([ + maze_name, + strategy_name, + average(times), + average(visited), + average(path_lengths) + ]) + + print( + strategy_name, + "time =", average(times), + "visited =", average(visited), + "path =", average(path_lengths) + ) + + os.makedirs("lab2/docs/data", exist_ok=True) + + with open( + "lab2/docs/data/results.csv", + "w", + newline="", + encoding="utf-8" + ) as file: + writer = csv.writer(file) + + writer.writerow([ + "maze", + "strategy", + "time_ms", + "visited_cells", + "path_length" + ]) + + writer.writerows(results) + + print("Results saved to lab2/docs/data/results.csv") + +if __name__ == "__main__": + run() diff --git a/KuznetsovMA/lab2/graphs.py b/KuznetsovMA/lab2/graphs.py new file mode 100644 index 00000000..b49e2eb9 --- /dev/null +++ b/KuznetsovMA/lab2/graphs.py @@ -0,0 +1,23 @@ +import csv +import matplotlib.pyplot as plt + +with open("lab2/docs/data/results.csv", encoding="utf-8") as file: + rows = list(csv.DictReader(file)) + +mazes = ["simple.txt", "dead.txt", "large.txt", "empty.txt", "noexit.txt"] +strategies = ["BFS", "DFS", "A*"] + +for maze in mazes: + values = [] + + for strategy in strategies: + for row in rows: + if row["maze"] == maze and row["strategy"] == strategy: + values.append(float(row["time_ms"])) + + plt.bar(strategies, values) + plt.title("Время поиска: " + maze) + plt.xlabel("Стратегия") + plt.ylabel("Время, мс") + plt.savefig("lab2/docs/data/" + maze.replace(".txt", "_time.png")) + plt.close() diff --git a/KuznetsovMA/lab2/make_large.py b/KuznetsovMA/lab2/make_large.py new file mode 100644 index 00000000..715daff7 --- /dev/null +++ b/KuznetsovMA/lab2/make_large.py @@ -0,0 +1,26 @@ +lines = [] + +for y in range(100): + row = [" "] * 100 + + if y == 0 or y == 99: + row = ["#"] * 100 + else: + row[0] = "#" + row[99] = "#" + + lines.append(row) + +lines[1][1] = "S" +lines[98][98] = "E" + +for x in range(4, 96, 4): + gap = 1 if (x // 4) % 2 == 0 else 98 + + for y in range(1, 99): + if y != gap: + lines[y][x] = "#" + +with open("lab2/mazes/large.txt", "w", encoding="utf-8") as file: + for row in lines: + file.write("".join(row) + "\n") diff --git a/KuznetsovMA/lab2/maze_solver.py b/KuznetsovMA/lab2/maze_solver.py new file mode 100644 index 00000000..f99bc2d6 --- /dev/null +++ b/KuznetsovMA/lab2/maze_solver.py @@ -0,0 +1,284 @@ +from abc import ABC, abstractmethod +from collections import deque +import heapq +import time + +class Cell: + def __init__(self, x, y): + self.x = x + self.y = y + self.is_wall = False + self.is_start = False + self.is_exit = False + + def is_passable(self): + return not self.is_wall + +class Maze: + def __init__(self, width, height): + self.width = width + self.height = height + self.cells = [] + self.start = None + self.exit = None + + for y in range(height): + row = [] + + for x in range(width): + row.append(Cell(x, y)) + + self.cells.append(row) + + def get_cell(self, x, y): + if 0 <= x < self.width and 0 <= y < self.height: + return self.cells[y][x] + + return None + + def get_neighbors(self, cell): + neighbors = [] + + directions = [ + (0, -1), + (0, 1), + (-1, 0), + (1, 0) + ] + + for dx, dy in directions: + neighbor = self.get_cell( + cell.x + dx, + cell.y + dy + ) + + if neighbor and neighbor.is_passable(): + neighbors.append(neighbor) + + return neighbors + +class MazeBuilder(ABC): + @abstractmethod + def build_from_file(self, filename): + pass + +class TextFileMazeBuilder(MazeBuilder): + def build_from_file(self, filename): + with open(filename, "r", encoding="utf-8") as file: + lines = [line.rstrip("\n") for line in file] + + if not lines: + raise ValueError("Файл лабиринта пустой") + + width = len(lines[0]) + + for line in lines: + if len(line) != width: + raise ValueError("Строки лабиринта имеют разную длину") + + maze = Maze(width, len(lines)) + + for y, line in enumerate(lines): + for x, symbol in enumerate(line): + cell = maze.get_cell(x, y) + + if symbol == "#": + cell.is_wall = True + + elif symbol == "S": + if maze.start is not None: + raise ValueError("В лабиринте несколько стартов") + + maze.start = cell + cell.is_start = True + + elif symbol == "E": + if maze.exit is not None: + raise ValueError("В лабиринте несколько выходов") + + maze.exit = cell + cell.is_exit = True + + elif symbol == " ": + pass + + else: + raise ValueError("Неизвестный символ в лабиринте") + + if maze.start is None: + raise ValueError("В лабиринте нет старта") + + if maze.exit is None: + raise ValueError("В лабиринте нет выхода") + + return maze + +class PathFindingStrategy(ABC): + @abstractmethod + def find_path(self, maze, start, exit): + pass + +class BFSStrategy(PathFindingStrategy): + def find_path(self, maze, start, exit): + if start is None or exit is None: + return [], 0 + + queue = deque([(start, [start])]) + visited = {start} + + while queue: + current, path = queue.popleft() + + if current == exit: + return path, len(visited) + + for neighbor in maze.get_neighbors(current): + if neighbor not in visited: + visited.add(neighbor) + queue.append((neighbor, path + [neighbor])) + + return [], len(visited) + +class DFSStrategy(PathFindingStrategy): + def find_path(self, maze, start, exit): + if start is None or exit is None: + return [], 0 + + stack = [(start, [start])] + visited = {start} + + while stack: + current, path = stack.pop() + + if current == exit: + return path, len(visited) + + for neighbor in maze.get_neighbors(current): + if neighbor not in visited: + visited.add(neighbor) + stack.append((neighbor, path + [neighbor])) + + return [], len(visited) + +class AStarStrategy(PathFindingStrategy): + def heuristic(self, a, b): + return abs(a.x - b.x) + abs(a.y - b.y) + + def find_path(self, maze, start, exit): + if start is None or exit is None: + return [], 0 + + heap = [] + counter = 0 + + heapq.heappush( + heap, + (self.heuristic(start, exit), counter, start, [start]) + ) + + g_score = {start: 0} + visited = set() + + while heap: + _, _, current, path = heapq.heappop(heap) + + if current in visited: + continue + + visited.add(current) + + if current == exit: + return path, len(visited) + + for neighbor in maze.get_neighbors(current): + new_cost = g_score[current] + 1 + + if neighbor not in g_score or new_cost < g_score[neighbor]: + g_score[neighbor] = new_cost + counter += 1 + + priority = new_cost + self.heuristic( + neighbor, + exit + ) + + heapq.heappush( + heap, + ( + priority, + counter, + neighbor, + path + [neighbor] + ) + ) + + return [], len(visited) + +class SearchStats: + def __init__(self, path, time_ms, visited_count): + self.path = path + self.time_ms = time_ms + self.visited_count = visited_count + self.path_length = len(path) if path else 0 + +class MazeSolver: + def __init__(self, maze, strategy=None): + self.maze = maze + self.strategy = strategy + self.observers = [] + + def attach(self, observer): + self.observers.append(observer) + + def detach(self, observer): + self.observers.remove(observer) + + def notify(self, event, data=None): + for observer in self.observers: + observer.update(event, data) + + def set_strategy(self, strategy): + self.strategy = strategy + + def solve(self): + if self.strategy is None: + raise ValueError("Стратегия не установлена") + + self.notify("search_started") + + start_time = time.perf_counter() + + path, visited_count = self.strategy.find_path( + self.maze, + self.maze.start, + self.maze.exit + ) + + end_time = time.perf_counter() + + time_ms = (end_time - start_time) * 1000 + + self.notify("search_finished", time_ms) + self.notify("path_found", path) + + return SearchStats( + path, + time_ms, + visited_count + ) + +class Observer(ABC): + @abstractmethod + def update(self, event, data=None): + pass + +class ConsoleView(Observer): + def update(self, event, data=None): + if event == "search_started": + print("Поиск начат") + + elif event == "search_finished": + print(f"Поиск завершен за {data:.3f} мс") + + elif event == "path_found": + print(f"Длина пути: {len(data)}") diff --git a/KuznetsovMA/lab2/mazes/dead.txt b/KuznetsovMA/lab2/mazes/dead.txt new file mode 100644 index 00000000..0ed9b484 --- /dev/null +++ b/KuznetsovMA/lab2/mazes/dead.txt @@ -0,0 +1,20 @@ +#################### +#S # +# # +# # +# # +# # +# ######### # +# # # +# # # +# # # +# # # +# # # +# # # +# # # +# # # +# # +# # +# # +# E# +#################### diff --git a/KuznetsovMA/lab2/mazes/empty.txt b/KuznetsovMA/lab2/mazes/empty.txt new file mode 100644 index 00000000..cf65c33c --- /dev/null +++ b/KuznetsovMA/lab2/mazes/empty.txt @@ -0,0 +1,50 @@ +################################################## +#S # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +#E # +################################################## diff --git a/KuznetsovMA/lab2/mazes/large.txt b/KuznetsovMA/lab2/mazes/large.txt new file mode 100644 index 00000000..79ed92ff --- /dev/null +++ b/KuznetsovMA/lab2/mazes/large.txt @@ -0,0 +1,100 @@ +#################################################################################################### +#S # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # E# +#################################################################################################### diff --git a/KuznetsovMA/lab2/mazes/noexit.txt b/KuznetsovMA/lab2/mazes/noexit.txt new file mode 100644 index 00000000..0d9e9c53 --- /dev/null +++ b/KuznetsovMA/lab2/mazes/noexit.txt @@ -0,0 +1,10 @@ +########## +#S######## +########## +########## +########## +########## +########## +########## +########E# +########## diff --git a/KuznetsovMA/lab2/mazes/simple.txt b/KuznetsovMA/lab2/mazes/simple.txt new file mode 100644 index 00000000..b7edabb2 --- /dev/null +++ b/KuznetsovMA/lab2/mazes/simple.txt @@ -0,0 +1,5 @@ +####### +#S # +# ### # +# E # +#######