
最近我在试着让 AI 助手接管一部分游戏开发工作主角是 Grok Bot项目语言选了仓颉。项目不大一个经典打砖块但就是这个看似简单的项目让我对“AI 编程”有了完全不一样的理解。我原本以为难点在于提示词写得好不好、代码生成得顺不顺实际跑完一遍才发现真正卡住进度的不是 AI 写不出代码而是我有没有想清楚每一行代码、每一个设计决定到底谁来拍板。如果你也想用类似的方式让 AI 帮你写游戏或者其他小型项目这篇文章应该能帮你省掉不少弯路。我尽量把我踩过的坑、总结的流程、以及最后沉淀下来的一套“拍板机制”讲透。1. 动手之前把“谁拍板”这件事想清楚1.1 为什么 AI 能写代码却仍然需要你盯着先说一个很多人容易产生的错觉AI 助手既然能生成看起来没什么毛病的代码那我只需要不断提出需求AI 写、AI 改、AI 跑通不就完事了吗我在项目里试过这种“放养模式”结果非常真实AI 确实能在几十秒内给我一段结构完整的打砖块代码但它对“游戏应该好玩”这件事完全没有概念也根本不会发现自己写的碰撞逻辑在某些情况下会让球直接穿模。AI 编码助手的本质是一个基于海量代码学习出来的模式生成器。它能写出平均水平的代码却不知道你的项目为什么存在。放在团队里类比Grok Bot 就像一个手脚很快、态度很好、但完全不了解业务背景的实习生你让它查资料、写模板、补测试它干得飞快你把整个项目的技术方向丢给它它也能给你一个听上去很合理的方案但那个方案极有可能带偏你的项目。这个阶段我意识到AI 写代码最大的风险不是它写得不好而是它会让开发者失去判断力。人一旦开始觉得“AI 说的应该没错”项目就会开始朝着随机方向漂移。漂移的前期你甚至察觉不到因为单看每一段代码都挺合理。1.2 我给 AI 助手定的边界能干活不决策所以我在项目启动前给自己立了一条规矩后来也成了整个项目能顺利跑通的关键Grok Bot 是执行者不是决策者。它可以提建议、给方案、写代码、改 bug但任何涉及游戏设计的取舍、技术路线的选择、代码质量和性能的验收都必须由我来拍板。这个“拍板”分三个层面缺一不可需求层玩家要的是什么手感、游戏难度曲线怎么定、哪些功能先做哪些砍掉这些只能由人决定。技术层用不用某个库、代码怎么分层、数据结构和接口怎么设计AI 可以给选项但最终选哪条路人必须拍板。验收层AI 说“代码写完了”不算数必须由人通过手动试玩、边界测试、代码审查来确认它真的满足要求。听起来像是给自己找麻烦毕竟用 AI 的目的就是省事。但实际上把拍板权牢牢握在自己手里反而让 AI 的产出效率更高。因为 AI 不需要思考它会严格按照你给出的规则来执行你给它的规则越清晰它一次写对的概率越高。后面整套流程其实都是在围绕“如何让人更好地拍板、让 AI 更好地执行”来搭的。2. 环境准备让 AI 助手在仓颉项目里“上岗”2.1 项目初始化与工具链配置这个项目的目标语言是仓颉。选它没有特别复杂的原因主要是我想在一门语法严谨、类型系统比较强的语言里做游戏看看 AI 在面对强类型约束时表现如何。结果证明强类型语言反而帮了大忙——很多 AI 爱犯的“类型糊弄学”错误在编译期就被直接拦下来了。环境配置本身不复杂。我先是安装了仓颉的开发者工具链用命令行初始化了一个新的项目目录。仓颉的工程结构默认把源码放在src目录下测试放在tests目录里。我顺便建了三个额外的目录docs放决策记录prompts放我写给 AI 的提示词存档scripts放构建和运行脚本。然后是版本管理。我在项目根目录初始化了 Git 仓库每完成一个模块、每稳定运行一次就做一次提交。这个动作后来成了我最大的安全网。Grok Bot 改代码改出问题的时候一句“git reset 回到上一个可用版本”能省下好几个小时。靠记忆去撤销 AI 的改动是不可靠的AI 可能连续改了好几轮每一步都不提醒你它改了什么。提示无论你用什么 AI 编码助手版本管理都是你拍板的底气。没有版本管理你不敢对 AI 说“这段不行重写”因为你怕它越改越乱最后没法还原。2.2 给 Grok Bot 写“上岗说明”这一步是我觉得整个项目里最值得分享的经验在开始写代码之前我先写了一份项目约定文档然后在每轮对话开始时把这份文档原样发给 AI。这份文档不长但每一条都是针对 AI 的工作方式设计的。我总结下来大概有六条语言版本和构建命令必须使用我给的固定命令不许假设环境。除标准库外禁止引入任何未经我确认的第三方依赖。所有常量不要散落在代码里统一放到一个配置区。公共接口必须使用我定义的结构体不允许自行发明新结构。每个函数必须写清输入输出禁止出现无返回值的“副作用流式”写法。生成代码的同时必须给出一段简要说明解释它的设计思路方便我来审查。写这份文档的动机很直接AI 没有偏好你给它什么规则它就遵守什么规则你没有给的维度它就会开始自由发挥。自由发挥对于一个需要维护的项目来说通常不是惊喜而是惊吓。我试过在没给规则的情况下让 AI 写一个简单的计分模块它给我写了一个带继承体系的计分类还引入了两个外部包理由是“这样扩展性更好”。听起来很有道理但对一个打砖块小游戏来说这就是纯粹的过度设计。另外我还建立了一个docs/decisions.md专门记录每次经过人拍板后定下来的设计决定。比如“球的碰撞只检测矩形相交不检测像素级碰撞”“难度曲线从第 10 块砖开始提升”等等。这些记录既给我自己看也给 AI 看——每次开新会话我都会把前沿的决策记录贴给它让它保持和之前工作的一致性。3. 游戏开发实战从 AI 写出行代码到能跑的 Demo3.1 需求拆解把游戏拆成 AI 能“一口吃下”的小任务项目敲定后我没让 Grok Bot 一次性生成整个游戏而是手动把游戏拆成了六个小模块窗口管理和游戏主循环挡板对象与键盘控制球的运动与反弹砖块阵列的生成与碰撞计分和游戏状态管理音效占位和 UI 文本不拆不知道一拆就发现每小块单独交给 AI 写准确率比整包生成高太多了。整包生成的问题在于AI 必须同时维护一大堆彼此相关的状态它的短期记忆根本扛不住经常前面写了一个变量名后面就换了个名字或者同一个功能写了两遍。拆成小块之后我给 Grok Bot 的提示词也模式化了固定四段目标这个模块负责什么功能输入输出提供什么数据、需要返回什么结构技术约束只能用哪些语法特性和数据结构验收标准怎样算写完具体跑什么操作能验证举个例子让 AI 写挡板移动逻辑时我的提示词大概是这样的目标实现挡板的左右移动并用键盘方向键控制。 输入键盘按键状态包含左键和右键的按下标记。 输出更新后的挡板位置坐标单位是像素。 技术约束不要引入额外库使用项目中定义好的 Paddle 结构体每次移动量用固定常量 MOVE_STEP 8。 验收标准按住左键时挡板向左移动松开停止按住右键时向右移动挡板不能移出窗口边界。AI 对这个提示词的响应质量很高一次就写对了。后面我发现凡是我在提示词里写明“验收标准”的任务AI 的完成度都明显更好。它虽然不会自己跑游戏但它在生成代码时会更注意边界条件因为它的训练数据里包含了大量“带测试要求的代码”。3.2 核心逻辑实现球的反弹与挡板控制的决策点这个游戏里最核心、也最容易出 bug 的地方就是球和挡板的碰撞反弹逻辑。我把这个任务单独拎出来让 AI 先给一个实现再经由我来拍板修正。AI 最初生成的逻辑很典型判断球和挡板的矩形是否相交如果相交就把球的垂直速度反向。乍一看没问题实际跑起来问题一堆球从挡板侧面撞过来时也会被弹上去球速很快时会出现“相交检测偶尔失效”的穿透现象更别提球撞到挡板不同位置时应该有不同的反弹角度AI 完全没处理。我把 AI 的实现和实际试玩结果放在一起做了一个简单的对比场景AI 最初版本的表现期望的正确表现球从挡板正上方落下正常反弹正常反弹球从挡板侧面撞入被弹回上方手感诡异应该按侧面碰撞处理向另一侧弹走球高速接近挡板偶尔直接穿过去任何时候都不应该穿过挡板球撞到挡板最左端反弹角度和中间一样应该向左侧偏移角度反弹这个对比就是典型的拍板素材。我拿着表格里这几条对 Grok Bot 说得很直接“不要用你现在这个方案按我的规则改挡板视作左、中、右三段球撞到不同段位时给一个对应的偏移角度碰撞检测使用球心到矩形的最近点距离来判断避免穿透。”AI 接收到这种明确的指令后很快就改好了。修正后的核心代码大概长这样我按仓颉的语法风格做了简化示意func computeBounce(ball: Ball, paddle: Paddle) - Float64 { let hitPos (ball.x - paddle.x) / paddle.width // hitPos 范围控制在 -1.0 到 1.0 let clamped Math.clamp(hitPos, -1.0, 1.0) // 用命中位置决定反弹角度越靠近边缘角度越大 return clamped * MAX_BOUNCE_ANGLE }这段逻辑其实就是业内做打砖块类游戏很常见的方案但 AI 不会主动给你写出来因为它默认会走“最安全、最简单、看起来正确”的路线。你想让游戏好玩、手感和别人不一样你就必须在这些关键决策点上亲自接管。3.3 把 AI 的碎片代码拼进完整的游戏循环模块独立生成时都很顺利但拼接的时候问题就来了这也是团队协作里常见的“接口对齐”问题只不过对象从人换成了 AI。AI 在写球模块时给球的坐标定义了一个ball.posX和ball.posY写挡板模块时给挡板中心点定义成了paddle.x和paddle.y。单独看没问题但当我让 AI 把两个模块整合时它就开始犯晕一会儿用posX一会儿用x编译直接报错。这里我必须拍板而且拍得很具体所有游戏对象统一用中心点坐标字段名统一叫x和y禁止再出现posX这种变体。我定义了一个公共的结构体模板让所有后续模块都按这个来。因为仓颉的静态类型系统在编译期就能抓出字段名不匹配的问题我在拼接阶段省了不少心。每次运行报错我就把错误信息原样贴回给 AI让 AI 自己对照我的统一结构体修正。大部分时候它都能改对但改完之后我一定会重新跑一遍游戏确认没有引入新的问题。拼接工作其实非常琐碎AI 在这一步的价值反而没有前面那么大。因为这里最需要的是对“整个项目现状”的全局理解和一致性管理而这恰恰是 AI 助手短期内最薄弱的地方。我的经验是不要把拼接工作交给 AI 一气呵成而是让它提供拼接建议你来决定其中一个然后一小段一小段地合入项目。4. 拍板机制测试、审查与回滚的实操方法4.1 验收标准能跑不算完边界情况才是分水岭很多 AI 编程项目给人“看起来很厉害”的感觉是因为它们只停留在“Demo 能跑”的阶段。跑起来确实能证明代码没有低级错误但根本不能证明游戏逻辑的正确性。我把验收分成了三层每一层都必须过了才允许进到下一阶段。第一层是编译层。仓颉的编译器帮我把守着类型错误、未定义变量、调用参数不匹配等大部分机械性问题。编译通过说明 AI 的代码没有被语法层面的低级错误击穿。第二层是手动试玩层。我会扮演玩家把游戏操作一遍重点检查几个固定场景挡板贴到最左边时球撞过来会怎样、球连续快速击打同一块砖会怎样、所有砖块清空后游戏是否进入胜利流程、重新开局时球是否回到初始位置。这一层出现的 bug 是最多的因为 AI 生成代码时根本不会主动考虑“玩家乱按一通”的场景。第三层是边界测试层。我会写几个小的断言来验证核心公式比如球的反弹角度是否在预期范围内、球碰撞砖块后的消失状态是否正确、计分是否按照砖块类型累加。写测试这段 AI 倒是很积极我把测试目标给它它三分钟内就能生成一版能跑的单元测试代码我再人工确认一遍断言的合理性。注意AI 生成的测试容易乐观它倾向于验证“正常情况”忽略异常输入。我在审查测试时会刻意往测试用例里塞边界值和非法值比如球速跑到极大时反弹计算会不会出现 NaN。4.2 代码审查AI 代码的三个高发问题就算测试全过我仍然会在合并前做一次人工审查。AI 写的代码和人类新手写的代码有一个共同点能跑和能维护是两码事。整理下来AI 代码的高发问题就是这三种第一是硬编码幽灵。AI 会把大量阈值、尺寸、速度直接写进具体的运算表达式比如if ball.y 540。它不会主动告诉你这个540是什么也不会去引用你定义的窗口高度常量。我要求 AI 把这些数字全部提取为命名常量替换后重新验证没有改变行为。第二是防御过度。我给 AI 提了一句“球的反弹要稳定”它就开始在反弹逻辑里加了一堆特判和兜底分支代码量膨胀了三倍行为却没有本质变化。这种防御式写法会让项目变得很难读看起来它很严谨实际上只是到处打补丁。我会在审查时删掉那些没有对应测试场景的分支让代码回到一个清晰的结构。第三是自作主张的结构设计。AI 非常喜欢在一开始就建抽象层、接口、继承体系。它对“扩展性”的执念远高于对“当前功能正确”的执念。而我的观点很明确小游戏项目在跑通之前最重要的是逻辑简单、方便改动。所以我定的拍板规则是基础版本一律用平铺结构禁止抽象类和接口继承所有模块通过公开函数直接调用同一个模块内部的函数不许超过三个层级。审查完成之后我会在decisions.md里记录一次审查结论同时把改动提交到 Git。这个流程坚持下来项目到后期几乎没有出现过“改一处坏一片”的情况。4.3 回滚与快照敢于说“这段不要了”AI 编码还有一个特性它可以非常轻松地否定你自己刚刚确认过的方案。你让它改一个弹速度参数它可能顺手把挡板移动逻辑也重构了一遍然后告诉你“顺手优化了一下”。这种“顺手优化”我基本都直接拒绝。这个态度对我保住进度非常重要。设定也简单每一阶段稳定运行后立刻打一个 Git 标签tag标记为可用版本。AI 后续的任何修改只能在这个标签上做增量如果增量出现无法立刻解决的问题我直接回到上一个标签重来而不是让 AI 在错误代码上继续修修补补。有一次我让 AI 尝试给游戏加上“变速球”机制结果球速一快碰撞检测又开始穿透。AI 修了三轮每次都是修复一个穿透场景、引入另一个场景的偏差。到第三轮我直接叫停回到没有变速球的标签重新以“碰撞检测加强”为目标让 AI 去改。一天之后变速球机制在一套新的碰撞检测逻辑上顺利加回来了。敢于说“这段不要了”是一种很重要的项目管理能力在 AI 参与开发的语境下尤其关键。因为 AI 没有心疼自己成果的情绪它不会因为你的回滚而沮丧重新生成一版代码对它来说成本极低。反而是人对已投入时间的执着会迫使人去挽救一条不值得挽救的代码线。5. 常见问题与排查技巧实录5.1 AI 幻觉它写了一个不存在的接口项目进行到中段时AI 给砖块生成模块加了一个它自己发明的函数名字叫randomPlaceBricks注释里还写着“按随机位置生成砖块阵列”。我一看就知道问题大了首先游戏的砖块阵列应该是整齐排布的不是随机撒的其次这个函数名看起来像是从某个框架的 API 里摘出来的但我查遍了当前语言的标准库根本不存在这么个接口。这类问题在 AI 编程里太常见了我甚至给它起了个名字叫 AI 幻觉接口。AI 会在你的需求和你使用的技术栈之间自行填补空白生成一些听起来很顺嘴、但实际上不存在的函数。排查方法其实很简单编译阶段报undefined错误时别急着把错误直接丢回给 AI先自己去确认一下是不是它调用了一个不存在的接口如果是直接删掉同时换个思路让 AI 重新实现。我的处理方式是在提示词里反复强调“只能使用你确认过的库和接口”并且在每次编译报错时让 AI 给出它引用的外部函数出自哪个库我可以快速核对。如果它说不出来处这个回答本来就不该被信任。5.2 上下文遗忘长对话之后 AI 开始“胡来”Grok Bot 在一个很长的会话里越到后面越容易忘记项目规则。它可能在前面几十轮回答里都严格使用Paddle结构体结果到后面某一轮突然改成了PaddleObj还会振振有词地解释“这样命名更符合面向对象风格”。这不是它变笨了而是它的注意力窗口有限早期的约定被挤掉了。要解决这个问题我给自己定了一个交互纪律一个会话只专注一件任务。比如会话 A 专门做挡板移动会话 B 专门做球反弹会话 C 专门做砖块阵列。每次开新会话第一句话就把AGENTS.md项目约定文档重新贴一遍再贴一遍当前的接口定义摘要最后才开始提任务。这样做之后AI 的“失忆”现象大幅减少。偶尔还会忘但我只需要在它偏离规则时回一句“按 AGENTS.md 里的约定重做”它就会纠正回来。这个“回贴规则”的操作虽然看着笨拙但效果非常稳定。5.3 性能与结构AI 的“能用”和你的“好维护”是两码事最后聊一个很容易在 AI 编程项目里被忽视的问题性能。我的打砖块游戏逻辑简单CPU 完全不是瓶颈但 AI 仍然有一种把简单逻辑写复杂的倾向。比如它会用遍历所有砖块来检测碰撞虽然砖块数量只有几十个这种写法完全可行但我更倾向于先做一个简单的空间分区思路来减少无谓判断哪怕只分成上、中、下三块区域也能明显减少碰撞检测次数。AI 生成代码时很少考虑性能边界因为它没有运行环境看不到卡顿。所以凡是和性能相关的优化我都是先自己试玩观察、再用调试工具分析热点最后把明确的问题丢给 AI 去针对性修改。实验下来这样比让 AI 提前“优化”要靠谱得多——AI 在没有明确瓶颈信号时做的优化本质上只是让代码变得更复杂。结构和性能这两个问题背后其实是同一个拍板原则AI 擅长的是在给定的优化目标下快速产出代码而不是判断哪里需要优化。决定优化时机和优化目标始终是开发者本人的核心工作。整个项目做下来我的一个总体感受是Grok Bot 确实能把开发速度拉快一大截但这种提速不是“甩手掌柜式”的而是一个需要更克制、更精细管理的协作过程。它像一台马力很强的发动机方向盘还是得攥在自己手里。后来我又用同样的流程做了第二个小项目有了这套拍板机制打底进度明显顺畅很多。希望这篇实践记录也能让你在准备把 AI 放进自己项目里时多想一分钟谁负责干活谁来拍板。