Claude3.5 打造带道具的创意贪吃蛇
之前实现的贪吃蛇过于简单了些,只有简单的移动和失败判定,不够好玩。于是想着增加一些道具系统,可以给游戏增加更多乐趣。
游戏体验地址:在线创意贪吃蛇
如果你有更好的玩法创意,欢迎在评论区留言。
贪吃蛇道具系统
我的贪吃蛇游戏之前有个个初始的版本,最初的需求很简单,想在这个基础上继续优化。简化游戏中的食物系统,只保留苹果,并添加一个道具系统。提示词:
继续完善我的贪吃蛇游戏:
- 只保留一个水果苹果,取消其他水果。
- 设计一个道具物品系统,支持增加不同的道具以及功能。
- 支持穿障碍物道具,每隔 5s 随机掉落 1 个,在屏幕上出现 3 秒(这里时间最好是可以方便改)。吃到这个道具的话,每个道具可以穿越一次障碍物而不结束游戏。
于是 Claude 修改了部分代码,完成了下面功能:
- 添加了道具系统相关的常量配置
- 添加了道具状态管理和生成逻辑
- 修改了碰撞检测逻辑,支持使用穿墙道具
- 添加了道具的显示和计数器
- 每5秒生成一个道具,显示3秒后消失
- 吃到道具后增加穿墙次数,碰到墙时自动消耗一次穿墙能力
还告诉我可以通过调整 POWER_UP_CONFIG 中的值来改变道具生成间隔和显示时间。
以我对 Claude3.5 的了解,别看他回复的这么好,这么多改动点,和容易会引入 bug。毕竟,对于复杂的任务,Claude3.5 目前还是处理不是很好。
简单看了下代码,首先遗留的食物相关的代码没有删除干净。这个也是用 Cursor 这么久以来常见的问题,Claude 修改的时候,经常会忘记删除废弃的功能逻辑。
配合日志排查
此外,道具生成部分也不太对,生成间隔没生效。这里看了下代码和日志,应该是 generatePowerUp 生成道具的函数实现有问题,生成不了道具。
这里开始的时候,Claude3.5 给的方案是循环去随机生成,然后判断生成的位置之前有没有障碍物之类的。不过这个方法并不好,所以我直接告诉他一个更好的方案。提示词:
这里应该记录下所有空白格子位置,然后生成的时候,从空白格子自由选择
一些算法逻辑相关的部分,Claude3.5 生成后还是要人工重新看下,不然很容易有些啰嗦的实现。给出了具体实现的思路后,Claude3.5 很快给出了正确的代码,还总结了下这个实现的优点是:
- 不需要使用 do-while 循环反复尝试生成位置
- 确保道具一定会生成在有效的空白位置上
- 避免了无限循环的可能性
- 更高效,因为我们先收集了所有可用位置再随机选择
在排查上面的问题的时候,发现还有点问题。添加的 useEffect 处理部分的日志一直在打印:
console.log("isPlaying now", isPlaying);
这个 useEffect 用来设置道具生成相关的定时器,应该只在 isPlaying, generatePowerUp 变化才会输出。问了下 Claude3.5 ,这次一次性就定位到了问题。
这是因为 generatePowerUp 的依赖项导致这个函数在每次渲染时都被重新创建,从而触发 useEffect。
...// 省略代码实现
这里减少了 generatePowerUp 的依赖项,只保留 gridWidth 和 gridHeight,因为这些值在游戏过程中不会改变
其他状态(snake, food, obstacles, powerUp)会在函数执行时自动获取最新值,不需要作为依赖项
更新 UI 部分
其实 UI 部分是 Claude3.5 的强项,描述清楚想要什么,基本很快就能给出不错的代码。这里我想在设置部分增加道具的设置项,支持多选道具,默认现在前面的穿墙道具,后续可以支持更多道具。
Claude3.5 的改动还是可以的,主要分为下面几个方面:
- 定义了道具类型的配置结构,方便后续添加新道具
- 添加了道具启用状态管理
- 在设置面板中添加了道具选择区域
- 修改了道具生成逻辑,只生成已启用的道具
- 默认启用穿墙道具
- 支持通过复选框开启/关闭不同道具
最后还贴心的告诉我,需要在语言文件中添加新的翻译:
power_ups: "道具设置"
ghost_power: "穿墙能力"
增加新的道具
接着我想再增加一个道具,天降食物(其实也就是食物大爆发),这个道具每隔 10s 出现一次,然后也是过 5 秒小时。出现这个道具后,会随机出现大量苹果,然后苹果持续 5 秒。
Claude3.5 很快就给出了下面的一些改动:
- 添加了食物雨道具类型
- 添加了食物雨配置(食物数量和持续时间)
- 添加了生成食物雨的函数
- 修改了道具处理逻辑,支持食物雨道具
- 默认启用食物雨道具
这样,当蛇吃到食物雨道具时,会立即生成10个食物,这些食物会持续5秒,5秒后会恢复到正常的单个食物状态。
可能对 Claude3.5 还是有点过于复杂,生成的代码并不对。现在吃到食物雨道具之后,也没有生成很多水果啊,还是只有一个。
提示后,Claude 倒是很快找到问题了,并给出了解决方案。问题在于 generateFoodRain 函数中,我们每次生成新食物时都在覆盖之前的食物。让我们修改代码,维护一个食物数组。
- 添加 foodRain 状态来存储多个食物
- 修改 generateFoodRain 函数,一次性生成多个食物并存储在 foodRain 中
- 在 moveSnake 函数中添加对食物雨的检测
- 在渲染部分添加食物雨的显示
这样修改后,当蛇吃到食物雨道具时,会同时在地图上生成多个食物,蛇可以吃掉这些食物来增加分数。
其实这个改动并不好,因为多造了一个食物数组出来。其实更好的做法是,不要增加单独的食物雨,可以在原来的单个食物基础上改就行。所以在用 Claude3.5 的时候,还是要对代码质量把关,自己至少知道某个需求怎么改比较好,当 Claude 给出不够好的方案时,要能及时指出。
这里简单提示后,Claude3.5 也很快给出了正确的方案。主要改动:
- 将单个食物状态改为食物数组
- 修改食物生成逻辑,支持生成多个食物
- 修改碰撞检测逻辑,检查是否吃到任何食物
- 修改渲染逻辑,渲染所有食物
- 保持其他游戏逻辑不变
这样修改后,游戏正常时只有一个食物,吃到食物雨道具后会生成多个食物,食物雨持续5秒后恢复为单个食物 在食物雨期间吃到食物不会立即生成新的食物。
其实这里并没有一次改对,改完运行后,直蛇贪吃蛇和食物都不见了。我猜测代码中涉及到食物的地方还是很多的,Claude3.5 漏掉了部分。于是让它检查所有和食物相关的地方,都要支持数组的。
看来我对 Claude3.5 的丢三落四还是理解到位了,上面提示后就改对了。看看我食物大丰收状态下的贪吃蛇吧:
贪吃蛇金身不败
接着又增加了一个道具,金身不败,吃到这个道具后,蛇身体上加上金边,然后遇到障碍物就把障碍物消掉。道具作用持续 5 秒。开始是这样提示的,消掉障碍物的功能很快实现了。但是蛇加金边就实现的很垃圾。
Claude3.5 甚至重构了蛇的绘制部分,但是最后也没能很好的实现。
于是我就稍微变通了下,这样提示:
在 GOLDEN 道具持续时间内,蛇全身变成金黄色。
修改这里,判断当前金身状态,并设置 blue 或者 gold
金边难搞,我就让蛇变个色总可以吧。然后找到了蛇当前颜色部分,直接把代码也给它。这样一次就给出了完美的代码,现在看我们的金身不败蛇吧。
当然,Claude3.5 快,猛,糙的实现了这个创意贪吃蛇,不过还是有些缺点的。比如,目前还只能我简单玩几局,看看有没 bug。后面还可以让 Claude3.5 帮我写完整的测试用例,来验证下这里实现有没有问题。
此外 Claude3.5 生成的代码,里面不够优雅,可能会有一些重复啰嗦的部分,和人用心写的还是有差距。