Sokoban
Seo Sanghyeon
unendliche at hanmail.net
Mon Aug 12 09:16:03 EDT 2002
# Sokoban in Python
import Tkinter
WALL = 'black'
BOX = 'blue'
EMPTY = 'yellow'
FULL = 'green'
PLAYER = 'red'
size = 20
margin = 5
def loadmap(mapdata):
lines = filter(None, mapdata.split('\n'))
xs, ys = len(lines[0]), len(lines)
wall, depot, box, player = {}, {}, {}, {}
mapstruct = wall, depot, box, player
switch = {' ': (),
'#': (wall,),
'$': (box,),
'.': (depot,),
'*': (depot, box),
'@': (player,),
'+': (depot, player)}
def setter(dic):
dic[x, y] = 1
for y, line in zip(range(ys), lines):
for x, char in zip(range(xs), line):
map(setter, switch[char])
return xs, ys, mapstruct
def makecanvas(parent, xs, ys):
width, height = xs*size+margin*2, ys*size+margin*2
canvas = Tkinter.Canvas(
parent, width=width, height=height)
return canvas
def drawmap(canvas, mapstruct):
def square(x, y, fill):
return canvas.create_rectangle(
(x+0)*size+margin, (y+0)*size+margin,
(x+1)*size+margin, (y+1)*size+margin,
width=0, fill=fill)
def circle(x, y, fill):
return canvas.create_oval(
(x+0.2)*size+margin, (y+0.2)*size+margin,
(x+0.8)*size+margin, (y+0.8)*size+margin,
width=0, fill=fill)
switch = {'s': square,
'c': circle}
def setter(dic, kind, fill):
def set(pos):
x, y = pos
dic[x, y] = switch[kind](x, y, fill)
return set
idstruct = {}, {}, {}, {}
kinds = 'sscc'
colors = WALL, EMPTY, BOX, PLAYER
for dic, kind, fill, data in zip(
idstruct, kinds, colors, mapstruct):
map(setter(dic, kind, fill), data)
return idstruct
def filldepot(canvas, mapstruct, idstruct):
depot = mapstruct[1]
depotid = idstruct[1]
box = mapstruct[2]
for pos in depot:
if pos in box:
canvas.itemconfigure(depotid[pos], fill=FULL)
def makemover(canvas, mapstruct, idstruct):
def delta(event):
key = event.keysym
switch = {'Up': (0, -1),
'Left': (-1, 0),
'Down': (0, 1),
'Right': (1, 0)}
return switch[key]
def move(dic, idic, pos, dd):
x, y, dx, dy = pos + dd
canvas.move(idic[x, y], dx*size, dy*size)
idic[x+dx, y+dy] = idic[x, y]
del idic[x, y]
dic[x+dx, y+dy] = dic[x, y]
del dic[x, y]
def fill(idic, pos, fill):
canvas.itemconfigure(idic[pos], fill=fill)
def mover(event):
wall, depot, box, player = mapstruct
wallid, depotid, boxid, playerid = idstruct
pos = player.keys()[0]
dd = delta(event)
x, y, dx, dy = pos + dd
dpos, ddpos = (x+dx, y+dy), (x+dx+dx, y+dy+dy)
if dpos not in wall:
if dpos not in box:
move(player, playerid, pos, dd)
elif ddpos not in wall and ddpos not in box:
move(player, playerid, pos, dd)
move(box, boxid, dpos, dd)
if dpos in depot:
fill(depotid, dpos, EMPTY)
if ddpos in depot:
fill(depotid, ddpos, FULL)
return mover
def makegame(parent, mapdata):
xs, ys, mapstruct = loadmap(mapdata)
canvas = makecanvas(parent, xs, ys)
idstruct = drawmap(canvas, mapstruct)
filldepot(canvas, mapstruct, idstruct)
mover = makemover(canvas, mapstruct, idstruct)
parent.bind('<Key>', mover)
canvas.pack(padx=margin, pady=margin)
def main():
filename = raw_input('> ')
mapdata = file(filename).read()
root = Tkinter.Tk()
makegame(root, mapdata)
root.mainloop()
if __name__ == '__main__':
main()
More information about the Python-list
mailing list