AI辅助编程实战:用Python与Pygame开发经典贪吃蛇游戏
1. 项目概述当经典游戏开发遇上AI助手最近几年AI编程工具的发展速度确实让人惊讶。作为一名有十多年编程经验的开发者我最初对这类工具的态度是怀疑的——它们能写出真正可用的代码吗会不会只是生成一些华而不实的“玩具”直到我亲自尝试用AI工具来辅助完成一个具体的项目比如这个经典的贪吃蛇游戏我的看法才有了彻底的转变。这不仅仅是一个简单的代码生成实验更是一次关于现代开发工作流如何被AI重塑的深度体验。贪吃蛇这个游戏相信是很多程序员入门图形界面编程的第一个实战项目。它逻辑清晰涉及碰撞检测、图形渲染、状态管理和用户输入处理等核心游戏开发概念但又不会过于复杂。过去我们可能需要翻阅Pygame的官方文档一行行地敲出初始化窗口、绘制矩形、处理键盘事件的代码。但现在你可以直接告诉AI“用Python 3.10和Pygame写一个贪吃蛇游戏蛇要能增长撞墙或撞到自己游戏结束并显示分数。” 几分钟内一个可运行的代码框架就出来了。这个项目的核心价值在我看来已经超越了“写一个贪吃蛇游戏”本身。它更像是一个**“AI辅助编程”的完整工作流示范**。目标读者非常广泛对于编程新手这是一个绝佳的、低门槛的实践能让你快速获得成就感并理解游戏的基本循环对于有一定经验的开发者你可以借此深入思考如何更高效地与AI协作将AI作为你的“超级实习生”处理那些繁琐、模式化的编码任务而你自己则专注于架构设计、逻辑优化和调试。整个过程你会深刻体会到AI不是来取代程序员的而是来放大程序员能力的工具。关键在于你需要知道如何向它提问如何迭代优化它的输出以及如何将它的代码整合成一个真正健壮、可维护的项目。接下来我就带你完整走一遍这个结合AI工具用Python和Pygame实现经典贪吃蛇游戏的全过程并附上我踩过坑、优化过的完整代码。2. 环境准备与工具选型搭建你的AI编程工作站在开始让AI写代码之前我们必须先把“战场”布置好。一个稳定、高效的本地开发环境是后续一切操作的基础。很多人拿到AI生成的代码后直接运行报错第一步就卡住了问题往往就出在环境配置上。2.1 Python环境版本管理与虚拟环境隔离首先确保你安装了Python。我强烈推荐使用Python 3.8以上的版本因为AI工具对这些版本的兼容性最好生态库也最全。直接从Python官网下载安装包是最直接的方式。安装时务必记得勾选“Add Python to PATH”这个选项这能让你在命令行中直接使用python和pip命令避免后续无数麻烦。安装好后打开你的终端Windows上是CMD或PowerShellmacOS/Linux上是Terminal输入python --version来验证。如果显示版本号说明安装成功。注意很多人的电脑里可能已经装了多个Python版本比如系统自带的Python 2.7和后来安装的Python 3.x。这容易导致命令混淆。一个专业的做法是使用虚拟环境Virtual Environment。虚拟环境可以为每个项目创建一个独立的Python运行环境项目之间的库依赖互不干扰。这是现代Python开发的标配。创建虚拟环境非常简单。在你的项目文件夹里比如snake_game打开终端执行# Windows python -m venv venv # macOS/Linux python3 -m venv venv这会在当前目录创建一个名为venv的文件夹里面包含了一个独立的Python解释器。接下来激活它# Windows (CMD/PowerShell) venv\Scripts\activate # macOS/Linux source venv/bin/activate激活后你的命令行提示符前面通常会显示(venv)表示你已经在这个虚拟环境中了。之后所有通过pip安装的包都只会安装到这个环境中不会影响系统全局或其他项目。2.2 Pygame库安装解决常见的“安装失败”问题Pygame是我们要用的游戏开发库。在激活的虚拟环境中安装它理论上只需要一行命令pip install pygame但这里可能是第一个坑。特别是对于Windows用户可能会遇到需要Microsoft C Build Tools的问题或者下载速度极慢甚至超时。实操心得如果直接pip install pygame失败可以尝试以下几个方法使用国内镜像源加速这是最有效的方法。国内访问PyPI官方源可能很慢我们可以使用清华、阿里云等镜像。pip install pygame -i https://pypi.tuna.tsinghua.edu.cn/simple升级pip工具有时旧版本的pip会导致安装问题。python -m pip install --upgrade pip使用预编译的wheel文件对于Windows可以去 这个非官方网站 下载对应你Python版本和系统位数32位或64位的.whl文件然后用pip本地安装。pip install pygame‑2.5.2‑cp310‑cp310‑win_amd64.whl安装成功后可以写一个简单的测试脚本test_pygame.py来验证import pygame pygame.init() print(Pygame 初始化成功) pygame.quit()运行它如果没有报错说明Pygame已经就绪。2.3 AI工具的选择与使用策略这是本项目的灵魂。市面上AI编程工具很多比如ChatGPT、GitHub Copilot、Claude、以及国内的DeepSeek、Kimi等。我的策略是将AI工具分为“主力构思”和“辅助补全”两类来使用。主力构思如 ChatGPT Plus, Claude, DeepSeek网页版用于进行完整的、对话式的需求描述和代码生成。你告诉它完整的需求它给你一整段代码。它的优势在于理解上下文能进行多轮迭代。例如你可以说“用Python和Pygame写贪吃蛇第一版先实现基本移动和吃食物。” 然后根据它的输出再提出“现在让蛇吃了食物后身体变长并添加计分功能。”辅助补全如 GitHub Copilot, Cursor这类工具通常集成在你的代码编辑器VS Code, PyCharm里。当你写下一行注释或部分代码时它会自动给出补全建议。它的优势在于“即想即得”提高编码流畅度。比如你刚写下# 处理键盘事件它可能就自动补全了整个事件循环的代码框架。我的组合拳我会先用“主力构思”工具生成大致的代码骨架和核心逻辑。然后将代码复制到VS Code中利用“辅助补全”工具来帮我快速填写一些重复性的代码比如颜色定义、绘制函数或者根据错误提示让Copilot帮我写一小段修复代码。绝对不要指望AI一次就给你完美的代码。它的第一版输出往往是一个“能跑起来”的demo里面充满了需要你人工干预和优化的地方。比如它可能不会处理窗口关闭事件或者碰撞检测的逻辑有瑕疵。你的角色是“架构师”和“质检员”AI是“快速原型生成器”。3. 核心游戏逻辑设计与AI协作拆解有了环境和工具我们就可以开始构思游戏了。贪吃蛇的核心逻辑并不复杂但用AI实现时我们需要把需求拆解得足够清晰、无歧义。模糊的指令只会得到模糊甚至错误的代码。3.1 需求拆解给AI一份清晰的“产品说明书”直接对AI说“写个贪吃蛇”是远远不够的。我们需要把游戏分解成一个个具体的、可执行的功能点。以下是我给AI的“需求清单”你可以直接参考游戏窗口创建一个800x600像素的窗口标题为“贪吃蛇游戏”。游戏元素蛇初始长度为1节用一个列表来存储身体每一节的坐标。每节是一个20x20像素的正方形。食物也是一个20x20像素的正方形随机出现在窗口内位置需与网格对齐即坐标是20的倍数。控制与移动使用键盘方向键上、下、左、右控制蛇的移动方向。蛇持续朝当前方向移动不能瞬间掉头例如向右移动时不能直接按左键掉头。游戏规则吃食物蛇头碰到食物蛇长度增加1得分加1食物在新的随机位置出现。碰撞检测撞墙蛇头碰到窗口边界游戏结束。撞自己蛇头碰到自己的身体任何一节游戏结束。游戏状态实时在屏幕左上角显示当前得分。游戏结束时屏幕中央显示“Game Over”和重新开始提示。按空格键可以重新开始游戏。按Q键可以退出游戏。把这些点清晰地告诉AI它生成的代码结构会合理得多。例如你可以这样开始对话“我将要开发一个贪吃蛇游戏使用Python和Pygame。请按照以下需求分步实现代码。首先请创建游戏窗口并初始化Pygame...”3.2 数据结构设计AI生成代码的优化起点AI生成的第一版代码在数据结构上往往比较“幼稚”。比如它可能只用两个变量snake_x,snake_y来表示蛇头这无法实现身体的增长。一个经典的贪吃蛇数据结构应该是这样的蛇 (snake_body)一个列表List列表中的每个元素是一个包含[x, y]坐标的列表或元组代表蛇身体的一节。列表的第一个元素snake_body[0]是蛇头最后一个元素是蛇尾。移动时在列表头部插入新的蛇头位置并删除尾部的元素如果没吃到食物。食物 (food_pos)一个包含[x, y]坐标的列表或元组。方向 (direction)用一个字符串如UP,DOWN,LEFT,RIGHT或一个二维向量如[0, -20]表示向上来表示当前移动方向。游戏状态 (game_over,score)布尔值和整数。当你发现AI给出的代码数据结构不合理时可以直接要求它重构。例如“之前的蛇表示方式无法实现增长。请修改代码使用一个列表snake_body来存储蛇身所有段的坐标列表第一个元素是蛇头。”3.3 游戏主循环理解AI生成的框架游戏的核心是一个“游戏循环”Game Loop。AI生成的代码通常会包含这个骨架理解它至关重要# 初始化 pygame.init() screen pygame.display.set_mode((WIDTH, HEIGHT)) clock pygame.time.Clock() # 游戏状态变量初始化 snake_body [...] food_pos [...] direction RIGHT game_over False score 0 # 游戏主循环 while not game_over: # 1. 处理事件如按键 for event in pygame.event.get(): if event.type pygame.QUIT: game_over True elif event.type pygame.KEYDOWN: # 处理方向键... # 2. 更新游戏状态移动蛇检查碰撞 # 根据direction计算新蛇头位置 new_head [snake_body[0][0] dx, snake_body[0][1] dy] snake_body.insert(0, new_head) # 头部增加一节 if 蛇头碰到食物: 得分增加食物重生 # 注意吃了食物不删除尾部蛇就变长了 else: snake_body.pop() # 没吃到食物删除尾部保持长度不变 if 蛇头撞墙 or 蛇头撞到自己: game_over True # 3. 绘制图形 screen.fill(BLACK) # 清屏 # 绘制食物 pygame.draw.rect(screen, RED, (food_pos[0], food_pos[1], BLOCK, BLOCK)) # 绘制蛇身遍历snake_body列表 for segment in snake_body: pygame.draw.rect(screen, GREEN, (segment[0], segment[1], BLOCK, BLOCK)) # 绘制分数 # ... # 4. 更新屏幕显示 pygame.display.update() # 5. 控制帧率控制游戏速度 clock.tick(10) # 每秒10帧数字越小越慢 # 游戏结束退出 pygame.quit()这个循环每秒执行很多次由clock.tick(FPS)控制。每一次循环我们处理输入、更新所有物体的状态、把新状态画出来。AI会帮你搭好这个架子但里面的细节尤其是碰撞检测和状态更新的顺序需要你仔细审查和调试。4. 分步实现与AI迭代从雏形到可玩版本现在让我们进入实战环节看看如何通过与AI的多轮对话将一个简陋的Demo打磨成一个功能完整的游戏。我将模拟这个迭代过程并指出每个阶段的关键点和常见陷阱。4.1 第一轮生成基础框架与核心移动给AI的指令“用Python和Pygame写一个贪吃蛇游戏的最基础版本。只需要一个方块蛇头在窗口内用方向键移动另一个方块作为食物。当蛇头碰到食物时在控制台打印‘吃到食物’即可。请给出完整代码。”AI很可能会给出一段类似这样的代码已精简import pygame import random # 常量定义 WIDTH, HEIGHT 800, 600 BLOCK_SIZE 20 WHITE (255,255,255) RED (255,0,0) BLACK (0,0,0) pygame.init() screen pygame.display.set_mode((WIDTH, HEIGHT)) pygame.display.set_caption(贪吃蛇 - 基础版) clock pygame.time.Clock() # 初始位置 snake_x WIDTH // 2 snake_y HEIGHT // 2 snake_dx BLOCK_SIZE snake_dy 0 food_x random.randrange(0, WIDTH-BLOCK_SIZE, BLOCK_SIZE) food_y random.randrange(0, HEIGHT-BLOCK_SIZE, BLOCK_SIZE) running True while running: for event in pygame.event.get(): if event.type pygame.QUIT: running False elif event.type pygame.KEYDOWN: if event.key pygame.K_LEFT: snake_dx -BLOCK_SIZE snake_dy 0 # ... 处理其他方向键 # 移动 snake_x snake_dx snake_y snake_dy # 简单边界检查穿墙 if snake_x WIDTH: snake_x 0 if snake_x 0: snake_x WIDTH - BLOCK_SIZE if snake_y HEIGHT: snake_y 0 if snake_y 0: snake_y HEIGHT - BLOCK_SIZE # 碰撞检测食物 if abs(snake_x - food_x) BLOCK_SIZE and abs(snake_y - food_y) BLOCK_SIZE: print(吃到食物) food_x random.randrange(0, WIDTH-BLOCK_SIZE, BLOCK_SIZE) food_y random.randrange(0, HEIGHT-BLOCK_SIZE, BLOCK_SIZE) # 绘制 screen.fill(BLACK) pygame.draw.rect(screen, WHITE, (snake_x, snake_y, BLOCK_SIZE, BLOCK_SIZE)) pygame.draw.rect(screen, RED, (food_x, food_y, BLOCK_SIZE, BLOCK_SIZE)) pygame.display.update() clock.tick(10) pygame.quit()第一轮代码分析优点框架有了能跑起来蛇可以移动能“吃”到食物虽然只是打印。问题蛇不会增长数据结构还是单个点。边界处理是“穿墙”而经典贪吃蛇是“撞墙死”。没有身体自然没有撞自己检测。方向控制可以瞬间反向比如向右时按左键会直接掉头这不符合常理。4.2 第二轮实现蛇身增长与撞墙死亡给AI的指令“很好现在请改进代码。1. 将蛇改为一个列表snake_body来管理初始长度为3节。2. 吃到食物后蛇的长度增加1即列表增加一个元素食物重生。3. 将边界检查改为撞墙即游戏结束。4. 防止蛇瞬间反向移动例如向右时不能直接向左。请输出修改后的完整代码。”AI会根据你的要求进行修改。关键改动部分会像这样# 蛇身改为列表 snake_body [[WIDTH//2, HEIGHT//2], [WIDTH//2 - BLOCK_SIZE, HEIGHT//2], [WIDTH//2 - BLOCK_SIZE*2, HEIGHT//2]] direction RIGHT next_direction direction food_pos [food_x, food_y] # 食物也用列表 score 0 while running: # 事件处理只更新“下一个方向”不直接改变蛇身 for event in pygame.event.get(): if event.type pygame.QUIT: running False elif event.type pygame.KEYDOWN: if event.key pygame.K_LEFT and direction ! RIGHT: next_direction LEFT # ... 处理其他键同时检查是否与当前方向相反 # 在游戏状态更新前应用“下一个方向” direction next_direction # 根据方向计算新蛇头 head_x, head_y snake_body[0] if direction LEFT: new_head [head_x - BLOCK_SIZE, head_y] # ... 其他方向 # 插入新蛇头 snake_body.insert(0, new_head) # 碰撞检测食物 if snake_body[0] food_pos: score 1 # 食物重生且不能重生在蛇身上 while True: food_pos [random.randrange(0, WIDTH, BLOCK_SIZE), random.randrange(0, HEIGHT, BLOCK_SIZE)] if food_pos not in snake_body: break else: # 没吃到食物删除蛇尾保持长度 snake_body.pop() # 碰撞检测墙壁 if (snake_body[0][0] 0 or snake_body[0][0] WIDTH or snake_body[0][1] 0 or snake_body[0][1] HEIGHT): game_over True # 新增一个game_over变量 # 碰撞检测自己检查新蛇头是否在蛇身列表中[1:] if snake_body[0] in snake_body[1:]: game_over True # 绘制遍历snake_body绘制每一节 screen.fill(BLACK) for segment in snake_body: pygame.draw.rect(screen, GREEN, (segment[0], segment[1], BLOCK_SIZE, BLOCK_SIZE)) pygame.draw.rect(screen, RED, (food_pos[0], food_pos[1], BLOCK_SIZE, BLOCK_SIZE)) # 还需要绘制分数...第二轮代码分析核心进步蛇身列表、增长逻辑、撞墙死、防反向移动都实现了。新问题与优化点食物重生逻辑AI可能会用一个简单的while True循环来确保食物不重生在蛇身上。这在蛇很长时可能效率低下但作为第一个可行方案可以接受。游戏结束处理现在游戏结束game_over True后循环会退出窗口直接关闭。我们需要一个游戏结束画面并允许重新开始。分数显示还没有在屏幕上显示分数。4.3 第三轮添加游戏状态与UI界面给AI的指令“现在请添加游戏状态管理。1. 游戏结束后不要立即退出而是在屏幕中央显示‘Game Over! Score: [分数]’和‘Press SPACE to restart, Q to quit’。2. 在游戏过程中在屏幕左上角实时显示当前分数。3. 实现按空格键重新开始游戏的功能按Q键退出游戏。请使用Pygame的字体模块来渲染文字。”这是对AI综合能力的一个考验。它需要理解游戏状态进行中、已结束、事件处理的分流游戏中和结束画面中按键意义不同、以及文字渲染。生成的代码会引入新的函数比如draw_text()和show_game_over_screen()主循环的逻辑也会变得更复杂。一个常见的实现模式是在game_over为True时进入一个while循环专门显示结束画面并等待玩家输入def show_game_over_screen(score): font_large pygame.font.SysFont(None, 72) font_small pygame.font.SysFont(None, 36) text_game_over font_large.render(fGame Over!, True, WHITE) text_score font_small.render(fScore: {score}, True, WHITE) text_restart font_small.render(Press SPACE to restart, Q to quit, True, WHITE) # ... 计算文字位置并绘制到screen上 pygame.display.update() waiting True while waiting: for event in pygame.event.get(): if event.type pygame.QUIT: pygame.quit() quit() # 直接退出程序 if event.type pygame.KEYDOWN: if event.key pygame.K_SPACE: waiting False # 跳出等待循环重新开始游戏 return True elif event.key pygame.K_q: pygame.quit() quit() clock.tick(5) # 结束画面不需要高帧率 return False # 在主循环外部 while True: # 最外层循环用于游戏重启 game_over False score 0 # ... 初始化蛇和食物 # 游戏主循环 while not game_over: # ... 原来的游戏逻辑 # 绘制分数 score_text font.render(fScore: {score}, True, WHITE) screen.blit(score_text, (10, 10)) # 游戏结束显示结束画面 if show_game_over_screen(score): continue # 如果玩家按了空格回到最外层循环开头重新初始化游戏 else: break # 如果玩家按了Q或关了窗口退出最外层循环第三轮代码分析功能趋于完整现在游戏有了基本的开始-进行-结束-重启的完整生命周期。潜在问题代码结构AI可能会把很多逻辑都塞在主循环里导致代码臃肿。作为有经验的开发者我们应该主动将一些功能模块化比如把绘制分数、绘制蛇、检查碰撞写成单独的函数。字体兼容性pygame.font.SysFont(None, size)在某些系统上可能找不到默认字体导致崩溃。更稳健的做法是使用pygame.font.Font(None, size)使用Pygame内置的默认字体或者指定一个确切的字体文件路径。游戏速度clock.tick(10)意味着每秒10帧对于贪吃蛇来说可能偏慢或偏快这成了一个可调节的参数。5. 代码优化、调试与经验分享拿到AI生成的、功能基本完整的代码后我们的工作才真正开始。现在需要以工程师的眼光去审查、优化和调试这段代码让它从“能跑”变得“健壮”、“优雅”。5.1 代码重构与模块化AI生成的代码通常是线性的所有东西都写在主循环附近。我们可以手动进行重构提升可读性和可维护性。提取常量将窗口大小、方块尺寸、颜色、速度等定义在文件开头的常量区。封装函数draw_snake(surface, body): 负责绘制蛇。draw_food(surface, pos): 负责绘制食物。draw_score(surface, score): 负责绘制分数。check_collision(head, body, screen_width, screen_height): 负责检查撞墙和撞自己返回布尔值。generate_food(body, screen_width, screen_height, block_size): 负责在非蛇身的位置生成食物。分离游戏逻辑与渲染在主循环中先更新游戏状态移动、碰撞检测再调用绘制函数。这样逻辑更清晰。实操心得当你要求AI“将绘制功能封装成函数”时它通常能做的不错。你可以这样指令“请将绘制蛇、食物、分数和游戏结束文字的功能分别封装成独立的函数如draw_snake(),draw_food()等并在主循环中调用它们。”5.2 调试AI代码的常见陷阱即使代码看起来合理运行时也可能出现各种奇怪的问题。以下是我在调试这个AI生成的贪吃蛇时遇到的典型问题及解决方法蛇身闪烁或移动异常问题蛇移动时身体看起来在闪烁或者移动轨迹很奇怪。原因这通常是绘制顺序或坐标更新逻辑的问题。确保你在每一帧中都是先清屏(screen.fill(BLACK))然后按从后到前的顺序绘制所有元素比如先画食物再画蛇身最后再pygame.display.update()。另外检查蛇身列表的更新逻辑是否在移动后正确地插入新头和删除旧尾调试在移动和绘制后打印出snake_body列表观察坐标变化是否符合预期。碰撞检测不精确问题蛇头明明看起来没碰到食物或墙壁却判定为碰撞或者反之。原因Pygame的draw.rect绘制是从(x, y)坐标开始画一个宽高为BLOCK_SIZE的矩形。碰撞检测时如果直接用snake_head food_pos要求坐标完全相等这是正确的因为我们的坐标都是BLOCK_SIZE的整数倍。但如果你的移动逻辑有误导致坐标出现非整数倍就会出问题。解决确保所有坐标计算蛇头移动、食物生成都严格与BLOCK_SIZE对齐。使用整数除法和乘法来保证。例如new_x (head_x // BLOCK_SIZE) * BLOCK_SIZE dx。游戏结束后无法退出或重启问题按Q键没反应或者按空格重启后状态混乱。原因事件处理循环嵌套错误或者游戏状态变量没有正确重置。解决仔细检查show_game_over_screen函数中的事件循环。确保它正确处理了pygame.QUIT事件。在重启游戏时必须将所有游戏状态变量snake_body,direction,score,food_pos重置为初始值。最好写一个reset_game()函数来做这件事。Mac系统窗口不显示问题在macOS上运行Pygame窗口一闪而过或者根本不出现。原因这是Pygame在macOS上的一个常见问题与显示驱动或事件循环有关。解决在主循环开始前强制调用一次pygame.display.flip()。或者在事件循环中确保有持续调用pygame.event.pump()来让系统知道你的程序是活跃的。这是从参考资料中学到的宝贵经验。5.3 性能与体验优化建议基础功能完成后我们可以考虑一些优化让游戏体验更好。速度随长度增加让游戏随着蛇身变长而逐渐加速增加挑战性。可以在主循环中动态调整clock.tick()的参数。例如clock.tick(10 len(snake_body) // 5)。更美观的绘制给蛇头和蛇身用不同颜色。给食物换个造型比如画个圆。音效使用pygame.mixer模块在吃到食物、游戏结束时播放简单的音效。最高分记录将最高分保存到一个本地文件如highscore.txt中每次游戏结束后比较并更新。你可以把这些优化点作为新的需求提给AI“现在我希望游戏难度能随着蛇的长度增加而增加请修改代码让游戏帧率速度随着snake_body列表长度的增加而适当提高。” AI通常能很好地理解并实现这个逻辑。6. 完整代码与最终整合经过多轮与AI的交互、调试和手动优化我们得到了一个功能完善、代码结构清晰的贪吃蛇游戏。以下是最终的完整代码示例它融合了上述所有讨论的最佳实践import pygame import random import sys # 初始化 pygame.init() # 常量定义 WINDOW_WIDTH 800 WINDOW_HEIGHT 600 BLOCK_SIZE 20 FPS 15 # 初始帧率 # 颜色定义 (R, G, B) BLACK (0, 0, 0) WHITE (255, 255, 255) GREEN (0, 255, 0) DARK_GREEN (0, 200, 0) # 蛇头颜色 RED (255, 0, 0) BLUE (0, 120, 255) # 分数颜色 # 方向常量 UP (0, -BLOCK_SIZE) DOWN (0, BLOCK_SIZE) LEFT (-BLOCK_SIZE, 0) RIGHT (BLOCK_SIZE, 0) # 初始化屏幕 screen pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT)) pygame.display.set_caption(AI辅助开发 - 经典贪吃蛇) clock pygame.time.Clock() font pygame.font.Font(None, 36) # 使用默认字体 # 在Mac上确保窗口显示 pygame.display.flip() def draw_snake(snake_body): 绘制蛇蛇头用不同颜色 for i, segment in enumerate(snake_body): color DARK_GREEN if i 0 else GREEN # 蛇头深绿色身体浅绿色 pygame.draw.rect(screen, color, (segment[0], segment[1], BLOCK_SIZE, BLOCK_SIZE)) # 可选给身体节之间画个细缝更美观 pygame.draw.rect(screen, BLACK, (segment[0], segment[1], BLOCK_SIZE, BLOCK_SIZE), 1) def draw_food(food_pos): 绘制食物用圆形看起来更可口 center_x food_pos[0] BLOCK_SIZE // 2 center_y food_pos[1] BLOCK_SIZE // 2 pygame.draw.circle(screen, RED, (center_x, center_y), BLOCK_SIZE // 2) def draw_score(score, high_score): 在屏幕左上角绘制当前分数和最高分 score_text font.render(fScore: {score}, True, BLUE) high_score_text font.render(fHigh Score: {high_score}, True, BLUE) screen.blit(score_text, (10, 10)) screen.blit(high_score_text, (10, 50)) def draw_game_over(score): 游戏结束画面 game_over_font pygame.font.Font(None, 72) instruction_font pygame.font.Font(None, 36) game_over_text game_over_font.render(GAME OVER, True, RED) score_text font.render(fFinal Score: {score}, True, WHITE) restart_text instruction_font.render(Press SPACE to Restart, True, WHITE) quit_text instruction_font.render(Press Q to Quit, True, WHITE) # 居中显示 screen.blit(game_over_text, (WINDOW_WIDTH // 2 - game_over_text.get_width() // 2, WINDOW_HEIGHT // 2 - 100)) screen.blit(score_text, (WINDOW_WIDTH // 2 - score_text.get_width() // 2, WINDOW_HEIGHT // 2 - 20)) screen.blit(restart_text, (WINDOW_WIDTH // 2 - restart_text.get_width() // 2, WINDOW_HEIGHT // 2 40)) screen.blit(quit_text, (WINDOW_WIDTH // 2 - quit_text.get_width() // 2, WINDOW_HEIGHT // 2 80)) def generate_food(snake_body): 在非蛇身的位置随机生成食物 while True: x random.randrange(0, WINDOW_WIDTH - BLOCK_SIZE, BLOCK_SIZE) y random.randrange(0, WINDOW_HEIGHT - BLOCK_SIZE, BLOCK_SIZE) food_pos [x, y] if food_pos not in snake_body: # 确保食物不在蛇身上 return food_pos def check_collision(head, snake_body): 检查碰撞撞墙或撞自己 # 撞墙 if (head[0] 0 or head[0] WINDOW_WIDTH or head[1] 0 or head[1] WINDOW_HEIGHT): return True # 撞自己 (检查头是否在身体其他部分中) if head in snake_body[1:]: return True return False def load_high_score(): 从文件加载最高分 try: with open(highscore.txt, r) as f: return int(f.read()) except FileNotFoundError: return 0 def save_high_score(score): 保存最高分到文件 with open(highscore.txt, w) as f: f.write(str(score)) def game_loop(): 游戏主逻辑循环 # 游戏状态初始化 snake_body [[WINDOW_WIDTH // 2, WINDOW_HEIGHT // 2]] current_direction RIGHT next_direction RIGHT food_pos generate_food(snake_body) score 0 high_score load_high_score() game_over False speed FPS # 动态速度 while True: # 主游戏循环 # 事件处理 for event in pygame.event.get(): if event.type pygame.QUIT: pygame.quit() sys.exit() if event.type pygame.KEYDOWN: if not game_over: # 游戏进行中处理方向键防止反向移动 if event.key pygame.K_UP and current_direction ! DOWN: next_direction UP elif event.key pygame.K_DOWN and current_direction ! UP: next_direction DOWN elif event.key pygame.K_LEFT and current_direction ! RIGHT: next_direction LEFT elif event.key pygame.K_RIGHT and current_direction ! LEFT: next_direction RIGHT # 游戏结束后的按键无论游戏状态 if event.key pygame.K_q: pygame.quit() sys.exit() if event.key pygame.K_SPACE and game_over: return # 重启游戏 if not game_over: # 更新方向 current_direction next_direction # 计算新蛇头位置 head_x, head_y snake_body[0] dx, dy current_direction new_head [head_x dx, head_y dy] # 插入新蛇头 snake_body.insert(0, new_head) # 检查是否吃到食物 if new_head food_pos: score 1 food_pos generate_food(snake_body) # 每得5分速度稍微增加难度提升 if score % 5 0: speed 1 # 更新最高分 if score high_score: high_score score save_high_score(high_score) else: # 没吃到食物移除蛇尾 snake_body.pop() # 检查碰撞 if check_collision(new_head, snake_body): game_over True # 绘制 screen.fill(BLACK) draw_food(food_pos) draw_snake(snake_body) draw_score(score, high_score) else: # 游戏结束显示结束画面 screen.fill(BLACK) draw_game_over(score) draw_score(score, high_score) # 结束画面也显示分数 pygame.display.update() clock.tick(speed) # 控制游戏速度 def main(): 主函数处理游戏重启 while True: game_loop() if __name__ __main__: main()最终版本亮点模块清晰每个功能都有独立的函数主循环简洁易懂。健壮性包含了文件读写最高分记录、跨平台兼容性考虑Mac的flip、安全的食物生成。体验优化蛇头蛇身颜色区分、食物绘制为圆形、速度随分数增加、游戏结束画面友好。代码注释关键步骤都有注释便于理解和后续修改。7. 总结AI作为编程伙伴的思考通过这个完整的项目我们可以清晰地看到AI工具在编程中扮演的角色不是“替代者”而是一个强大的“加速器”和“协作者”。它极大地降低了从零到一的门槛快速生成可运行的原型让你能立刻看到效果并进行迭代。这对于学习新库如Pygame、验证想法、或者完成那些你明确知道步骤但懒得写的模板代码效率提升是巨大的。然而它也明确地告诉我们AI无法替代程序员的核心价值对问题的深度理解、系统设计能力、调试技巧和将粗糙原型打磨成健壮产品的工程能力。AI生成的代码需要你以“审查者”和“架构师”的身份去审视、调试和重构。你提出的问题越精准迭代的指令越明确得到的结果就越好。这个过程本身就是对你逻辑思维和工程能力的一种锻炼。最后关于工具选择我的建议是对于这种需要多轮对话、明确需求拆解的任务像DeepSeek、ChatGPT这样的聊天式AI是首选而在日常编码中GitHub Copilot这类集成在IDE里的工具能无缝提升你的编码流畅度。合理利用它们你将能更专注于创造性的逻辑和架构设计而不是重复性的键盘敲击。这个贪吃蛇项目只是一个开始尝试用同样的方法论让AI帮你实现更复杂的想法吧你会发现编程的乐趣和效率都进入了新的维度。