Spaces:
Sleeping
Sleeping
import numpy as np | |
import random | |
from matplotlib import pyplot as plt | |
from astar import AStar | |
import pickle | |
import enum | |
class MazeSolver(AStar): | |
""" | |
Because I'm too lazy to implement A-star, this class yoinked | |
from https://github.com/jrialland/python-astar/blob/f11311b678522d90c1786e6b8d9393095a0b733f/tests/maze/test_maze.py#L58 | |
Sample use of the astar algorithm. In this exemple we work on a maze made of ascii characters, | |
and a 'node' is just a (x,y) tuple that represents a reachable position | |
""" | |
def __init__(self, maze): | |
self.world = maze | |
self.size = maze.shape[0] | |
def heuristic_cost_estimate(self, n1, n2): | |
"""computes the 'direct' distance between two (x,y) tuples""" | |
(x1, y1) = n1 | |
(x2, y2) = n2 | |
return np.hypot(x2 - x1, y2 - y1) | |
def distance_between(self, n1, n2): | |
"""this method always returns 1, as two 'neighbors' are always adajcent""" | |
return 1 | |
def neighbors(self, node): | |
""" for a given coordinate in the maze, returns up to 4 adjacent(north,east,south,west) | |
nodes that can be reached (=any adjacent coordinate that is not a wall) | |
""" | |
x, y = node | |
return[(nx, ny) for nx, ny in[(x, y - 1), (x, y + 1), (x - 1, y), (x + 1, y)] if 0 <= nx < self.size and 0 <= ny < self.size and self.world[ny,nx] == 1] | |
class StationaryGrid: | |
def __init__(self, seed, size=20): | |
np.random.seed(seed) | |
random.seed(seed) | |
self.size = size | |
self.grid = np.ones((size, size),dtype=np.uint8) | |
def create_grid(self): | |
n_obstacles = np.random.randint(1, 10) | |
i = 0 | |
while i < n_obstacles: | |
# for i in range(n_obstacles): | |
x = np.random.randint(0, self.grid.shape[0]) | |
y = np.random.randint(0, self.grid.shape[1]) | |
size = np.random.randint(2, high=self.size // 2, size=(2,)) | |
if x == 0 and y == 0: | |
continue | |
if (x + size[0]) >= self.grid.shape[0] and (y + size[1]) >= self.grid.shape[1]: | |
continue | |
start = (0, 0) | |
goal = (self.grid.shape[0] - 2, self.grid.shape[0] - 2) | |
self.grid[x:x + size[0], y:y + size[1]] = 0 | |
# make sure there's still a path to the goal | |
path = MazeSolver(self.grid).astar(start, goal) | |
if path is None: | |
# if not, undo the current obstacle and generate another random one | |
self.grid[x:x + size[0], y:y + size[1]] = 1 | |
continue | |
i += 1 | |
def plot(self, pth=None): | |
plt.imshow(self.grid, cmap='gray') | |
plt.plot(0, 0,marker='o', markersize=10, color="red") | |
plt.plot(self.grid.shape[0]-1, self.grid.shape[1]-1, marker='o', markersize=10, color="green") | |
if pth is not None: | |
plt.savefig(pth) | |
else: | |
plt.show() | |
if __name__ == '__main__': | |
for i in range(100): | |
grid = StationaryGrid(i, size=100) | |
grid.create_grid() | |
grid.plot(f'imgs/{i}.png') | |
print(i) | |