import heapq import time import codecs import csv class Cell: def __init__(self,x,y,isWall,isStart,isExit): self.x=x self.y=y self.isWall=isWall self.isStart=isStart self.isExit=isExit def isPassable(self): if self.isWall==False: return True else: return False class Maze: def __init__(self,grid): self.grid=grid self.width=len(self.grid[0]) self.height=len(self.grid) self.start=None self.exit=None for i in range(self.height): for j in range(self.width): if self.grid[i][j].isStart==True: self.start=(j,i) if self.grid[i][j].isExit==True: self.exit=(j,i) def getCell(self,x,y): return self.grid[y][x] def getNeighbours(self,cell): x=cell.x y=cell.y cell_up=None cell_down=None cell_left=None cell_right=None #up if y>0: if self.grid[y-1][x].isPassable()==True: cell_up=self.grid[y-1][x] #down if y<(self.height-1): if self.grid[y+1][x].isPassable()==True: cell_down=self.grid[y+1][x] #left if x>0: if self.grid[y][x-1].isPassable()==True: cell_left=self.grid[y][x-1] #right if x<(self.width-1): if self.grid[y][x+1].isPassable()==True: cell_right=self.grid[y][x+1] #neighbours=[cell_up, cell_down, cell_left, cell_right] neighbours=[cell_down, cell_right, cell_up, cell_left] return neighbours class TextFileMazeBuilder: def build(self,filename): with open(filename,"r") as f: lines=f.readlines() grid=[] x=0 y=0 for i in range(len(lines)): line=lines[i] x=0 row=[] for j in range(len(line)): if line[j]=="#": row.append(Cell(x,y,True,False,False)) elif line[j]==" ": row.append(Cell(x,y,False,False,False)) elif line[j]=="S": row.append(Cell(x,y,False,True,False)) elif line[j]=="E": row.append(Cell(x,y,False,False,True)) x+=1 grid.append(row) y+=1 return grid class MazeBuilder: def buildFromFile(self,filename): grid = TextFileMazeBuilder().build(filename) return Maze(grid) class SearchStats: def __init__(self,ttime,visited_cells,path_length): self.ttime=ttime self.visited_cells=visited_cells self.path_length=path_length class BFSStrategy: def findPath(self,maze,start,exxit): tstart=time.perf_counter() queue=[] queue.append((maze.getCell(start[0],start[1]),0)) visited_cells=[maze.getCell(start[0],start[1])] Path={} f=0 count=0 while len(queue)!=0: temp=queue.pop(0) cell=temp[0] steps=temp[1] directions=maze.getNeighbours(cell) count+=1 if (cell.x,cell.y)==exxit: end=time.perf_counter() #print(end-tstart) f=1 break for i in directions: if i!=None: flag=0 for j in visited_cells: if i==j: flag=1 break if flag==0: queue.append((i,steps+1)) visited_cells.append(i) Path[(i.x,i.y)]=(cell.x,cell.y) reversePath=[] if f==1: cell=exxit while cell!=start: reversePath.append(cell) cell=Path[cell] reversePath.append(cell) reversePath.reverse() #print(len(reversePath)-1) return reversePath, count class DFSStrategy: def findPath(self,maze,start,exxit): tstart=time.perf_counter() queue=[] queue.append((maze.getCell(start[0],start[1]),0)) visited_cells=[maze.getCell(start[0],start[1])] Path={} f=0 count=0 while len(queue)!=0: temp=queue.pop() cell=temp[0] steps=temp[1] directions=maze.getNeighbours(cell) count+=1 if (cell.x,cell.y)==exxit: end=time.perf_counter() #print(end-tstart) f=1 break for i in directions: if i!=None: flag=0 for j in visited_cells: if i==j: flag=1 break if flag==0: queue.append((i,steps+1)) visited_cells.append(i) Path[(i.x,i.y)]=(cell.x,cell.y) reversePath=[] if f==1: cell=exxit while cell!=start: reversePath.append(cell) cell=Path[cell] reversePath.append(cell) reversePath.reverse() #print(len(reversePath)-1) return reversePath, count class AStarStrategy: def H(self,exxit,cell): Hn=0 if exxit!=None: Hn=abs(exxit[0]-cell.x)+abs(exxit[1]-cell.y) return Hn def findPath(self,maze,start,exxit): tstart=time.perf_counter() queue=[] f=self.H(exxit,maze.getCell(start[0],start[1])) heapq.heappush(queue, (f, f, (start[0],start[1]))) f_scores=[] for i in range(maze.height): row=[] for j in range(maze.width): row.append(None) f_scores.append(row) g_scores=[] for i in range(maze.height): row=[] for j in range(maze.width): row.append(None) g_scores.append(row) f_scores[start[1]][start[0]]=f g_scores[start[1]][start[0]]=0 Path={} flag=0 count=0 while len(queue)!=0: temp=heapq.heappop(queue) cell=temp[2] directions=maze.getNeighbours(maze.getCell(cell[0], cell[1])) count+=1 if (cell[0],cell[1])==exxit: end=time.perf_counter() #print(end-tstart) flag=1 break for i in directions: if i!=None: temp_g=g_scores[cell[1]][cell[0]]+1 temp_f=temp_g+self.H(exxit,i) if f_scores[i.y][i.x]==None: g_scores[i.y][i.x]=temp_g f_scores[i.y][i.x]=temp_f heapq.heappush(queue,(temp_f,self.H(exxit,i),(i.x,i.y))) Path[(i.x,i.y)]=cell elif temp_f0: path_length=len(path)-1 else: path_length=0 return SearchStats(end-start, visited, path_length) def test(): #maze=MazeBuilder().buildFromFile("1.txt") #maze=MazeBuilder().buildFromFile("2.txt") maze=MazeBuilder().buildFromFile("v.txt") #maze=MazeBuilder().buildFromFile("maze_10x10.txt") #maze=MazeBuilder().buildFromFile("maze_50x50.txt") #maze=MazeBuilder().buildFromFile("maze_100x100.txt") #maze=MazeBuilder().buildFromFile("maze_no_walls.txt") #maze=MazeBuilder().buildFromFile("maze_no_exit.txt") print(maze.exit) print(maze.start) stats=MazeSolver(maze, "BFS").solve() print(stats.ttime,stats.visited_cells,stats.path_length) stats=MazeSolver(maze, "DFS").solve() print(stats.ttime,stats.visited_cells,stats.path_length) stats=MazeSolver(maze, "AStar").solve() print(stats.ttime,stats.visited_cells,stats.path_length) #print(PathFindingStrategy("BFS").findPath(maze,maze.start,maze.exit)) #print(PathFindingStrategy("DFS").findPath(maze,maze.start,maze.exit)) #print(PathFindingStrategy("AStar").findPath(maze,maze.start,maze.exit)) #PathFindingStrategy("BFS").findPath(maze,maze.start,maze.exit) #PathFindingStrategy("DFS").findPath(maze,maze.start,maze.exit) #PathFindingStrategy("AStar").findPath(maze,maze.start,maze.exit) def run(): maze=MazeBuilder().buildFromFile("maze_10x10.txt") results = [ [u"Лабиринт", u"Стратегия", u"Среднее время (мс)", u"Посещено клеток",u"Длина пути"] ] temp=0 for i in range(10): stats=MazeSolver(maze, "BFS").solve() temp+=stats.ttime temp=temp/10 temp=temp*(10**3) results.append(["10x10", "BFS", temp, stats.visited_cells, stats.path_length]) temp=0 for i in range(10): stats=MazeSolver(maze, "DFS").solve() temp+=stats.ttime temp=temp/10 temp=temp*(10**3) results.append(["10x10", "DFS", temp, stats.visited_cells, stats.path_length]) temp=0 for i in range(10): stats=MazeSolver(maze, "AStar").solve() temp+=stats.ttime temp=temp/10 temp=temp*(10**3) results.append(["10x10", "AStar", temp, stats.visited_cells, stats.path_length]) with codecs.open("docs/data/[2]results.csv", "w", "utf-16") as f: writer = csv.writer(f) writer.writerows(results) writer.writerow("") maze=MazeBuilder().buildFromFile("maze_50x50.txt") results = [] temp=0 for i in range(10): stats=MazeSolver(maze, "BFS").solve() temp+=stats.ttime temp=temp/10 temp=temp*(10**3) results.append(["50x50", "BFS", temp, stats.visited_cells, stats.path_length]) temp=0 for i in range(10): stats=MazeSolver(maze, "DFS").solve() temp+=stats.ttime temp=temp/10 temp=temp*(10**3) results.append(["50x50", "DFS", temp, stats.visited_cells, stats.path_length]) temp=0 for i in range(10): stats=MazeSolver(maze, "AStar").solve() temp+=stats.ttime temp=temp/10 temp=temp*(10**3) results.append(["50x50", "AStar", temp, stats.visited_cells, stats.path_length]) with codecs.open("docs/data/[2]results.csv", "a+", "utf-16") as f: writer = csv.writer(f) writer.writerows(results) writer.writerow("") maze=MazeBuilder().buildFromFile("maze_100x100.txt") results = [] temp=0 for i in range(10): stats=MazeSolver(maze, "BFS").solve() temp+=stats.ttime temp=temp/10 temp=temp*(10**3) results.append(["100x100", "BFS", temp, stats.visited_cells, stats.path_length]) temp=0 for i in range(10): stats=MazeSolver(maze, "DFS").solve() temp+=stats.ttime temp=temp/10 temp=temp*(10**3) results.append(["100x100", "DFS", temp, stats.visited_cells, stats.path_length]) temp=0 for i in range(10): stats=MazeSolver(maze, "AStar").solve() temp+=stats.ttime temp=temp/10 temp=temp*(10**3) results.append(["100x100", "AStar", temp, stats.visited_cells, stats.path_length]) with codecs.open("docs/data/[2]results.csv", "a+", "utf-16") as f: writer = csv.writer(f) writer.writerows(results) writer.writerow("") maze=MazeBuilder().buildFromFile("maze_no_walls.txt") results = [] temp=0 for i in range(10): stats=MazeSolver(maze, "BFS").solve() temp+=stats.ttime temp=temp/10 temp=temp*(10**3) results.append([u"Без стен", "BFS", temp, stats.visited_cells, stats.path_length]) temp=0 for i in range(10): stats=MazeSolver(maze, "DFS").solve() temp+=stats.ttime temp=temp/10 temp=temp*(10**3) results.append([u"Без стен", "DFS", temp, stats.visited_cells, stats.path_length]) temp=0 for i in range(10): stats=MazeSolver(maze, "AStar").solve() temp+=stats.ttime temp=temp/10 temp=temp*(10**3) results.append([u"Без стен", "AStar", temp, stats.visited_cells, stats.path_length]) with codecs.open("docs/data/[2]results.csv", "a+", "utf-16") as f: writer = csv.writer(f) writer.writerows(results) writer.writerow("") maze=MazeBuilder().buildFromFile("maze_no_exit.txt") results = [] temp=0 for i in range(10): stats=MazeSolver(maze, "BFS").solve() temp+=stats.ttime temp=temp/10 temp=temp*(10**3) results.append([u"Без выхода", "BFS", temp, stats.visited_cells, stats.path_length]) temp=0 for i in range(10): stats=MazeSolver(maze, "DFS").solve() temp+=stats.ttime temp=temp/10 temp=temp*(10**3) results.append([u"Без выхода", "DFS", temp, stats.visited_cells, stats.path_length]) temp=0 for i in range(10): stats=MazeSolver(maze, "AStar").solve() temp+=stats.ttime temp=temp/10 temp=temp*(10**3) results.append([u"Без выхода", "AStar", temp, stats.visited_cells, stats.path_length]) with codecs.open("docs/data/[2]results.csv", "a+", "utf-16") as f: writer = csv.writer(f) writer.writerows(results) writer.writerow("") run()