from builders import TextFileMazeBuilder from strategies import BFSStrategy, DFSStrategy, AStarStrategy from solver import MazeSolver from observers import ConsoleView from experiments import run_experiments, save_to_csv import random WALL = '■' PASSAGE = ' ' START = 'S' EXIT = 'E' def generate_maze_prim(size: int, filename: str, label: str): random.seed(hash(filename) % 10000) grid = [[WALL for _ in range(size)] for _ in range(size)] start_x, start_y = 1, 1 grid[start_y][start_x] = PASSAGE walls = [] for dx, dy in [(0, -1), (0, 1), (-1, 0), (1, 0)]: wall_x = start_x + dx wall_y = start_y + dy cell_x = start_x + 2*dx cell_y = start_y + 2*dy if 0 <= cell_x < size and 0 <= cell_y < size: if grid[wall_y][wall_x] == WALL: walls.append((wall_x, wall_y, start_x, start_y, cell_x, cell_y)) while walls: idx = random.randint(0, len(walls) - 1) wall_x, wall_y, from_x, from_y, to_x, to_y = walls.pop(idx) if grid[to_y][to_x] == WALL: grid[wall_y][wall_x] = PASSAGE grid[to_y][to_x] = PASSAGE for dx, dy in [(0, -1), (0, 1), (-1, 0), (1, 0)]: new_wall_x = to_x + dx new_wall_y = to_y + dy new_cell_x = to_x + 2*dx new_cell_y = to_y + 2*dy if 0 <= new_cell_x < size and 0 <= new_cell_y < size: if grid[new_wall_y][new_wall_x] == WALL: walls.append((new_wall_x, new_wall_y, to_x, to_y, new_cell_x, new_cell_y)) grid[1][1] = START grid[size-2][size-2] = EXIT with open(filename, 'w', encoding='utf-8') as f: for row in grid: f.write(''.join(row) + '\n') print(f"✓ {label}: {filename}") def generate_small_maze(filename='small_maze.txt'): maze = [ "■■■■■■■■■■", "■S ■", "■ ■■■■ ■ ■", "■ ■ ■ ■ ■", "■ ■ ■■ ■ ■", "■ ■ ■ ■", "■ ■■■■■■ ■", "■ ■", "■ ■■■■■■■■", "■ E■", "■■■■■■■■■■" ] with open(filename, 'w', encoding='utf-8') as f: f.write('\n'.join(maze)) print(f"Маленький лабиринт 10x10: {filename}") def generate_no_exit_maze(filename='no_exit_maze.txt'): maze = [ "■■■■■■■■■■", "■S ■", "■ ■■■■ ■ ■", "■ ■ ■ ■ ■", "■ ■ ■■ ■ ■", "■ ■ ■ ■", "■ ■■■■■■ ■", "■ ■", "■ ■■■■■■■■", "■ ■■■■■■", "■■■■■E■■■■" ] with open(filename, 'w', encoding='utf-8') as f: f.write('\n'.join(maze)) print(f"Лабиринт без выхода 10x10: {filename}") def generate_empty_maze(filename='empty_maze.txt'): size = 10 maze = [] maze.append(WALL * size) for i in range(size - 2): if i == 0: row = WALL + START + PASSAGE * (size - 3) + WALL elif i == size - 3: row = WALL + PASSAGE * (size - 3) + EXIT + WALL else: row = WALL + PASSAGE * (size - 2) + WALL maze.append(row) maze.append(WALL * size) with open(filename, 'w', encoding='utf-8') as f: f.write('\n'.join(maze)) print(f"Пустой лабиринт 10x10: {filename}") def main(): print("=" * 60) print("ГЕНЕРАЦИЯ ЛАБИРИНТОВ") print("=" * 60) generate_small_maze('small_maze.txt') generate_maze_prim(50, 'medium_maze.txt', 'Средний лабиринт 50x50') generate_maze_prim(100, 'large_maze.txt', 'Большой лабиринт 100x100') generate_no_exit_maze('no_exit_maze.txt') generate_empty_maze('empty_maze.txt') print("\n" + "=" * 60) print("ДЕМОНСТРАЦИЯ НА МАЛЕНЬКОМ ЛАБИРИНТЕ") print("=" * 60) builder = TextFileMazeBuilder() maze = builder.buildFromFile('small_maze.txt') print(f"Размер: {maze.width}x{maze.height}") print(f"Старт: ({maze.start.x}, {maze.start.y})") print(f"Выход: ({maze.exit.x}, {maze.exit.y})") view = ConsoleView() solver = MazeSolver(maze) solver.attach(view) strategies = { "BFS (поиск в ширину)": BFSStrategy(), "DFS (поиск в глубину)": DFSStrategy(), "A*": AStarStrategy() } for name, strat in strategies.items(): print(f"\n{'─' * 40}") print(f"Стратегия: {name}") solver.setStrategy(strat) path, stats = solver.solve() if path: print(f"Путь найден! Длина: {len(path)} шагов") print(f" Время: {stats.time_ms:.3f} мс | Посещено: {stats.visited_count}") view.render(maze, path=path) else: print("Путь не найден!") # Эксперименты print("\n" + "=" * 60) print("ЭКСПЕРИМЕНТЫ НА ВСЕХ ЛАБИРИНТАХ") print("=" * 60) test_mazes = {} maze_files = [ ("Маленький (10x10)", "small_maze.txt"), ("Средний (50x50)", "medium_maze.txt"), ("Большой (100x100)", "large_maze.txt"), ("Без выхода (10x10)", "no_exit_maze.txt"), ("Пустой (10x10)", "empty_maze.txt") ] for name, filename in maze_files: try: test_mazes[name] = builder.buildFromFile(filename) m = test_mazes[name] print(f"{name} загружен ({m.width}x{m.height})") except Exception as e: print(f"Ошибка {name}: {e}") if test_mazes: print(f"\nЗапуск тестов (по 3 прогона)...") results = run_experiments(test_mazes, strategies, runs=3) save_to_csv(results) print("ГОТОВО! Графики: python visualize_results.py") if __name__ == "__main__": main()