Enter Kruskal. Kruskal's algorithm is an algorithm used to find a minimum spanning tree for a graph. If this doesn't sound like a good way to build a maze, just hang on. I'm getting there. A lot of the time, the most difficult part of applying an algorithm to a problem is fitting it into some sort of data structure. A maze makes a perfect graph--every square is a node in the graph. Every square that is not separated by a wall is connected.
For more details on graph theory or Kruskal's algorithm, Wikipedia is your friend.
Back to the point: I love how simple the python implementation is.
width, height = 20, 20
# create a list of all walls
# (all connections between squares in the maze)
# add all of the vertical walls into the list
walls = [(x,y,x+1,y)
for x in range(width-1)
for y in range(height)]
# add all of the horizontal walls into the list
walls.extend([(x,y,x,y+1)
for x in range(width)
for y in range(height-1)])
# create a set for each square in the maze
cell_sets = [set([(x,y)])
for x in range(width)
for y in range(height)]
# in Kruskal's algorithm, the walls need to be
# visited in order of weight
# since we want a random maze, we will shuffle
# it and pretend that they are sorted by weight
walls_copy = walls[:]
random.shuffle(walls_copy)
for wall in walls_copy:
set_a = None
set_b = None
# find the sets that contain the squares
# that are connected by the wall
for s in cell_sets:
if (wall[0], wall[1]) in s:
set_a = s
if (wall[2], wall[3]) in s:
set_b = s
# if the two squares are in separate sets,
# then combine the sets and remove the
# wall that connected them
if set_a is not set_b:
cell_sets.remove(set_a)
cell_sets.remove(set_b)
cell_sets.append(set_a.union(set_b))
walls.remove(wall)
I'm sure there are things here that could be improved, but I really like the way Python works. If I were to implement this in C++, it might run faster (not that it needs to, the mazes are generated fast enough in Python) but it would take a lot longer to write and would end up with a lot more code.
No comments:
Post a Comment