第 12 章:压轴章节(构建一个游戏)

Nanocode 真的能构建出东西吗?

“零代码挑战”:用 Python 和 Pygame 构建一个经典的贪吃蛇游戏。规则只有一条——你不能编写哪怕一行 Python 代码,只能用英语与智能体对话。

An icon of a info-circle1

旁注: 本演示涉及大量 API 调用。如果触及速率限制(HTTP 429),智能体会自动重试。对于较长的会话,可以考虑通过 Ollama 使用本地模型,从而完全避免此类限制。

第一步:准备工作

在项目根目录(即包含 nanocode.py.env 的目录)下,为游戏创建一个工作目录:

An icon of a info-circle1

旁注: 我们在子目录中进行操作,这样智能体的 list_files 只会看到游戏相关文件,而不会看到其自身的源代码,同时也能以全新的记忆状态开始工作。

1 mkdir -p snake_game
2 cp nanocode.py snake_game/
3 cp .env snake_game/
4 cd snake_game

如果你使用的是本书的代码仓库,请改为从 ch11 复制:

1 mkdir -p snake_game
2 cp resources/code/ch11/nanocode.py snake_game/
3 cp .env snake_game/
4 cd snake_game

安装 Pygame:

1 pip install pygame
An icon of a info-circle1

旁注: 上述 Shell 命令适用于 macOS/Linux。在 Windows 上,请改用 mkdir snake_gamecopy nanocode.py snake_game\copy .env snake_game\。如果在 macOS 上执行 pip install pygame 失败,可能需要先运行 brew install sdl2 sdl2_image sdl2_mixer sdl2_ttf。在 Linux 上,请安装 SDL 开发包:sudo apt install libsdl2-dev libsdl2-image-dev libsdl2-mixer-dev libsdl2-ttf-dev。在 Windows 上,pip install pygame 已捆绑所有依赖。

第二步:架构师(计划模式)

启动智能体。我们从计划模式开始,因为我们希望在动工之前先画好蓝图。

1 python nanocode.py

提示词:

1 Build a classic Snake game using Pygame. Include a score counter and Game Over screen with a restart option. Put ALL code in ONE file: snake.py. Write the plan in PLAN.md.

智能体将使用 write_plan 来创建 PLAN.md。请阅读该文件。它应该概述 Snake 类、Food 类以及游戏循环——全部放在一个文件中。

如果计划看起来合理,请继续进行第 3 步。

第 3 步:构建者(执行模式)

切换到执行模式:

1 /mode act

提示词:

1 Implement the plan in snake.py. All code in one file.

注意终端:

1   → Writing snake.py

智能体正在根据它存储在 PLAN.md 中的上下文生成代码。

第四步:现实检验

在运行游戏之前,先调高超时时间。默认的 30 秒根本不够用来实际玩一局游戏——Pygame 的主循环会一直阻塞,直到你关闭窗口。在启动前设置好环境变量:

1 export NANOCODE_TIMEOUT=300

提示词:

1 Run the game with: python snake.py

代理执行 run_command。一个窗口弹出。你玩贪吃蛇游戏。

如果程序崩溃: LLM 是非确定性的。你的代理可能在第一次尝试时就出现 bug。如果游戏崩溃并出现类似 AttributeError: 'Snake' object has no attribute 'draw' 的错误,不要自己动手修复。让代理查看 stderr 输出。

提示词:

1 The game crashed. Read the error and fix it.

智能体将读取 traceback,使用 read_file 找到 bug,使用 edit_file 打上补丁,然后再次运行。

第五步:转向(需求蔓延)

游戏可以运行了,但很难看。蛇只是一堆绿色方块。让我们来压力测试一下智能体的重构能力。

提示词:

1 The game looks boring. Make the snake change color as it eats food, increase speed every 5 points, and search the web for 'cool retro game color palettes' to apply.

智能体应该:

  1. 使用 search_web 查找配色方案
  2. 使用 read_file 了解当前的渲染逻辑
  3. 使用 edit_file 注入新功能
  4. 运行游戏进行验证

会出什么问题

你的结果会和我的不同——大语言模型是非确定性的。但以下是通常会发生的情况,以及需要注意的地方。

第一次运行时的常见失败:

  • ModuleNotFoundError: No module named 'pygame' —— 智能体忘记了需要先安装它,或者在不同的环境中运行了脚本。告诉它先运行 pip install pygame
  • 智能体定义了某个方法,但在调用处拼写错误,导致 AttributeError。一旦看到错误追踪信息,智能体会很快修复这类问题。
  • 碰撞检测中的差一错误。蛇穿墙而过,或者提前一个像素就死掉了。这类问题需要 2-3 次“编辑-运行-修复“的迭代。

典型的会话流程:

在我的测试中,智能体通常在 2-4 次迭代内就能得到一个可运行(但不太好看)的游戏。第一次编写的代码会崩溃,第二或第三次修复后游戏就能跑起来了。功能扩展步骤(修改颜色、速度递增)又会增加 3-5 次迭代,因为智能体需要读取自己的代码、进行精细修改,并验证每一处改动。

到最后,对话已经深入到 15-20 轮。如果你使用的是 Claude,注意压缩触发的时机——大约在第 12-15 轮,当 token 数量接近 75% 阈值时,你会看到“(Compacting conversation…)“的提示。压缩之后,智能体会丢失一些早期轮次的细节,但仍会继续工作。这正是第 9 章那套系统在证明其价值。

智能体容易卡壳的地方:

Pygame 的坐标系和事件循环比较棘手。智能体有时会写出渲染正常但键盘输入处理不当的代码,或者绘制蛇的顺序有误,导致蛇头出现在身体后面。这类 bug 人类一眼就能发现,但智能体看不到——它没有视觉反馈,只有 stdout 和 stderr。如果游戏运行时没有报错但显示有问题,你需要描述视觉上的 bug,比如:“蛇渲染反了——蛇头应该在前面。”

关键不在于第一次就做到完美,而在于智能体能够收敛——编写、运行、读取错误、修复、再重复——贯穿十一章所构建的每一件工具都在此派上用场。

在你交付最终的 snake.py 之前,先读一遍。智能体写的代码能跑,但人类仍然应该审查那些测试循环无法发现的问题:硬编码的魔法数字、遗漏的边界情况(如果窗口被调整大小怎么办?),以及代码结构是否是你愿意长期维护的样子。智能体是快速的起草者,而不是最终的审查者。

结语

计划、实现、崩溃、调试、修复、再运行——每一章的价值都在此体现。

那么,接下来该去哪里?

后记

整个项目大约 750 行 Python 代码,没有任何框架。nanocode.py 是你的了,想怎么用就怎么用:

  • Git 集成,在测试通过后自动提交
  • 基于截图的调试,用于前端工作(Claude 能读取图片)
  • 通过 Whisper 实现语音输入,让你可以说话代替打字
  • 用 MCP 连接团队已在使用的外部服务
  • 派生对话、并行处理子任务的子智能体

Claude Code、Cursor、Copilot 这类生产级智能体能做的比这更多:流式响应(参见附录 A)、并行工具执行、tree-sitter 解析、沙盒执行环境、跨越数千个文件的多文件上下文窗口。750 行和 750,000 行之间的差距是真实存在的。但架构是一样的:一个大脑、一个循环、工具、记忆,以及一套安全约束机制。现在你知道幕后是什么了。

模型会持续进步。而那套保障机制——循环、工具、安全检查——那部分是工程问题,它不会消失。