CS课程项目设计13:手把手实现支持AI辅助移动的贪吃蛇小游戏
一、研究背景本专栏的第九篇文章介绍了手把手实现经典的贪吃蛇小游戏,具体内容可以参考以下帖子:CS课程项目设计9:手把手实现经典的贪吃蛇小游戏-CSDN博客随着人工智能的火热,AI人机对战的引入显得很有必要,本质上就是引入强化学习的概念了,这也是现在大模型领域比较关心的方向了。因此,和本专栏第六个和第八个CS课程项目一样,我们继续在现有贪吃蛇小游戏基础上,增加AI辅助移动功能:CS课程项目设计6:基
本专栏的第九篇文章介绍了手把手实现经典的贪吃蛇小游戏,具体内容可以参考以下帖子:
随着人工智能的火热,AI人机对战的引入显得很有必要,本质上就是引入强化学习的概念了,这也是现在大模型领域比较关心的方向了。
因此,和本专栏第六个和第八个CS课程项目一样,我们继续在现有贪吃蛇小游戏基础上,增加AI辅助移动功能:
CS课程项目设计6:基于Canvas支持人机对战的井字棋游戏-CSDN博客https://blog.csdn.net/weixin_36431280/article/details/149668934?spm=1001.2014.3001.5501CS课程项目设计8:基于Canvas支持AI人机对战的五子棋游戏-CSDN博客
https://blog.csdn.net/weixin_36431280/article/details/149686915?spm=1001.2014.3001.5501
一、研究背景
随着贪吃蛇是经典的休闲游戏,其核心玩法是通过控制蛇的移动方向,使蛇吃到食物并避免碰撞自身或边界,随着食物的获取,蛇的长度不断增加,游戏难度逐渐提升。传统贪吃蛇游戏依赖玩家的操作反应速度和策略规划能力,而引入 AI 辅助移动功能后,可通过算法自动规划蛇的移动路径,降低操作难度,同时为游戏 AI 路径规划研究提供实践案例。
本代码基于 Pygame 库实现,在保留经典贪吃蛇玩法的基础上,集成了 AI 自动寻路功能,旨在探索基于广度优先搜索(BFS)算法的游戏智能决策机制,提升游戏的可玩性与研究价值。
二、研究目的
- 实现一个功能完整的贪吃蛇游戏,支持玩家手动控制与 AI 辅助移动两种模式切换;
- 基于 BFS 算法设计蛇头到食物的最短路径规划逻辑,使 AI 能够自主避开障碍物、自身身体及边界;
- 验证路径规划算法在动态游戏场景中的有效性(如蛇身长度变化、障碍物随机生成等);
- 提供友好的用户交互界面,包括用户名输入、速度设置、游戏状态显示等功能。
三、技术方案
3.1 开发环境与工具
基于 Python 语言,使用 Pygame 库实现游戏窗口渲染、事件处理、图像与音效加载等功能;通过文件操作实现历史最高分的持久化存储。
3.2 核心算法
- 路径规划:采用 BFS(广度优先搜索)算法,以蛇头为起点、食物为终点,在游戏区域内搜索最短路径。搜索过程中需避开蛇身(除头部外)、障碍物及边界。
- 碰撞检测:实时检测蛇头与边界、自身身体、障碍物的碰撞,触发游戏结束逻辑。
3.3 功能模块设计
- 用户交互模块:支持用户名输入、游戏速度调节(1-30 级)、障碍物启用 / 禁用设置;
- 游戏逻辑模块:蛇的移动控制(手动 / AI 切换)、食物随机生成(含不同分数的食物类型)、分数计算与最高分记录;
- AI 模块:基于 BFS 算法的路径规划,根据规划结果自动调整蛇的移动方向。
其中,AI模块的可视化界面如下图所示:
四、实现流程
4.1 初始化与配置
-
初始化 Pygame 及混音器,定义游戏窗口尺寸(含游戏区域与信息面板)、颜色常量、蛇的移动参数(速度范围、方块大小);
-
加载游戏资源(蛇头 / 身体 / 食物 / 障碍物图像、音效),若加载失败则使用默认色块与空音效对象替代;
- 设置支持中文的字体,用于显示文字信息(分数、提示等)。
相较于第九篇帖子,我们主要修改了set_speed()函数,增加了路障启用选项:
- 游戏开始时没有路障
- 蛇每吃掉一个食物,会生成一个新路障
- 路障不会与蛇身或食物重叠
- 蛇撞到路障会导致游戏结束
路障功能的实现代码如下所示:
# 判断是否撞到路障(如果启用了路障)
if enable_obstacles and obstacles:
for obstacle in obstacles:
if x1 == obstacle[0] and y1 == obstacle[1]:
game_close = True
x1 += x1_change
y1 += y1_change
draw_checkerboard()
dis.blit(current_food["image"], [foodx, foody])
# 绘制路障(如果启用了路障且路障存在)
if enable_obstacles and obstacles:
for obstacle in obstacles:
dis.blit(obstacle_img, [obstacle[0], obstacle[1]])
# 吃到食物后增加分数、长度并生成新食物和路障
if x1 == foodx and y1 == foody:
# 播放吃食物音效
eat_sound.play()
score += current_food["score"] # 增加对应分数
Length_of_snake += 1 # 增加蛇长度
# 更新历史最高得分
if score > high_score:
high_score = score
save_high_score(high_score)
# 生成新食物
current_food = random.choices(food_types, weights=[ft["probability"] for ft in food_types])[0]
foodx, foody = generate_valid_position(snake_List, None, None)
# 如果启用了路障,生成新路障(替换旧路障)
if enable_obstacles:
obstacles = [generate_valid_position(snake_List, foodx, foody)]
路障功能的可视化界面如下图所示:
路障功能禁用的可视化界面如下图所示:
4.2 用户输入与设置
- 通过输入框获取用户名(默认 “玩家 1”);
- 提供速度调节界面(方向键 ± 速度)、障碍物开关(空格键切换),按回车确认进入游戏。
4.3 游戏主循环
1)手动模式:通过方向键控制蛇的移动方向(限制反向移动,避免自撞);
2)AI 模式(按 A 键切换)
-
通过输入框获取用户名(默认 “玩家 1”);
- 提供速度调节界面(方向键 ± 速度)、障碍物开关(空格键切换),按回车确认进入游戏。
- 调用
bfs_shortest_path
函数,传入蛇头位置、食物位置、蛇身列表、障碍物等参数; - BFS 算法遍历四个方向(上下左右),生成从蛇头到食物的最短路径;
- 根据路径的下一步位置,自动设置蛇的移动方向(x/y 轴变化量);
3)碰撞检测:实时判断蛇头是否撞墙、撞自身或障碍物,触发游戏结束界面;
4)食物与分数逻辑:蛇吃到食物后,增加对应分数(苹果 + 1、橘子 + 3、西瓜 + 5)、增长蛇身、生成新食物与障碍物(若启用),并更新最高分记录。
其中,核心的bfs_shortest_path
函数代码如下所示:
def bfs_shortest_path(snake_head, food_pos, snake_body, obstacles, snake_block, dis_width, dis_height,
score_bar_height):
"""使用BFS算法寻找从蛇头到食物的最短路径"""
# 定义四个方向的移动向量
directions = [
(snake_block, 0), # 右
(-snake_block, 0), # 左
(0, snake_block), # 下
(0, -snake_block) # 上
]
# 转换位置为网格坐标以便于计算
start = (snake_head[0], snake_head[1])
target = (food_pos[0], food_pos[1])
# 如果已经在食物位置,返回空路径
if start == target:
return []
# 初始化队列和已访问集合
queue = deque()
queue.append([start])
visited = set()
visited.add(start)
# 将蛇身和障碍物添加到障碍集合
obstacles_set = set(obstacles) if obstacles else set()
snake_body_set = set(tuple(segment) for segment in snake_body[:-1]) # 排除蛇头
obstacles_combined = obstacles_set.union(snake_body_set)
# BFS主循环
while queue:
path = queue.popleft()
current_pos = path[-1]
# 尝试四个方向
for dx, dy in directions:
next_x = current_pos[0] + dx
next_y = current_pos[1] + dy
next_pos = (next_x, next_y)
# 检查是否到达目标
if next_pos == target:
return path[1:] + [next_pos] # 返回路径(排除起点)
# 检查是否在有效范围内且未访问过且不是障碍
if (0 <= next_x < game_area_width and # 限制在游戏区域内
score_bar_height <= next_y < dis_height and
next_pos not in visited and
next_pos not in obstacles_combined):
visited.add(next_pos)
new_path = list(path)
new_path.append(next_pos)
queue.append(new_path)
# 如果找不到路径,返回空列表
return []
贪吃蛇有三种食物:苹果、橘子、西瓜,分数分别对应:1分、3分、5分,三种食物出现的概率分别为50%、30%、20%。障碍物为地雷图片,实时出现,可视化界面如下所示:
蛇头如果在移动时碰墙或者踩到地雷障碍物,就会结束游戏,并计算分数,可视化界面如下所示:
4.4 界面渲染
-
绘制棋盘格背景(游戏区域)、蛇身(头部与身体图像)、食物、障碍物;
- 右侧信息面板显示用户名、当前分数、速度、最高分及 AI 状态,底部显示操作提示。
五、总结
本代码实现了一个兼具娱乐性与研究性的贪吃蛇游戏,核心亮点在于集成了基于 BFS 算法的 AI 辅助移动功能。通过手动与 AI 模式的切换,既保留了传统游戏的操作乐趣,又展示了路径规划算法在动态场景中的应用。
后续可进一步优化:
- 增强 AI 算法鲁棒性(如处理 BFS 无解场景的避障策略);
- 增加难度递增机制(如随分数提升自动加快速度);
- 扩展食物与障碍物类型,丰富游戏策略性。
最后,还上传个该项目的简要演示视频,供大家了解。
手把手实现支持AI辅助移动的贪吃蛇小游戏
更多推荐
所有评论(0)