Python 贪吃蛇小游戏实现:
推箱子曾经在我们的童年给我们带来了很多乐趣。推箱子这款游戏现在基本上没人玩了,甚至在新一代人的印象中都已毫无记忆了。。。但是,这款游戏可以在一定程度上锻炼自己的编程能力。
运行效果如图所示:

游戏关卡有点难哦,码友们一起来挑战一下吧。
代码如下:
import pygame, sys, os
from pygame.locals import *
from collections import deque
def to_box(level, index):
if levelindex == '-' or levelindex == '@':
levelindex = '$'
else:
levelindex = '*'
def to_man(level, i):
if leveli == '-' or leveli == '$':
leveli = '@'
else:
leveli = '+'
def to_floor(level, i):
if leveli == '@' or leveli == '$':
leveli = '-'
else:
leveli = '.'
def to_offset(d, width):
d4 = -1, -width, 1, width
m4 = 'l', 'u', 'r', 'd'
return d4m4.index(d.lower())
def b_manto(level, width, b, m, t):
maze = list(level)
mazeb = '#'
if m == t:
return 1
queue = deque(\[\])
queue.append(m)
d4 = -1, -width, 1, width
m4 = 'l', 'u', 'r', 'd'
while len(queue) > 0:
pos = queue.popleft()
for i in range(4):
newpos = pos + d4i
if mazenewpos in '-', '.':
if newpos == t:
return 1
mazenewpos = i
queue.append(newpos)
return 0
def b_manto_2(level, width, b, m, t):
maze = list(level)
mazeb = '#'
mazem = '@'
if m == t:
return \[\]
queue = deque(\[\])
queue.append(m)
d4 = -1, -width, 1, width
m4 = 'l', 'u', 'r', 'd'
while len(queue) > 0:
pos = queue.popleft()
for i in range(4):
newpos = pos + d4i
if mazenewpos in '-', '.':
mazenewpos = i
queue.append(newpos)
if newpos == t:
path = \[\]
while mazet != '@':
path.append(m4maze\[t])
t = t - d4maze\[t]
return path
return \[\]
class Sokoban:
def init(self):
self.level = list(
'----#####--------------#---#--------------#--#------------###--##-----------#----#---------###-#-##-#---#######---#-##-#####--..##-------------..######-###-#@##--..#----#-----#########----#######--------')
self.w = 19
self.h = 11
self.man = 163
self.hint = list(self.level)
self.solution = \[\]
self.push = 0
self.todo = \[\]
self.auto = 0
self.sbox = 0
self.queue = \[\]
def draw(self, screen, skin):
w = skin.get_width() / 4
offset = (w - 4) / 2
for i in range(0, self.w):
for j in range(0, self.h):
if self.levelj \* self.w + i == '#':
screen.blit(skin, (i * w, j * w), (0, 2 * w, w, w))
elif self.levelj \* self.w + i == '-':
screen.blit(skin, (i * w, j * w), (0, 0, w, w))
elif self.levelj \* self.w + i == '@':
screen.blit(skin, (i * w, j * w), (w, 0, w, w))
elif self.levelj \* self.w + i == '$':
screen.blit(skin, (i * w, j * w), (2 * w, 0, w, w))
elif self.levelj \* self.w + i == '.':
screen.blit(skin, (i * w, j * w), (0, w, w, w))
elif self.levelj \* self.w + i == '+':
screen.blit(skin, (i * w, j * w), (w, w, w, w))
elif self.levelj \* self.w + i == '*':
screen.blit(skin, (i * w, j * w), (2 * w, w, w, w))
if self.sbox != 0 and self.hintj \* self.w + i == '1':
screen.blit(skin, (i * w + offset, j * w + offset), (3 * w, 3 * w, 4, 4))
def move(self, d):
self._move(d)
self.todo = \[\]
def _move(self, d):
self.sbox = 0
h = to_offset(d, self.w)
h2 = 2 * h
if self.levelself.man + h == '-' or self.levelself.man + h == '.':
# move
to_man(self.level, self.man + h)
to_floor(self.level, self.man)
self.man += h
self.solution += d
elif self.levelself.man + h == '*' or self.levelself.man + h == '$':
if self.levelself.man + h2 == '-' or self.levelself.man + h2 == '.':
# push
to_box(self.level, self.man + h2)
to_man(self.level, self.man + h)
to_floor(self.level, self.man)
self.man += h
self.solution += d.upper()
self.push += 1
def undo(self):
if self.solution.len() > 0:
self.todo.append(self.solution-1)
self.solution.pop()
h = to_offset(self.todo-1, self.w) * -1
if self.todo-1.islower():
# undo a move
to_man(self.level, self.man + h)
to_floor(self.level, self.man)
self.man += h
else:
# undo a push
to_floor(self.level, self.man - h)
to_box(self.level, self.man)
to_man(self.level, self.man + h)
self.man += h
self.push -= 1
def redo(self):
if self.todo.len() > 0:
self._move(self.todo-1.lower())
self.todo.pop()
def manto(self, x, y):
maze = list(self.level)
mazeself.man = '@'
queue = deque(\[\])
queue.append(self.man)
d4 = -1, -self.w, 1, self.w
m4 = 'l', 'u', 'r', 'd'
while len(queue) > 0:
pos = queue.popleft()
for i in range(4):
newpos = pos + d4i
if mazenewpos in '-', '.':
mazenewpos = i
queue.append(newpos)
# print str(maze)
t = y * self.w + x
if mazet in range(4):
self.todo = \[\]
while mazet != '@':
self.todo.append(m4maze\[t])
t = t - d4maze\[t]
# print self. todo
self.auto = 1
def automove(self):
if self.auto == 1 and self.todo.len() > 0:
self._move(self.todo-1.lower())
self.todo.pop()
else:
self.auto = 0
def boxhint(self, x, y):
d4 = -1, -self.w, 1, self.w
m4 = 'l', 'u', 'r', 'd'
b = y * self.w + x
maze = list(self.level)
to_floor(maze, b)
to_floor(maze, self.man)
mark = maze * 4
size = self.w * self.h
self.queue = \[\]
head = 0
for i in range(4):
if b_manto(maze, self.w, b, self.man, b + d4i):
if len(self.queue) == 0:
self.queue.append((b, i, -1))
marki \* size + b = '1'
# print self.queue
while head < len(self.queue):
pos = self.queuehead
head += 1
# print pos
for i in range(4):
if markpos\[0 + i * size] == '1' and mazepos\[0 - d4i] in '-', '.':
# print i
if markpos\[0 - d4i + i * size] != '1':
self.queue.append((pos0 - d4i, i, head - 1))
for j in range(4):
if b_manto(maze, self.w, pos0 - d4i, pos0, pos0 - d4i + d4j):
markj \* size + pos\[0 - d4i] = '1'
for i in range(size):
self.hinti = '0'
for j in range(4):
if markj \* size + i == '1':
self.hinti = '1'
# print self.hint
def boxto(self, x, y):
d4 = -1, -self.w, 1, self.w
m4 = 'l', 'u', 'r', 'd'
om4 = 'r', 'd', 'l', 'u'
b = y * self.w + x
maze = list(self.level)
to_floor(maze, self.sbox)
to_floor(maze, self.man) # make a copy of working maze by removing the selected box and the man
for i in range(len(self.queue)):
if self.queuei0 == b:
self.todo = \[\]
j = i
while self.queuej2 != -1:
self.todo.append(om4self.queue\[j1].upper())
k = self.queuej2
if self.queuek2 != -1:
self.todo += b_manto_2(maze, self.w, self.queuek0, self.queuek0 + d4self.queue\[k1],
self.queuek0 + d4self.queue\[j1])
else:
self.todo += b_manto_2(maze, self.w, self.queuek0, self.man,
self.queuek0 + d4self.queue\[j1])
j = k
# print self. todo
self.auto = 1
return
print('not found!')
def mouse(self, x, y):
if x >= self.w or y >= self.h:
return
m = y * self.w + x
if self.levelm in '-', '.':
if self.sbox == 0:
self.manto(x, y)
else:
self.boxto(x, y)
elif self.levelm in '$', '\*':
if self.sbox == m:
self.sbox = 0
else:
self.sbox = m
self.boxhint(x, y)
elif self.levelm in '-', '.', '@', '+':
self.boxto(x, y)
def main():
# start pygame
pygame.init()
screen = pygame.display.set_mode((400, 300))
# load skin
skinfilename = os.path.join('borgar.png')
try:
skin = pygame.image.load(skinfilename)
except pygame.error as msg:
print('cannot load skin')
raise SystemExit(msg)
skin = skin.convert()
# print skin.get_at((0,0))
# screen.fill((255,255,255))
screen.fill(skin.get_at((0, 0)))
pygame.display.set_caption('推箱子')
# create Sokoban object
skb = Sokoban()
skb.draw(screen, skin)
#
clock = pygame.time.Clock()
pygame.key.set_repeat(200, 50)
# main game loop
while True:
clock.tick(60)
if skb.auto == 0:
for event in pygame.event.get():
if event.type == QUIT:
# print skb.solution
pygame.quit()
sys.exit()
elif event.type == KEYDOWN:
if event.key == K_LEFT:
skb.move('l')
skb.draw(screen, skin)
elif event.key == K_UP:
skb.move('u')
skb.draw(screen, skin)
elif event.key == K_RIGHT:
skb.move('r')
skb.draw(screen, skin)
elif event.key == K_DOWN:
skb.move('d')
skb.draw(screen, skin)
elif event.key == K_BACKSPACE:
skb.undo()
skb.draw(screen, skin)
elif event.key == K_SPACE:
skb.redo()
skb.draw(screen, skin)
elif event.type == MOUSEBUTTONUP and event.button == 1:
mousex, mousey = event.pos
mousex /= (skin.get_width() / 4)
mousey /= (skin.get_width() / 4)
skb.mouse(mousex, mousey)
skb.draw(screen, skin)
else:
skb.automove()
skb.draw(screen, skin)
pygame.display.update()
pygame.display.set_caption(skb.solution.len().str() + '/' + skb.push.str() + ' - 推箱子')
if name == 'main':
main()
图片素材:

完整素材及全部代码
代码已上传csdn,0积分下载,觉得这片博文有用请留下你的点赞。