diff --git a/YanyaevAA/task2/docs/data/100x100.txt b/YanyaevAA/task2/docs/data/100x100.txt new file mode 100644 index 0000000..a030319 --- /dev/null +++ b/YanyaevAA/task2/docs/data/100x100.txt @@ -0,0 +1,101 @@ +#################################################################################################### +#S # # # # # # # # # +# ####### # ##### # ############# # ####### # ##### # ############# # ####### # ##### # ########## # +# # # # # # # # # # # # # # # # # # # # # # # # # # # # +# # ### # # # # # # # ######### # # # ### # # # # # # # ######### # # # ### # # # # # # # ###### # # +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +# # # ### # # # # # # # ##### # # # # # ### # # # # # # # ##### # # # # # ### # # # # # # # ## # # # +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +# # ####### # ############# ##### # # ####### # ############# ##### # # ####### # ############# # ## +# # # # # # # # # # # +# ################################# # ############################### # ########################## # +# # # # +# ################################# # ############################### # ########################## # +# # # # # # # +# # ############################### # # ############################# # # ######################## # +# # # # # # # # # # # +# # # ########################### # # # # ########################### # # # ###################### # +# # # # # # # # # # # # # # # # # +# # # # ####################### # # # # # # ####################### # # # # # ################## # # +# # # # # # # # # # # # # # # # # # # # # # # +# # # # # ################### # # # # # # # # ################### # # # # # # # ############## # # # +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # ############### # # # # # # # # # # ############### # # # # # # # # # ########## # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # ########### # # # # # # # # # # # # ########### # # # # # # # # # # # ###### # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # ####### # # # # # # # # # # # # # # ####### # # # # # # # # # # # # # ## # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # ### # # # # # # # # # # # # # # # ### # # # # # # # # # # # # # # ## # # # # # ## +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # ## +# # # # # # # # ### ##### # # # # # # # ### ##### ### ##### # # # # # # # ### ##### ### # # # # # ## +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # ## +# # # # # # # ### ######### # # # # # ### ######### ######### # # # # # ### ######### ### # # # # ## +# # # # # # # # # # # # # # # # # # # # # # # # # # ## +# # # # # # ### ############# # # # ### ############# ######### # # # ### ############# ### # # # ## +# # # # # # # # # # # # # # # # # # # # ## +# # # # # ### ############### # # ### ############### ######### # # ### ############### ### # # # ## +# # # # # # # # # # # # # # # # # ## +# # # # ### ################# # ### ################# ######### # ### ################# ### # # # ## +# # # # # # # # # # # # # # ## +# # # ### ##################### ### ################# ######### ### ##################### ### # # ## +# # # # # # # # # # # ## +# # ### ######################### # ################# ######### # # ######################### ### ## +# # # # # # # ## +# ### ############################# ################# ######### # ############################# #### +# # # # ## +### ################################################# ######### # ################################## +# # # # +# ################################################### ######### # ################################## +# # # # # # +# # ################################################# ######### # # ################################ +# # # # # # # # +# # # ############################################### ######### # # # ############################## +# # # # # # # # # # +# # # # ############################################# ######### # # # # ############################ +# # # # # # # # # # # # +# # # # # ########################################### ######### # # # # # ########################## +# # # # # # # # # # # # # # +# # # # # # ######################################### ######### # # # # # # ######################## +# # # # # # # # # # # # # # # # +# # # # # # # ####################################### ######### # # # # # # # ###################### +# # # # # # # # # # # # # # # # # # +# # # # # # # # ##################################### ######### # # # # # # # # #################### +# # # # # # # # # # # # # # # # # # # # +# # # # # # # # # ################################### ######### # # # # # # # # # ################## +# # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # ################################# ######### # # # # # # # # # # ################ +# # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # ############################### ######### # # # # # # # # # # # ############## +# # # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # ############################# ######### # # # # # # # # # # # # ############ +# # # # # # # # # # # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # ########################### ######### # # # # # # # # # # # # # ########## +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # ## +# # # # # # # # # # # # # # ######################### ######### # # # # # # # # # # # # # # ##### ## +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # ## +# # # # # # # # # # # # # # # ####################### ######### # # # # # # # # # # # # # # # # # ## +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # ## +# # # # # # # # # # # # # # # # ################### # # # # # # # # # # # # # # # # # # # ## +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # ## +# # # # # # # # # # # # # # # # # ############### # # # # # # # # # # # # # # # # # # # # ## +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # ## +# # # # # # # # # # # # # # # # # # ########### # # # # # # # # # # # # # # # # # # # # # ## +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # ## +# # # # # # # # # # # # # # # # # # # ####### # # # # # # # # # # # # # # # # # # # # # ## +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # ## +# # # # # # # # # # # # # # # # # # # # ### # # # # # # # # # # # # # # # # # # # # # ## +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # ## +# # # # # # # # # # # # # # # # # # # # ### # # # # # # # # # # # # # # # # # # # # ## +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # ## +# # # # # # # # # # # # # # # # # # # ### # # # # # # # # # # # # # # # # # # # ## +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # ## +# # # # # # # # # # # # # # # # # # ### # # # # # # # # # # # # # # # # # # ## +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # ## +# # # # # # # # # # # # # # # # # ### # # # # # # # # # # # # # # # # # ## +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # ## +# # # # # # # # # # # # # # # # ### # # # # # # # # # # # # # # # # # # +# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #### +# # # # # # # # # # # # # # # ### # # # # # # # # # # # # # # # # # +# E# +#################################################################################################### \ No newline at end of file diff --git a/YanyaevAA/task2/docs/data/10x10.txt b/YanyaevAA/task2/docs/data/10x10.txt new file mode 100644 index 0000000..3c17166 --- /dev/null +++ b/YanyaevAA/task2/docs/data/10x10.txt @@ -0,0 +1,10 @@ +########## +#S # +######## # +# # +# ######## +# # +######## # +# # +# E# +########## diff --git a/YanyaevAA/task2/docs/data/50x50.txt b/YanyaevAA/task2/docs/data/50x50.txt new file mode 100644 index 0000000..1e119cb --- /dev/null +++ b/YanyaevAA/task2/docs/data/50x50.txt @@ -0,0 +1,51 @@ +################################################## +#S# # # # # # +# # ### # ##### # ### ####### ### ### # ### ### # +# # # # # # # # # # # # # # # # # +##### # ### # # # # ### # # ####### # ####### ### +# # # # # # # # # # # # +### # ####### # # ####### # ### ### # # ### ### # +# # # # # # # # # # # # # +# ######### # ######### # ### ### ####### ### # # +# # # # # # # # # # # # # +# # ### # ### # ####### ### # # # # ### # ##### # +# # # # # # # # # # # # # +### # ### # ######### ### ########### # # # ### # +# # # # # # # # # # # # +# ##### # # # ##### ### # # ######### # ####### # +# # # # # # # # # # # # # # # # +# # # # # # # # # ### # # # # ##### # # # ##### # +# # # # # # # # # # # # # # # # # # # # # +# # # # # # # # ### # # ##### # # # # # # # # # # +# # # # # # # # # # # # # # +##### ####### ### ####### ########### ####### # # +# # # # # # # # # +# ####### ####### # ####### ##### # ### ####### # +# # # # # # # # # # # # +# # ####### ####### ##### # # # # ### # # ######## +# # # # # # # # # # # # # # # +# # # ####### ### ##### # # # # ### # # # # ### # +# # # # # # # # # # # # # # # # # +# # # # ####### ### # ####### ### # # # ##### # # +# # # # # # # # # # # # # # +# # # # # ####### ### # ####### ### # ######### # +# # # # # # # # # # # +####### # # ####### ### # ### ### # ########### # +# # # # # # # # # # # +# ####### # # ####### ### # # # ############### # +# # # # # # # # # +# # ####### ########### ####### # ############# # +# # # # # # # # # +# # # ####### ########### ####### # ######### # # +# # # # # # # # # # # # +# # # # ####### ########### ### # # # ##### # # # +# # # # # # # # # # # # # # +# # # # # ####### ########### # # # ####### # # # +# # # # # # # # # # +# ####### # ####### ############### # ######### # +# # # # # # # +# ######### # ####### ####################### # # +# # # # +############# ################################# # +# E# +################################################## \ No newline at end of file diff --git a/YanyaevAA/task2/docs/data/empty.txt b/YanyaevAA/task2/docs/data/empty.txt new file mode 100644 index 0000000..10bbaf0 --- /dev/null +++ b/YanyaevAA/task2/docs/data/empty.txt @@ -0,0 +1,20 @@ +#################### +#S # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# # +# E# +#################### \ No newline at end of file diff --git a/YanyaevAA/task2/docs/data/maze_results.csv b/YanyaevAA/task2/docs/data/maze_results.csv new file mode 100644 index 0000000..e3dad16 --- /dev/null +++ b/YanyaevAA/task2/docs/data/maze_results.csv @@ -0,0 +1,16 @@ +лабиринт,стратегия,время_мс,посещено_клеток,длина_пути +10x10.txt,BFS,0.02810000005410984,30.0,29.0 +10x10.txt,DFS,0.038610000046901405,43.0,29.0 +10x10.txt,AStar,0.03273000111221336,30.0,29.0 +50x50.txt,BFS,0.7084800003212877,799.0,316.0 +50x50.txt,DFS,0.48563999953330494,562.0,350.0 +50x50.txt,AStar,0.6310500000836328,539.0,316.0 +100x100.txt,BFS,3.024820000428008,3576.0,196.0 +100x100.txt,DFS,0.44655999954557046,595.0,364.0 +100x100.txt,AStar,0.5645899997034576,522.0,196.0 +empty.txt,BFS,0.2849799988325685,324.0,35.0 +empty.txt,DFS,0.1592799999343697,324.0,171.0 +empty.txt,AStar,0.4022000000986736,324.0,35.0 +without_exit.txt,BFS,0.041259999125031754,48.0,0.0 +without_exit.txt,DFS,0.040809998608892784,48.0,0.0 +without_exit.txt,AStar,0.052090000826865435,48.0,0.0 diff --git a/YanyaevAA/task2/docs/data/without_exit.txt b/YanyaevAA/task2/docs/data/without_exit.txt new file mode 100644 index 0000000..2c4c62a --- /dev/null +++ b/YanyaevAA/task2/docs/data/without_exit.txt @@ -0,0 +1,15 @@ +############### +#S # +# ########### # +# # # # +# # ####### # # +# # # # # # +# # # ### # # # +# # # #E# # # # +# # # ### # # # +# # # # # # +# # ####### # # +# # # # +# ########### # +# # +############### \ No newline at end of file diff --git a/YanyaevAA/task2/task_2.py b/YanyaevAA/task2/task_2.py index a7fcff9..27dd015 100644 --- a/YanyaevAA/task2/task_2.py +++ b/YanyaevAA/task2/task_2.py @@ -1,17 +1,20 @@ from abc import ABC, abstractmethod from collections import deque import heapq +import time +import os +import csv #Этап 1 class Cell: - def __init__(self, x, y, is_wall=False, is_start=False, is_exit=False): + def __init__(self, x, y, isWall=False, isStart=False, isExit=False): self.x = x self.y = y - self.is_wall = is_wall - self.is_start = is_start - self.is_exit = is_exit + self.isWall = isWall + self.isStart = isStart + self.isExit = isExit def isPassable(self): - return not self.is_wall + return not self.isWall class Maze: def __init__(self, cells, width, height, start, exit): @@ -59,15 +62,15 @@ class TextFileMazeBuilder(MazeBuilder): for x in range(width): char=lines[y][x] - is_wall = (char == '#') - is_start = (char == 'S') - is_exit = (char == 'E') + isWall = (char == '#') + isStart = (char == 'S') + isExit = (char == 'E') - cell=Cell(x, y, is_wall, is_start, is_exit) + cell=Cell(x, y, isWall, isStart, isExit) - if is_start: + if isStart: start_cell =cell - if is_exit: + if isExit: exit_cell =cell row.append(cell) grid.append(row) @@ -135,22 +138,30 @@ class AStar(PathFindingStrategy): if neighbor not in g_score or g_score_new < g_score[neighbor]: traveled_path[neighbor] = current g_score[neighbor] = g_score_new - f_score = tentative_g_score + abs(neighbor.x - exit.x) + abs(neighbor.y - exit.y) + f_score = g_score_new + abs(neighbor.x - exit.x) + abs(neighbor.y - exit.y) count += 1 heapq.heappush(open_set, (f_score, count, neighbor)) return [],len(traveled_path) #Этап 4 +class SearchStats: + def __init__(self, time, visited_cells, path_length): + self.time = time + self.visited_cells = visited_cells + self.path_length = path_length + class MazeSolver: def __init__(self, maze, strategy): self.maze = maze self.strategy = strategy - + self.observers = [] + def addObserver(self, observer): + self.observers.append(observer) def setStrategy(self, strategy): self.strategy = strategy def solve(self): - start_cell = self.maze.getStart() - exit_cell = self.maze.getExit() + start_cell = self.maze.start + exit_cell = self.maze.exit start_time = time.perf_counter() path, visited_cells = self.strategy.findPath(self.maze, start_cell, exit_cell) @@ -158,7 +169,98 @@ class MazeSolver: time_ms = (end_time - start_time) * 1000 path_length = len(path) + stats=SearchStats(time_ms, visited_cells, path_length) + event = Event("path_found", data=stats) + for observer in self.observers: + observer.update(event) - return time_ms, visited_cells, path_length + return stats -#Этап 5 \ No newline at end of file +#Этап 5 +#5.1 +class Event: + def __init__(self, event_type, data=None): + self.event_type = event_type + self.data = data + +class Observer(ABC): + @abstractmethod + def update(self, event): + pass + +class ConsoleView(Observer): + def update(self, event): + if event.event_type == "path_found": + stats=event.data + print("Путь найден:") + print("Время выполнения:", stats.time) + print("Количество посещённых клеток:", stats.visited_cells) + print("Длина найденного пути:", stats.path_length) + if event.event_type == "move": + x, y = event.data + print(f"Игрок переместился в ячейку: {x}, {y}") + if event.event_type == "maze_loaded": + print("Загружен новый лабиринт") + + def render(self, maze, path): + for y in range(maze.height): + row_str="" + for x in range(maze.width): + cell=maze.getCell(x, y) + if cell == maze.start: + row_str += "S" + elif cell == maze.exit: + row_str += "E" + elif cell in path: + row_str += "·" + elif cell.isWall: + row_str += "#" + else: + row_str += " " + print(row_str) + +#Этап 6 +mazes = ["10x10.txt","50x50.txt","100x100.txt","empty.txt","without_exit.txt"] + +results =[["лабиринт", + "стратегия", + "время_мс", + "посещено_клеток", + "длина_пути"]] +strategies = { + "BFS": BFS(), + "DFS": DFS(), + "AStar": AStar() +} +builder = TextFileMazeBuilder() +n=10 +directory = os.path.join("docs", "data") +for maze_name in mazes: + print(maze_name) + file_name=os.path.join(directory, maze_name) + maze = builder.buildFromFile(file_name) + viewer=ConsoleView() + for strategy_name, strategy in strategies.items(): + total_time = 0.0 + total_visited = 0 + total_path_length = 0 + + solver = MazeSolver(maze, strategy) + + for _ in range(n): + stats = solver.solve() + total_time += stats.time + total_visited += stats.visited_cells + total_path_length += stats.path_length + avg_time = total_time/n + avg_visited = total_visited/n + avg_path_length = total_path_length/n + print(f"{maze_name} стратегия: {strategy_name} время_мс: {avg_time} посещено_клеток: {avg_visited} длина_пути: {avg_path_length}") + results.append([maze_name, strategy_name, avg_time, avg_visited, avg_path_length]) + path, _ = strategy.findPath(maze, maze.start, maze.exit) + path=path[1:-1] + viewer.render(maze, path) +csv_filename = os.path.join(directory, "maze_results.csv") +with open(csv_filename, "w", newline="", encoding="utf-8-sig") as f: + writer = csv.writer(f) + writer.writerows(results) \ No newline at end of file