def solve(self, start, end, algorithm): """Solves a maze from start to finish.""" if self.maze is None: raise utils.MazeError( "Maze is not assigned.\n" "Use the \"create\" or \"load_maze\" method to create or load a maze." ) start = start if start else (0, 0) end = end if end else (self.row_count - 1, self.col_count - 1) if not (0 <= start[0] < self.row_count and 0 <= start[1] < self.col_count): raise utils.MazeError("Start point <{}> is out of range.".format(start)) if not (0 <= end[0] < self.row_count and 0 <= end[1] < self.col_count): raise utils.MazeError("End point <{}> is out of range.".format(end)) start = tuple([2 * x + 1 for x in start]) end = tuple([2 * x + 1 for x in end]) self.solution = self.maze.copy() if algorithm == Maze.Solve.C: return self._depth_first_search_c(start, end) if algorithm == Maze.Solve.DEPTH: return self._depth_first_search(start, end) if algorithm == Maze.Solve.BREADTH: return self._breadth_first_search(start, end) raise utils.MazeError( "Wrong algorithm <{}>.\n" "Use \"Algorithm.Solve.<algorithm>\" to choose an algorithm.".format(algorithm) )
def create(self, row_count, col_count, algorithm): """Creates a maze for a given row and column count.""" if (row_count or col_count) <= 0: raise utils.MazeError( "Row or column count cannot be smaller than zero.") self.maze = np.ones((row_count, col_count), dtype=np.uint8) * -1 if algorithm == Maze.Create.BACKTRACKING or algorithm == 0: return self._recursive_backtracking() # if algorithm == Maze.Create.HUNT: # return self._hunt_and_kill() if algorithm == Maze.Create.ELLER or algorithm == 1: return self._eller() if algorithm == Maze.Create.SIDEWINDER or algorithm == 2: return self._sidewinder() if algorithm == Maze.Create.PRIM or algorithm == 3: return self._prim() if algorithm == Maze.Create.KRUSKAL or algorithm == 4: return self._kruskal() if algorithm == Maze.Create.RANDOM or algorithm == 5: return self._randomGenerate() raise utils.MazeError( "Wrong algorithm <{}>.\n" "Use \"Maze.Create.<algorithm>\" to choose an algorithm.".format( algorithm))
def create(self, col_count,row_count, algorithm): """Creates a maze for a given row and column count.""" if (row_count or col_count) <= 0: raise utils.MazeError("Row or column count cannot be smaller than zero.") self.maze = np.zeros((2 * row_count + 1, 2 * col_count + 1, 3), dtype=np.uint8) if algorithm == Maze.Create.C: return self._recursive_backtracking_c() if algorithm == Maze.Create.BACKTRACKING: return self._recursive_backtracking() if algorithm == Maze.Create.HUNT: return self._hunt_and_kill() if algorithm == Maze.Create.ELLER: return self._eller() if algorithm == Maze.Create.SIDEWINDER: return self._sidewinder() if algorithm == Maze.Create.PRIM: return self._prim() if algorithm == Maze.Create.KRUSKAL: return self._kruskal() raise utils.MazeError( "Wrong algorithm <{}>.\n" "Use \"Maze.Create.<algorithm>\" to choose an algorithm.".format(algorithm) )
def load_maze(self, file_name="maze.png"): """Loads the maze from png.""" if not os.path.isfile(file_name): raise util.MazeError( "Cannot load maze because <{}> does not exist.".format( file_name)) self.maze = util.downscale(np.array(Image.open(file_name)))
def save_solution(self, file_name="solution.png", scale=3): """Saves the solution as png.""" if self.solution is None: raise util.MazeError( "Cannot save solution because it is not assigned.\n" "Use the \"solve\" method to solve a maze." ) Image.fromarray(util.upscale(self.solution, scale), "RGB").save(file_name, "png")
def save_maze(self, file_name="maze.png", scale=3): """Saves the maze as png.""" if self.maze is None: raise util.MazeError( "Cannot save maze because it is not assigned.\n" "Use the \"create\" or \"load_maze\" method to create or load a maze." ) Image.fromarray(util.upscale(self.maze, scale), "RGB").save(file_name, "png")
def save_maze(self, file_name="maze.png", line=5, path=15): """Saves the maze as png.""" if self.maze is None: raise util.MazeError( "Cannot save maze because it is not assigned.\n" "Use the \"create\" or \"load_maze\" method to create or load a maze." ) img = Image.fromarray(util.upscale(self.maze, line, path), "RGB") img.save("uncropped.png") print(img) img = PIL.ImageOps.invert(img).convert("L") newImage = Image.new("L", (1085, 720)) newImage.paste(img, (0, 7, 1085, 7 + 705)) newImage.save(file_name, "png") return newImage
def _depth_first_search(self, start, end): """Solves a maze using depth-first search.""" visited = self.maze.copy() # List of visited cells, value of visited cell is 0 stack = collections.deque() # List of visited cells [(x, y), ...] x, y = start visited[x, y, 0] = 0 # Mark as visited while x and y: while x and y: stack.append((x, y)) if (x, y) == end: # Stop if end has been found return utils.draw_path(self.solution, stack) x, y = self._solve_walk(x, y, visited) x, y = self._solve_backtrack(stack, visited) raise utils.MazeError("No solution found.")
def _breadth_first_search(self, start, end): """Solves a maze using breadth-first search.""" visited = self.maze.copy() # List of visited cells, value of visited cell is 0 queue = collections.deque() # List of cells [cell, ...] cell = utils.stack_empty() # Tuple of current cell with according stack ((x, y), stack) x, y = start cell = utils.stack_push(cell, (x, y)) queue.append(cell) visited[x, y, 0] = 0 # Mark as visited while queue: self._enqueue(queue, visited) if queue[0][0] == end: # Stop if end has been found cell = utils.stack_push(queue[0], end) # Push end into cell return utils.draw_path(self.solution, utils.stack_deque(cell)) raise utils.MazeError("No solution found.")