---
title: Claude3.5 打造带道具的创意贪吃蛇
date: '2024-11-05 18:00:00'
tags: ['claude']
keywords: ['Claude3.5 辅助前端', '创意贪吃蛇', '在线贪吃蛇']
description: 用 Claude3.5 实现一个好玩的贪吃蛇游戏，加入了道具系统，支持各种有意思的创意道具。本文会记录是用 Cursor 完成这个创意贪吃蛇的整个过程，一起来看我如何更好的利用 AI 解决复杂问题。
---

之前实现的贪吃蛇过于简单了些，只有简单的移动和失败判定，不够好玩。于是想着增加一些道具系统，可以给游戏增加更多乐趣。

![贪吃蛇道具系统](https://slefboot-1251736664.file.myqcloud.com/20241104_ai_gallery_snake_blog.png)

游戏体验地址：[在线创意贪吃蛇](https://gallery.selfboot.cn/zh/games/snake)

如果你有更好的玩法创意，欢迎在评论区留言。

## 贪吃蛇道具系统

我的贪吃蛇游戏之前有个个初始的版本，最初的需求很简单，想在这个基础上继续优化。简化游戏中的食物系统，只保留苹果，并添加一个道具系统。提示词：

> 继续完善我的贪吃蛇游戏：
> 
> 1. 只保留一个水果苹果，取消其他水果。
> 2. 设计一个道具物品系统，支持增加不同的道具以及功能。
> 3. 支持穿障碍物道具，每隔 5s 随机掉落 1 个，在屏幕上出现 3 秒（这里时间最好是可以方便改）。吃到这个道具的话，每个道具可以穿越一次障碍物而不结束游戏。

于是 Claude 修改了部分代码，完成了下面功能：

1. 添加了道具系统相关的常量配置
2. 添加了道具状态管理和生成逻辑
3. 修改了碰撞检测逻辑，支持使用穿墙道具
4. 添加了道具的显示和计数器
5. 每5秒生成一个道具，显示3秒后消失
6. 吃到道具后增加穿墙次数，碰到墙时自动消耗一次穿墙能力

还告诉我可以通过调整 POWER_UP_CONFIG 中的值来改变道具生成间隔和显示时间。

以我对 Claude3.5 的了解，**别看他回复的这么好，这么多改动点，和容易会引入 bug**。毕竟，对于复杂的任务，Claude3.5 目前还是处理不是很好。

简单看了下代码，首先遗留的食物相关的代码没有删除干净。这个也是用 Cursor 这么久以来常见的问题，**Claude 修改的时候，经常会忘记删除废弃的功能逻辑**。 

## 配合日志排查

此外，道具生成部分也不太对，生成间隔没生效。这里看了下代码和日志，应该是 generatePowerUp 生成道具的函数实现有问题，生成不了道具。

这里开始的时候，Claude3.5 给的方案是循环去随机生成，然后判断生成的位置之前有没有障碍物之类的。不过这个方法并不好，所以我直接告诉他一个更好的方案。提示词：

> 这里应该记录下所有空白格子位置，然后生成的时候，从空白格子自由选择

**一些算法逻辑相关的部分，Claude3.5 生成后还是要人工重新看下，不然很容易有些啰嗦的实现**。给出了具体实现的思路后，Claude3.5 很快给出了正确的代码，还总结了下这个实现的优点是：

1. 不需要使用 do-while 循环反复尝试生成位置
2. 确保道具一定会生成在有效的空白位置上
3. 避免了无限循环的可能性
4. 更高效，因为我们先收集了所有可用位置再随机选择

在排查上面的问题的时候，发现还有点问题。添加的 useEffect 处理部分的日志一直在打印：

```js
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 的改动还是可以的，主要分为下面几个方面：

1. 定义了道具类型的配置结构，方便后续添加新道具
2. 添加了道具启用状态管理
3. 在设置面板中添加了道具选择区域
4. 修改了道具生成逻辑，只生成已启用的道具
5. 默认启用穿墙道具
6. 支持通过复选框开启/关闭不同道具

最后还贴心的告诉我，需要在语言文件中添加新的翻译：

```json
power_ups: "道具设置"
ghost_power: "穿墙能力"
```

## 增加新的道具

接着我想再增加一个道具，天降食物（其实也就是食物大爆发），这个道具每隔 10s 出现一次，然后也是过 5 秒小时。出现这个道具后，会随机出现大量苹果，然后苹果持续 5 秒。

Claude3.5 很快就给出了下面的一些改动：

1. 添加了食物雨道具类型
2. 添加了食物雨配置（食物数量和持续时间）
3. 添加了生成食物雨的函数
4. 修改了道具处理逻辑，支持食物雨道具
5. 默认启用食物雨道具

这样，当蛇吃到食物雨道具时，会立即生成10个食物，这些食物会持续5秒，5秒后会恢复到正常的单个食物状态。

可能对 Claude3.5 还是有点过于复杂，生成的代码并不对。现在吃到食物雨道具之后，也没有生成很多水果啊，还是只有一个。

提示后，Claude 倒是很快找到问题了，并给出了解决方案。问题在于 generateFoodRain 函数中，**我们每次生成新食物时都在覆盖之前的食物。让我们修改代码，维护一个食物数组**。

- 添加 foodRain 状态来存储多个食物
- 修改 generateFoodRain 函数，一次性生成多个食物并存储在 foodRain 中
- 在 moveSnake 函数中添加对食物雨的检测
- 在渲染部分添加食物雨的显示

这样修改后，当蛇吃到食物雨道具时，会同时在地图上生成多个食物，蛇可以吃掉这些食物来增加分数。

其实这个改动并不好，因为多造了一个食物数组出来。其实更好的做法是，不要增加单独的食物雨，可以在原来的单个食物基础上改就行。**所以在用 Claude3.5 的时候，还是要对代码质量把关，自己至少知道某个需求怎么改比较好，当 Claude 给出不够好的方案时，要能及时指出**。

这里简单提示后，Claude3.5 也很快给出了正确的方案。主要改动：

- 将单个食物状态改为食物数组
- 修改食物生成逻辑，支持生成多个食物
- 修改碰撞检测逻辑，检查是否吃到任何食物
- 修改渲染逻辑，渲染所有食物
- 保持其他游戏逻辑不变

这样修改后，游戏正常时只有一个食物，吃到食物雨道具后会生成多个食物，食物雨持续5秒后恢复为单个食物
在食物雨期间吃到食物不会立即生成新的食物。

其实这里并没有一次改对，改完运行后，直蛇贪吃蛇和食物都不见了。**我猜测代码中涉及到食物的地方还是很多的，Claude3.5 漏掉了部分**。于是让它**检查所有和食物相关的地方，都要支持数组的**。

看来我对 Claude3.5 的丢三落四还是理解到位了，上面提示后就改对了。看看我食物大丰收状态下的贪吃蛇吧：

![贪吃蛇金身不败了](https://slefboot-1251736664.file.myqcloud.com/20241104_ai_gallery_snake_apples.png)

## 贪吃蛇金身不败

接着又增加了一个道具，金身不败，吃到这个道具后，蛇身体上加上金边，然后遇到障碍物就把障碍物消掉。道具作用持续 5 秒。开始是这样提示的，消掉障碍物的功能很快实现了。但是蛇加金边就实现的很垃圾。

Claude3.5 甚至重构了蛇的绘制部分，但是最后也没能很好的实现。

于是我就稍微变通了下，这样提示：

> 在 GOLDEN 道具持续时间内，蛇全身变成金黄色。
> 
> 修改这里，判断当前金身状态，并设置 blue 或者 gold

金边难搞，我就让蛇变个色总可以吧。然后找到了蛇当前颜色部分，直接把代码也给它。这样一次就给出了完美的代码，现在看我们的金身不败蛇吧。

![贪吃蛇金身不败了](https://slefboot-1251736664.file.myqcloud.com/20241104_ai_gallery_snake_golden.png)

当然，Claude3.5 快，猛，糙的实现了这个创意贪吃蛇，不过还是有些缺点的。比如，目前还只能我简单玩几局，看看有没 bug。后面还可以让 Claude3.5 帮我写完整的测试用例，来验证下这里实现有没有问题。

此外 Claude3.5 生成的代码，里面不够优雅，可能会有一些重复啰嗦的部分，和人用心写的还是有差距。