| 项目 | 内容 |
|---|---|
| 这个作业属于哪个课程 | https://edu.cnblogs.com/campus/fzu/2026-01SoftwareEngineeringandSoftwareEngineeringPractice?page=4 |
| 这个作业要求在哪里 | https://edu.cnblogs.com/campus/fzu/2026-01SoftwareEngineeringandSoftwareEngineeringPractice/homework/16718 |
| 这个作业的目标 | 使用 Python 和 AIGC 完成“一箭又一箭”小游戏 |
| 学号 | 102401303 |
| GitHub 仓库 | https://github.com/cheng0673/arrow-game-cz |
一、项目展示(ง •̀_•́)ง:
开始界面

游戏过程

通关界面

失败界面(有个小彩蛋在此!)

二、项目介绍=ᗜωᗜ=:
2.1游戏规则:
我将用最直白、最不绕弯子、最一针见血的告诉你:点箭头,让它飞出去,飞出去就消失,全部消失就赢!
2.2界面设计小巧思💡:
整体风格走的是童趣+糖果色 + 圆角 + 果冻质感 路线,每个箭头上面还有可爱的小表情,而且箭头碰撞会变成哭哭(╥_╥)/的表情哦(就是上面说的小彩蛋,全是细节吧!)。同时背景设计了一个10s为一个循环的日夜更替,保证页面动态,点击开始游戏后会有主题风格选择,同时每个关卡还有不同难度等级设计,各位玩家还可以根据实际情况选择是否挑战“限时模式”,考验手速的时候到了!迎难而上!挑战自己吧!


2.3功能与特色:
1.有许多通关玩法,你可以选择正常闯关、限时挑战、随机关卡,同时设计了异形关卡,可以多换换口味,比如下面这个苹果、葡萄关卡


2.同时增加了连击加分机制,让玩家在游戏中挑战更高分,如果不小心走错了也没关系,可以撤销上一步,世上可能没有后悔药,但在我这里有嘿嘿嘿,详细呈现大家可以看下方演示

3.为了满足我个人的换装喜好,我还设计了一个对四方向箭头颜色以及表情的游戏设计界,快来设计属于你的专属闯关页面吧啊哈哈哈,总有一款表情和颜色属于你,如果没有那我再加、、同时在这个界面也可以通过滑动条调整游戏音量~ദ്ദിˊᗜˋ)

4.那就有人问了,玩到一半不小心关闭了怎么办?不用担心!为此我特意设计了游戏进度保存功能,关卡会保留在你上次运行的进度,再也不用担心一朝回到解放前,从新手村重新开始惹₍^ >ヮ<^₎ .ᐟ.ᐟ


