python吃豆人小游戏代码(完整代码+逐步解释)
吃豆人是经典的街机游戏。在本程序中,你需要使用箭头键导航和吃所有的白色食物,并且小心在迷宫里游荡的红色幽灵。
程序代码
代码来源:grantjenks在github上面的开源项目。
同样尝试:python贪吃蛇代码示例(实测可运行)
"""Pacman, classic arcade game. Exercises 1. Change the board. 2. Change the number of ghosts. 3. Change where pacman starts. 4. Make the ghosts faster/slower. 5. Make the ghosts smarter. """ from random import choice from turtle import * from freegames import floor, vector state = {'score': 0} path = Turtle(visible=False) writer = Turtle(visible=False) aim = vector(5, 0) pacman = vector(-40, -80) ghosts = [ [vector(-180, 160), vector(5, 0)], [vector(-180, -160), vector(0, 5)], [vector(100, 160), vector(0, -5)], [vector(100, -160), vector(-5, 0)], ] # fmt: off tiles = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ] # fmt: on def square(x, y): """Draw square using path at (x, y).""" path.up() path.goto(x, y) path.down() path.begin_fill() for count in range(4): path.forward(20) path.left(90) path.end_fill() def offset(point): """Return offset of point in tiles.""" x = (floor(point.x, 20) + 200) / 20 y = (180 - floor(point.y, 20)) / 20 index = int(x + y * 20) return index def valid(point): """Return True if point is valid in tiles.""" index = offset(point) if tiles[index] == 0: return False index = offset(point + 19) if tiles[index] == 0: return False return point.x % 20 == 0 or point.y % 20 == 0 def world(): """Draw world using path.""" bgcolor('black') path.color('blue') for index in range(len(tiles)): tile = tiles[index] if tile > 0: x = (index % 20) * 20 - 200 y = 180 - (index // 20) * 20 square(x, y) if tile == 1: path.up() path.goto(x + 10, y + 10) path.dot(2, 'white') def move(): """Move pacman and all ghosts.""" writer.undo() writer.write(state['score']) clear() if valid(pacman + aim): pacman.move(aim) index = offset(pacman) if tiles[index] == 1: tiles[index] = 2 state['score'] += 1 x = (index % 20) * 20 - 200 y = 180 - (index // 20) * 20 square(x, y) up() goto(pacman.x + 10, pacman.y + 10) dot(20, 'yellow') for point, course in ghosts: if valid(point + course): point.move(course) else: options = [ vector(5, 0), vector(-5, 0), vector(0, 5), vector(0, -5), ] plan = choice(options) course.x = plan.x course.y = plan.y up() goto(point.x + 10, point.y + 10) dot(20, 'red') update() for point, course in ghosts: if abs(pacman - point) < 20: return ontimer(move, 100) def change(x, y): """Change pacman aim if valid.""" if valid(pacman + vector(x, y)): aim.x = x aim.y = y setup(420, 420, 370, 0) hideturtle() tracer(False) writer.goto(160, 160) writer.color('white') writer.write(state['score']) listen() onkey(lambda: change(5, 0), 'Right') onkey(lambda: change(-5, 0), 'Left') onkey(lambda: change(0, 5), 'Up') onkey(lambda: change(0, -5), 'Down') world() move() done()
代码解释
这段代码实现了经典街机游戏Pacman的简化版本。下面是代码的解释:
首先,导入了必要的模块和函数:
from random import choice # 用于选择随机方向
from turtle import * # 用于绘制图形
from freegames import floor, vector # 自定义的辅助函数
然后,定义了一些全局变量和初始状态:
state = {'score': 0} # 当前游戏状态,初始得分为0
path = Turtle(visible=False) # 用于绘制游戏场景的路径
writer = Turtle(visible=False) # 用于显示分数的文字
aim = vector(5, 0) # Pacman 的移动方向
pacman = vector(-40, -80) # Pacman 的初始位置
ghosts = [ # 鬼的初始位置和移动方向
[vector(-180, 160), vector(5, 0)],
[vector(-180, -160), vector(0, 5)],
[vector(100, 160), vector(0, -5)],
[vector(100, -160), vector(-5, 0)],
]
接下来是游戏地图的定义,用一个长串的数字表示墙壁和空地的布局:
tiles = [
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0,
...
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
]
然后定义了一些辅助函数:
square(x, y)
: 在指定位置绘制一个正方形。offset(point)
: 将坐标转换为地图上的索引。valid(point)
: 检查坐标是否是合法的游戏区域。
接下来的 world()
函数用于绘制游戏地图:
def world():
bgcolor('black') # 设置背景颜色为黑色
path.color('blue') # 设置路径颜色为蓝色
for index in range(len(tiles)):
tile = tiles[index]
if tile > 0: # 如果是墙壁或空地
x = (index % 20) * 20 - 200
y = 180 - (index // 20) * 20
square(x, y)
if tile == 1: # 如果是食物
path.up()
path.goto(x + 10, y + 10)
path.dot(2, 'white') # 在食物位置绘制一个小白点
然后定义了 move()
函数,用于移动 Pacman 和鬼:
def move():
writer.undo() # 清除之前的分数显示
writer.write(state['score']) # 显示当前分数
clear() # 清除之前的绘图
if valid(pacman + aim): # 如果 Pacman 可以朝当前方向移动
pacman.move(aim) # 移动 Pacman
index = offset(pacman)
if tiles[index] == 1: # 如果 Pacman 吃到了食物
tiles[index] = 2 # 将食物变成空地
state['score'] += 1 # 分数加1
x = (index % 20) * 20 - 200
y = 180 - (index // 20) * 20
square(x, y) # 在 Pacman 移动后的位置接下来是鬼的移动逻辑:
```python
for point, course in ghosts:
if valid(point + course): # 如果鬼可以朝当前方向移动
point.move(course) # 移动鬼
else:
options = [
vector(5, 0),
vector(-5, 0),
vector(0, 5),
vector(0, -5),
]
plan = choice(options) # 随机选择一个方向
course.x = plan.x
course.y = plan.y
up()
goto(point.x + 10, point.y + 10)
dot(20, 'red') # 在鬼的位置绘制一个红色点
接下来是 draw()
函数,用于绘制 Pacman 的图形:
def draw():
clear() # 清除之前的绘图
# 绘制 Pacman
up()
goto(pacman.x + 10, pacman.y + 10)
dot(20, 'yellow') # 在 Pacman 的位置绘制一个黄色点
# 绘制鬼
for point, course in ghosts:
up()
goto(point.x + 10, point.y + 10)
dot(20, 'red') # 在鬼的位置绘制一个红色点
update() # 更新绘图
然后是 change(x, y)
函数,用于改变 Pacman 的移动方向:
def change(x, y):
if valid(pacman + vector(x, y)):
aim.x = x
aim.y = y
最后是主循环,负责设置游戏窗口和事件处理:
setup(420, 420, 370, 0) # 设置游戏窗口的大小和位置
hideturtle() # 隐藏海龟图标
tracer(False) # 关闭动画效果
onscreenclick(change) # 注册鼠标点击事件,用于改变 Pacman 的移动方向
# 设置绘图对象的属性
path.speed(0)
writer.speed(0)
writer.color('white')
path.color('blue')
world() # 绘制初始游戏地图
tracer(True) # 打开动画效果
# 游戏主循环
while True:
move() # 移动 Pacman 和鬼
draw() # 绘制 Pacman 和鬼的图形
done() # 结束游戏
以上就是这段代码的主要逻辑。它实现了一个简化的 Pacman 游戏,玩家可以通过点击游戏窗口来改变 Pacman 的移动方向,同时要躲避鬼并吃掉食物来获得分数。游戏的界面使用了 Turtle 模块进行绘制,具有简单的图形效果。