Added Wilson's Alg
This commit is contained in:
parent
9dc41e9ba8
commit
f051ab58e3
5
main.py
5
main.py
|
@ -61,7 +61,7 @@ class MazeVisualizer:
|
|||
if event.key == pygame.K_m:
|
||||
for _ in range(10000):
|
||||
if not self.maze.step(): break
|
||||
if event.key == pygame.K_o:
|
||||
if event.key == pygame.K_v:
|
||||
self.maze = maze.VectorWrapper.convert(self.maze)
|
||||
|
||||
# Only step through the algorithm if it's not finished
|
||||
|
@ -95,7 +95,8 @@ VEC_MAZE_SIZE = (MAZE_SIZE + 1) // 2
|
|||
# my_maze = maze.RecursiveDivision(MAZE_SIZE, uniform=False)
|
||||
# my_maze = maze.RecursiveDivision(MAZE_SIZE, depth_first=False)
|
||||
# my_maze = maze.RecursiveDivision(MAZE_SIZE, binary=True)
|
||||
my_maze = maze.VectorWrapper(maze.Prim(VEC_MAZE_SIZE))
|
||||
# my_maze = maze.VectorWrapper(maze.Prim(VEC_MAZE_SIZE))
|
||||
my_maze = maze.VectorWrapper(maze.Wilson(VEC_MAZE_SIZE))
|
||||
|
||||
# for _ in range(512): my_maze.step()
|
||||
# for _ in range(2048): my_maze.step()
|
||||
|
|
98
maze.py
98
maze.py
|
@ -159,10 +159,13 @@ class VectorWrapper(Maze):
|
|||
return ((i - 1) // 2)
|
||||
|
||||
@classmethod
|
||||
def convert(cls, maze: Maze) -> "VectorWrapper":
|
||||
def convert(cls, maze: Maze, origin: tuple[int,int] | None = None) -> "VectorWrapper":
|
||||
width, height = cls.__to_vec(maze.width), cls.__to_vec(maze.height)
|
||||
|
||||
stack = [(random.randint(0,width-1),random.randint(0,height-1))]
|
||||
if origin is None:
|
||||
stack = [(random.randint(0,width-1),random.randint(0,height-1))]
|
||||
else:
|
||||
stack = [origin]
|
||||
|
||||
cells = [list([VectorEnum.Null for _ in range(width)]) for _ in range(height)]
|
||||
|
||||
|
@ -747,3 +750,94 @@ class Prim(VectorMaze):
|
|||
neighbors.append((x,y + 1))
|
||||
|
||||
return neighbors
|
||||
|
||||
|
||||
class Wilson(VectorMaze):
|
||||
|
||||
__cells: list[list[VectorEnum]]
|
||||
|
||||
__width: int
|
||||
__height: int
|
||||
|
||||
__path: dict[tuple[int,int], VectorEnum]
|
||||
__start: tuple[int,int] | None
|
||||
|
||||
def __init__(self, width: int, height: int | None = None, *, bias: int | None = None ):
|
||||
self.__width = width
|
||||
self.__height = height or width
|
||||
|
||||
self.__cells = [list([VectorEnum.Null for _ in range(self.width)]) for _ in range(self.height)]
|
||||
|
||||
x, y = random.randint(0,self.width-1), random.randint(0,self.height-1)
|
||||
self.__cells[y][x] = VectorEnum.Zero
|
||||
|
||||
self.__start = self.__new_start()
|
||||
if self.__start is not None:
|
||||
self.__path = {self.__start: VectorEnum.Zero}
|
||||
else:
|
||||
self.__path = {}
|
||||
|
||||
@property
|
||||
def width(self) -> int:
|
||||
return self.__width
|
||||
|
||||
@property
|
||||
def height(self) -> int:
|
||||
return self.__height
|
||||
|
||||
@property
|
||||
def highlighted(self) -> tuple[int,int] | None:
|
||||
if self.__start is not None:
|
||||
for key, value in self.__path.items():
|
||||
if value == VectorEnum.Zero:
|
||||
return key
|
||||
return None
|
||||
|
||||
def __getitem__(self, index: tuple[int,int]) -> VectorEnum:
|
||||
x, y = index
|
||||
return self.__cells[y][x]
|
||||
|
||||
def step(self) -> bool:
|
||||
if self.highlighted:
|
||||
highlighted = self.highlighted
|
||||
neighbors = self._neighbors(highlighted)
|
||||
cell = neighbors[random.randint(0, len(neighbors)-1)]
|
||||
self.__path[highlighted] = self.__direction(highlighted, cell)
|
||||
if self.__cells[cell[1]][cell[0]] == VectorEnum.Null:
|
||||
self.__path[cell] = VectorEnum.Zero
|
||||
else:
|
||||
# if self.highlighted is not None, self.__start is not None
|
||||
cell: tuple[int,int] = self.__start # type: ignore
|
||||
while self.__path.get(cell, VectorEnum.Zero) != VectorEnum.Zero:
|
||||
self.__cells[cell[1]][cell[0]] = self.__path[cell]
|
||||
cell = self.__next(cell, self.__path[cell])
|
||||
self.__start = self.__new_start()
|
||||
if self.__start is not None:
|
||||
self.__path = {self.__start: VectorEnum.Zero}
|
||||
else:
|
||||
self.__path = {}
|
||||
return True
|
||||
else: return False
|
||||
|
||||
def __new_start(self) -> tuple[int, int] | None:
|
||||
empty = []
|
||||
for x in range(self.width):
|
||||
for y in range(self.height):
|
||||
if self.__cells[y][x] == VectorEnum.Null:
|
||||
empty.append((x,y))
|
||||
if empty: return empty[random.randint(0,len(empty)-1)]
|
||||
else: return None
|
||||
|
||||
def __direction(self, start: tuple[int,int], end: tuple[int,int]) -> VectorEnum:
|
||||
if start[0] > end[0]: return VectorEnum.Left
|
||||
if start[0] < end[0]: return VectorEnum.Right
|
||||
if start[1] > end[1]: return VectorEnum.Up
|
||||
if start[1] < end[1]: return VectorEnum.Down
|
||||
return VectorEnum.Zero
|
||||
|
||||
def __next(self, index: tuple[int,int], direction: VectorEnum) -> tuple[int,int]:
|
||||
if direction == VectorEnum.Up: return index[0], index[1]-1
|
||||
elif direction == VectorEnum.Down: return index[0], index[1]+1
|
||||
elif direction == VectorEnum.Left: return index[0]-1, index[1]
|
||||
elif direction == VectorEnum.Right: return index[0]+1, index[1]
|
||||
else: return index[0], index[1]
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
+ Recursive Division
|
||||
+ Binary Division
|
||||
+ Prim's Algorithm
|
||||
+ Wilson's Algorithm
|
||||
- Aldous-Broder Algorithm
|
||||
- Wilson's Algorithm
|
||||
- Aldous-Broder-Wilson Algorithm
|
||||
- Kruskal's Algorithm
|
||||
- Eller's Algorithm
|
||||
|
|
Loading…
Reference in New Issue