三、实现思路:
3.1箭头和方向表示
3.1.1方向——Direction 枚举
model.py#L18-L33 中定义了四个方向,每个方向用(dr, dc)`位移量表示:
| 方向 | 枚举值 | dr(行位移) | dc(列位移) | 字符 |
|---|---|---|---|---|
| 上 | Direction.UP |
-1 | 0 | ↑ |
| 下 | Direction.DOWN |
+1 | 0 | ↓ |
| 左 | Direction.LEFT |
0 | -1 | ← |
| 右 | Direction.RIGHT |
0 | +1 | → |
3.1.2箭头——ArrowSpec三元组
一支箭头就是(r, c, d) 三个值——它在第 r 行第 c 列,朝 d 方向射。
ArrowSpec = tuple[int, int, Direction] # (行号 r, 列号 c, 方向 d)
3.2关卡——dict字典
3.2.1像素画棋盘
levels.py#L405-L420 定义了 14 色调色板,用字符代表颜色,例如苹果图案的顶部几行:
.....bbb.......
....bgggb......
....ggg#.......
....####.......
其中b是棕色果柄、g是绿叶、#是红色果身(主体格,可放箭头)。_parse_mask()函数把这种字符图案解析成两个集合:cells(所有格子及其颜色,供渲染用)和playable。
3.2.2关卡生成——逆向构造
正向思维 :摆好箭头 → 检查能不能解 → 不能就重摆(暴力枚举,几乎不可能找到可解的密集关卡)。
**逆向思维 **:从空棋盘开始, 倒着放箭头 ——先放最后一个被消除的,再放倒数第二个……每放一个,只要保证它前方射线上没有已摆放的箭头,那么按放置的逆序点击就一定能通关!
for 每次尝试 (attempts=80):
occupied = 空集
placed = 空列表
for 要放 count 支箭:
1. 遍历所有 active 格子,找出"至少有一个方向射线畅通"的候选格
2. 对候选格的每个畅通方向,记录 blocked_by 值(该格被多少支箭挡着)
3. 「最深优先」策略:优先选被挡最多的格子(制造更紧密的依赖关系)
- 密度≥80%时放宽偏好(否则贪心必失败)
4. 随机选一个 (格子, 方向),放入 occupied 和 placed
5. 更新该方向射线上所有格子的 blocked_by 计数
如果放满 count 支 → 记录为候选解,保留 blocked_by 总分最高的
如果全部失败 → 启用保底构造
3.3路经检测方法
3.3.1核心函数_ray_clear
def _ray_clear(occ, rows, cols, r, c, d):
"""(r,c) 朝 d 方向的射线上(不含自身)没有已占据格子。"""
nr, nc = r + d.dr, c + d.dc
while 0 <= nr < rows and 0 <= nc < cols:
if (nr, nc) in occ:
return False # 遇到阻挡,射不出去
nr += d.dr
nc += d.dc
return True # 一路走到棋盘边缘,畅通
执行过程 (以 → 方向为例):
棋盘: → · · ↓ · |
(0,0)(0,1)(0,2)(0,3)(0,4) 边缘
点击 (0,0) 的 →:
nr=0, nc=1 → 不在 occ 中,继续
nr=0, nc=2 → 不在 occ 中,继续
nr=0, nc=3 → (0,3) 在 occ 中(有↓箭头)→ return False ❌
-------------------------------------------------------
棋盘: → · · · · |
点击 (0,0) 的 →:
nr=0, nc=1 → 空,继续
nr=0, nc=2 → 空,继续
nr=0, nc=3 → 空,继续
nr=0, nc=4 → 空,继续
nr=0, nc=5 → 越界(nc >= cols)→ return True ✅ 畅通!
四、AIGC 使用过程:
本项目全程借助 Trae AI 辅助开发,覆盖代码编写、关卡设计、Bug 排查、测试用例编写与美术方案等环节。总体使用情况如下表:
| 子任务 | 借助何种 AIGC 技术 | AI 实现或提供了什么 | 效果如何 | 人工修改 |
|---|---|---|---|---|
| 游戏核心框架 | Trae AI | 生成 Pygame 主循环、场景状态机、按钮组件骨架 | 框架可运行,但场景切换逻辑有冗余 | 精简场景管理结构,统一事件处理入口 |
| 路径检测 | Trae AI | 实现四方向射线扫描 _ray_clear,沿 dr/dc 步进查阻挡 |
基本可用,异形棋盘装饰格被误判为阻挡 | 改为 occupied 集合只存箭头坐标,装饰格射线天然可穿过 |
| 关卡逆向构造 | Trae AI | 实现 reverse_generate_masked 逆向摆放 + 贪心选位 |
矩形棋盘正常;高密度困难关卡频繁生成失败 | 密度≥80%自动放宽贪心偏好,并补写保底构造算法 |
| 像素画图案设计 | Trae AI | 用 14 色调色板字符绘制 6 水果 + 6 动物图案 | 首版形状偏方块、猫兔面部出现空洞裂缝 | 多轮目检后重画:苹果改正圆、葡萄改果粒串、五官全部填满 |
| 主题选择流程 | Trae AI | 生成主题选择页、选关页、难度弹窗及卡片组件 | 流程跑通,但三主题存档键和解锁逻辑混在一起 | 拆分独立存档键,水果动物全解锁、默认顺序解锁 |
| 界面美化 | Trae AI | 生成糖果色渐变背景、果冻质感格子、圆角按钮 | 卡片底色不统一、标题副标题间距太近 | 三卡片统一白底,描述文字改黑色,全局拉开间距 |
| 难度分级与限时挑战 | Trae AI | 实现三档箭头数量控制及倒计时模式 | 高难度参数与生成器不匹配导致坏档 | 重新校准三档密度比例与目标箭头数阶梯 |
| 加载性能优化 | Trae AI | 降低 attempts、新增磁盘缓存 | 首次 0.4-2.3 秒,二次启动毫秒级 | 发现缓存无版本号,补加图案内容 hash 版本校验 |
| 存档系统 | Trae AI | 实现 JSON 序列化、继续/重置弹窗、旧存档迁移 | tuple 颜色键无法直接序列化 | 增加 cells/playable 字段转换,旧中途存档自动清理 |
| 测试与验证 | Trae AI | 编写 21 个单元测试及 36 关批量验证脚本 | 测试暴露出生成失败的隐藏 bug | 修复生成器后,36/36 关全部精准命中目标 |
下面选取 3 次最有代表性的 AIGC 使用过程详细展开。
代表性过程一:路径检测——游戏的「心脏」
我提出的要求:实现箭头点击后的路径判定——箭头朝上下左右四个方向射出,射线路径上没有其他箭头就能飞出棋盘消除,有阻挡则消除失败。
| 子任务 | 借助何种 AIGC 技术 | AI 实现或提供了什么 | 效果如何 | 人工修改 |
|---|---|---|---|---|
| 路径检测 | Trae AI | 生成四方向射线扫描函数,沿 dr/dc 位移逐格检查,并处理棋盘边界 | 矩形棋盘一切正常;但加入异形棋盘后,苹果叶子、兔子五官等装饰格被误判为阻挡,旁边的箭头飞不出去 | 让 AI 把判定依据改为「当前箭头坐标集合 occupied」——装饰格不放置箭头、不在集合中,射线天然可穿过;同一函数对矩形和异形棋盘通用 |
代表性过程二:像素画图案——AI 画的苹果,是一块方宝石
我提出的要求:水果按现实配色和形状画——以苹果为例,中间红色、上面棕色的杆和绿色的叶子,形状要圆;动物要更形象,兔子拉长耳朵、加上眼睛鼻子嘴巴,像像素画一样。
| 子任务 | 借助何种 AIGC 技术 | AI 实现或提供了什么 | 效果如何 | 人工修改 |
|---|---|---|---|---|
| 像素画图案设计 | Trae AI | 设计 14 色字符调色板(g 绿叶、b 棕柄、k 黑五官、p 粉内耳等)和图案解析器,并画出 12 个图案的第一版 | 框架思路清晰,但实机效果不理想:苹果是方的像红宝石、葡萄像洋葱、猫兔脸中间空了一条缝(胡须和嘴巴一行只画 3 格),一点不可爱 | 让 AI 把图案放大逐格截图给我看,逐一下令修改:苹果按真像素圆宽度规律重画;葡萄推翻重画三版定为「绿叶梗在上、3-2-1 层果粒垂挂」;猫兔五官全部替换满行格子保证面部实心 |
代表性过程三:36 关批量验证——测试抓出了「看不见的坏档」
我提出的要求:编写脚本一次性生成全部 36 个异形关卡(12 图案 × 3 难度),验证每关都能生成成功,且箭头数量符合难度预期。
| 子任务 | 借助何种 AIGC 技术 | AI 实现或提供了什么 | 效果如何 | 人工修改 |
|---|---|---|---|---|
| 测试与验证 | Trae AI | 编写批量生成与校验脚本,输出每关的目标箭头数与实际生成数 | 直接抓出大问题:草莓困难、西瓜困难两关全部生成失败,箭头数从 87/81 的目标回退到 49/46,比简单档还少;这种坏档靠手工试玩几乎不可能发现 | 与 AI 一起定位根因(贪心「最深优先」偏好在高密度棋盘钻牛角尖),确定方案:密度≥80% 自动放宽偏好,仍失败则启用保底构造算法;修复后重测 36/36 关全部精准命中目标箭头数 |
五、测试结果:
| 编号 | 测试内容 | 预期结果 | 实际结果 | 是否通过 |
|---|---|---|---|---|
| T01 | 点击前方无阻挡的箭头 | 箭头飞出棋盘并消失,剩余箭头数减 1 | 箭头沿方向飞出棋盘边缘并播放消除动画,剩余箭头数正确减 1 | ✅ 通过 |
| T02 | 点击前方有其他箭头阻挡的箭头 | 箭头不消失,失误次数减 1,播放碰撞反馈 | 箭头原地不动,失误次数减 1 并显示晃动碰撞效果 | ✅ 通过 |
| T03 | 点击位于棋盘边缘且朝向棋盘外的箭头 | 箭头正常消失,不发生数组越界错误 | 边缘箭头直接消除,无越界报错(边界条件已正确处理) | ✅ 通过 |
| T04 | 消除本关全部箭头 | 显示通关结算页,按步数与失误数给出 1-3 星评价 | 清空最后一支箭头后弹出结算页,星级按表现正确计算 | ✅ 通过 |
| T05 | 失误次数耗尽 / 倒计时归零 | 均正确判定失败,允许重新开始本关 | 失误 3 次、超时两种情况均弹出失败页,可点击重新开始 | ✅ 通过 |
| T06 | 点击异形棋盘装饰格(苹果叶子、兔子五官等) | 装饰格不放箭、不可点击,箭头射线可正常穿过装饰区域 | 装饰格无点击响应,射线穿叶/五官区域检测结果正确 | ✅ 通过 |
| T07 | 三主题解锁逻辑验证 | 默认主题顺序解锁(未通关灰显带锁),水果/动物 12 关全部解锁可自由选择 | 默认第 2 关起灰显带锁;水果/动物 6 关全彩色可点 | ✅ 通过 |
| T08 | 简单/中等/困难三档箭头数量验证 | 三档箭头密度依次递增(约 50%/70%/88%),且每档布局 100% 保证可解 | 三档箭头数实测递增,solve() 验证全部存在通关顺序 | ✅ 通过 |
| T09 | 36 个异形关卡批量生成验证 | 全部关卡精准命中目标箭头数、无一失败 | 修复前:草莓/西瓜困难档生成失败回退(49/46 支);修复后(高密度放宽贪心 + 保底构造):36/36 关全部精准命中 | ✅ 通过(修复后) |
| T10 | 关卡加载速度测试 | 首次生成 < 3 秒,二次启动毫秒级 | 优化前:10-20 秒/关;优化后(attempts 降至 80 + 磁盘缓存 + hash 版本校验):首次 0.4-2.3 秒,二次启动 < 5ms | ✅ 通过(优化后) |
六、PSP 表格:
| 任务 | 预估耗时(小时) | 实际耗时(小时) | 差异(小时) |
|---|---|---|---|
| 需求分析与游戏设计 | 2.0 | 3.0 | +1.0 |
| Python 与图形库学习 | 4.0 | 3.0 | -1.0 |
| 游戏界面实现 | 6.0 | 8.0 | +2.0 |
| 路径与碰撞逻辑实现 | 4.0 | 4.5 | +0.5 |
| 关卡设计 | 6.0 | 10.0 | +4.0 |
| AIGC 辅助开发 | 2.0 | 3.5 | +1.5 |
| 测试与修改 | 4.0 | 7.0 | +3.0 |
| README 与博客撰写 | 2.0 | 3.0 | +1.0 |
| 合计 | 30.0 | 42.0 | +12.0 |
差异说明(实际比预估多 12 小时,主要超支点):
- 关卡设计(+4h):12 个异形图案并非一次画成——苹果从「方块宝石」改到真像素圆、葡萄重画 3 版才定稿成串状果粒、猫兔面部空洞问题排查,逆向构造的保底算法也花了额外时间。
- 测试与修改(+3h):36 关批量验证暴露了草莓/西瓜困难档坏档问题,修复生成器后又做了全量回归;加载性能优化(磁盘缓存 + hash 版本号)也是计划外的工作量。
- 游戏界面实现(+2h):主题卡片白底统一、标题副标题间距、音量键位置反复调整了多轮,属于「看着不满意就得改」的视觉打磨。
节省的部分:Python/Pygame 基础语法比预想熟悉,且 AIGC 在样板代码(按钮组件、渲染循环)上提速明显,学习阶段少花了 1 小时。
七、心得体会:
AI 到底帮了我什么?
这次开发我全程都在跟 AI 结对编程,最大的感受是:它真的像一个傻但不知疲惫的搭档。
那些机械重复的活儿,它干得又快又好——按钮组件、场景切换、渲染循环,我描述清楚需求,它几秒钟就给我一版能跑的骨架。特别是写像素画棋盘的时候,我要的是 14 种颜色的字符系统,它不仅帮我把调色板和解析器写出来了,还顺带给每个水果、动物都画了第一版草图,让我在这个基础上改,比对着空白文件发呆强太多了。
当然,它也没少让我生气,它的第一版方案经常“看起来像那么回事,细一看全是问题”。
就说那个苹果,我明明想要圆滚滚的,它给我画了个方块宝石;葡萄更绝,第一版像个洋葱,第二版像个灯泡,(`Д´)我硬生生让它重画了三版才变成现在这串正经的葡萄。
所以说,AI 给的是起点,不是终点。
我自己的收获
这趟下来,收获远不止一个能跑的游戏:
技术上,我第一次完整走通了「需求 → 设计 → 实现 → 测试 → 迭代」的流程。逆向构造算法的思维方式让我特别受启发——正着解不了的难题,倒过来想居然豁然开朗。还有单元测试,以前总觉得写测试是负担,这次真的是测试帮我抓出了大 bug,从此对「21 个测试全绿」有了执念哈哈哈。
方法上,我学会了怎么跟 AI 高效合作:需求要描述得具体;它给的代码一定要跑、要看、要质疑;大改动之前先commit一次做个记录,防止后面跑歪了还能即使回退。最后我明白了,AI 时代最值钱的能力,是提问和判断,而不是打字。
最后
从一个方格子小游戏,到现在这个有三种主题、24 个关卡、还能看像素画的「糖果世界」,我玩着自己写的游戏通关的时候,是真的开心,而且这种cos产品经理压力ai的感觉好爽啊哈哈哈哈哈哈哈哈哈哈哈!(≖ᴗ≖✿)
谢谢 AI 这个嘴快但靠谱的搭档,也谢谢那个没有在它连苹果长啥样都不知道时选择「凑合交了」的自己。✧。٩(ˊᗜˋ)و✧*。
下一个项目,继续加油!
浙公网安备 33010602011771号