Making a maze....
Phil Schmidt
phil_nospam_schmidt at yahoo.com
Mon Nov 17 12:46:28 EST 2003
I couldn't resist...
--------------------------------------------------
import random as rand
rand.seed()
opposite = {'north':'south', 'south':'north', 'east':'west', 'west':'east'}
adjacentcell = {'north': lambda x,y: (x,y-1),
'south': lambda x,y: (x,y+1),
'east' : lambda x,y: (x+1,y),
'west' : lambda x,y: (x-1,y)}
class Cell:
def __init__(self, canvas, x, y, grid, state='virgin'):
self.canvas = canvas
self.location = (x, y)
x0 = 3 + x * grid.cellsize_x
x1 = x0 + grid.cellsize_x
y0 = 3 + y * grid.cellsize_y
y1 = y0 + grid.cellsize_y
self.coords = (x0, x1, y0, y1)
self.state = state
self.colors = {'virgin':'green',
'frontier':'brown',
'explored':'yellow'}
self.walls = {}
# display the cell
x0, x1, y0, y1 = self.coords
self.cell = self.canvas.create_rectangle(x0, y0, x1, y1,
fill=self.colors[self.state],
outline='')
self.canvas.lower(self.cell) # ensures the walls are all on top
# make the walls
self.walls['north'] = self.canvas.create_rectangle(x0-grid.borderwidth/2,
y0-grid.borderwidth/2,
x1+grid.borderwidth/2,
y0+grid.borderwidth/2,
fill='black')
self.walls['south'] = self.canvas.create_rectangle(x0-grid.borderwidth/2,
y1-grid.borderwidth/2,
x1+grid.borderwidth/2,
y1+grid.borderwidth/2,
fill='black')
self.walls['west'] = self.canvas.create_rectangle(x0-grid.borderwidth/2,
y0-grid.borderwidth/2,
x0+grid.borderwidth/2,
y1+grid.borderwidth/2,
fill='black')
self.walls['east'] = self.canvas.create_rectangle(x1-grid.borderwidth/2,
y0-grid.borderwidth/2,
x1+grid.borderwidth/2,
y1+grid.borderwidth/2,
fill='black')
def removeWall(self, wall):
self.canvas.delete(self.walls[wall])
del self.walls[wall]
def changeState(self, state):
self.canvas.itemconfigure(self.cell, fill=self.colors[state])
self.state = state
class Grid:
def __init__(self, canvas=None,
cellsize_x=10, cellsize_y=10,
gridsize_x=10, gridsize_y=10,
borderwidth=2):
self.cellsize_x = cellsize_x
self.cellsize_y = cellsize_y
self.gridsize_x = gridsize_x
self.gridsize_y = gridsize_y
self.borderwidth = borderwidth
if not canvas:
# create the canvas and display it
self.c = Canvas()
self.c.pack()
else:
self.c = canvas
self.c.configure(height = 3 + gridsize_y * cellsize_y + borderwidth,
width = 3 + gridsize_x * cellsize_x + borderwidth)
self.c.update()
# create cells
self.cells = []
for y in range(gridsize_y):
row = []
for x in range(gridsize_x):
row.append(Cell(self.c, x, y, self))
self.cells.append(row)
# start with an empty frontier
self.frontier = []
def openExploration(self):
# pick an initial cell to open the frontier
start = rand.choice(rand.choice(self.cells))
start.changeState('explored')
return start.location
def update(self):
self.c.update()
def isInArray(self, x, y):
return x >= 0 and x < self.gridsize_x \
and y >= 0 and y < self.gridsize_y
def isExplored(self, x, y):
if self.isInArray(x, y):
return self.cells[y][x].state is 'explored'
else:
return False
def isVirgin(self, x, y):
if self.isInArray(x, y):
return self.cells[y][x].state is 'virgin'
else:
return False
def markFrontier(self, x, y):
if self.isVirgin(x, y):
self.cells[y][x].changeState('frontier')
self.frontier.append(self.cells[y][x])
def extendFrontier(self, x, y):
self.markFrontier(x+1, y)
self.markFrontier(x-1, y)
self.markFrontier(x, y+1)
self.markFrontier(x, y-1)
def MazeBuilder(grid):
# pick an initial cell to open the frontier
x, y = grid.openExploration()
yield x, y
# this is the main iteration loop
while 1:
# mark all the frontier cells
grid.extendFrontier(x, y)
# pick a random frontier cell, and open a random wall to an explored cell
pick = rand.choice(grid.frontier)
x, y = pick.location
walls = ['north','south','east','west']
rand.shuffle(walls)
for wall in walls:
x1, y1 = adjacentcell[wall](x, y)
if grid.isExplored(x1, y1):
# open the wall in the target cell
pick.removeWall(wall)
# and then the wall in the adjacent cell
otherwall = opposite[wall]
grid.cells[y1][x1].removeWall(otherwall)
# mark the cell as explored
pick.changeState('explored')
# take the cell off the frontier list
grid.frontier.remove(pick)
break
if grid.frontier:
yield x,y
else:
return
for y in range(8):
for x in range(8):
c = Canvas()
c.grid(column=x, row=y)
# make a grid
grid = Grid(c,
cellsize_x=8, cellsize_y=8,
gridsize_x=10, gridsize_y=10)
# get the maze generator
explorer = MazeBuilder(grid)
while 1:
grid.update()
try:
explorer.next()
except StopIteration:
break
c.mainloop()
More information about the Python-list
mailing list