第二次软工作业
软件工程第二次个人作业 —— 「一箭又一箭」小游戏
| 项目 | 内容 |
|---|---|
| 这个作业属于哪个课程 | https://edu.cnblogs.com/campus/fzu/202601SofwareEngineering |
| 这个作业要求在哪里 | https://edu.cnblogs.com/campus/fzu/202601SofwareEngineering/homework/16717 |
| 这个作业的目标 | 使用 Python 和 AIGC 完成「一箭又一箭」小游戏 |
| 学号 | 102401330 |
| GitHub 仓库 | https://github.com/Gaoyypp/-2 |
一、项目展示
以下截图为我自行截取的游戏实际运行画面。
开始界面

游戏进行中(含剩余箭头、剩余失误、当前关卡)

碰撞反馈(箭头前顶弹回并变红)

通关 / 失败界面

二、项目介绍
游戏规则
「一箭又一箭」是一款点击式箭头解谜游戏:棋盘中散布着上、下、左、右四种方向的箭头,玩家需要观察箭头方向与相互阻挡关系,按合适顺序点击箭头,让所有箭头依次飞出棋盘。
- 点击某个箭头后,程序检查其前进方向到棋盘边界之间是否有其他箭头;
- 前方无阻挡:箭头飞出棋盘并消失;
- 前方有阻挡:箭头被挡住不能消除,播放「前顶弹回 + 变红」的碰撞反馈,并消耗一次失误机会;
- 消除当前关卡全部箭头即可进入下一关;
- 失误次数耗尽则本关失败,可重新开始。
界面设计
游戏采用深色主题,包含三个主要界面:
- 开始界面:游戏标题、规则说明与「开始游戏」按钮;
- 游戏界面:顶部信息条(当前关卡、剩余箭头数量、剩余失误次数、重新开始按钮)+ 居中棋盘;
- 结果界面:通关(下一关 / 返回菜单)与失败(重新开始 / 返回菜单)。
主要功能
- 上 / 下 / 左 / 右四种方向箭头,正确的阻挡与边界判断;
- 鼠标点击选择箭头,前方无阻挡时飞出动画、有阻挡时晃动变红;
- 失误次数显示与耗尽判定;
- 4 个可正常通关的关卡,通关 / 失败 / 重新开始流程完整;
- 附带自动化测试与关卡可通关性校验。
特色
- 逻辑与界面分离:核心路径检测、关卡求解独立成模块,可用
unittest自动化测试; - 关卡自动校验:内置求解器,保证每个关卡都存在合理通关顺序,避免「关卡无法通关」;
- 碰撞反馈明显:箭头向前一顶再弹回,同时由橙色变红。
三、实现思路
1. 箭头、方向与关卡的表示
箭头方向用一个「坐标增量」字典表示,U / D / L / R 分别对应上、下、左、右:
DIRECTIONS = {
"U": (-1, 0), # 行号减 1 => 向上
"D": (1, 0),
"L": (0, -1),
"R": (0, 1),
}
棋盘用一个二维字符网格表示,每个格子取 U / D / L / R 或 .(空格)。关卡数据直接写成等长字符串列表,直观易读:
Level(name="第 1 关", mistakes=5, grid=[
"..U..",
".....",
".U.R.",
".....",
"RR..D",
])
2. 路径检测(核心)
判断箭头能否飞出,本质是「沿方向逐格前进,看是否在到达边界前遇到其他箭头」:
def path_clear(self, r, c):
d = self.get(r, c)
dr, dc = DIRECTIONS[d]
nr, nc = r + dr, c + dc
while 0 <= nr < self.rows and 0 <= nc < self.cols: # 未出界则继续
if self.grid[nr][nc] != ".": # 遇到箭头 => 被阻挡
return False
nr += dr
nc += dc
return True # 走到边界外 => 可飞出
边界处理的关键在于循环条件 0 <= nr < self.rows and 0 <= nc < self.cols:只要还在棋盘内就继续检查,一旦越界循环结束,返回 True,因此边缘箭头朝外时不会发生数组越界。
3. 关卡可通关性(求解器)
一个关卡「存在合理通关顺序」当且仅当每一步都存在至少一个「前方无阻挡」的箭头。这里有一个关键性质:消除一个箭头只会减少障碍、不会新增障碍,因此「当前可飞出的箭头集合」随消除过程单调递增,贪心地反复消除任意可飞出箭头,一定等价于最优解。基于此写出的求解器既能自动判断关卡是否可通关,也能直接给出通关顺序,用于校验关卡数据。
4. 程序结构
| 文件 | 职责 |
|---|---|
core.py |
纯逻辑:棋盘、方向、路径检测、求解器(不依赖图形库) |
game.py |
会话层:关卡推进、失误次数、点击判定(同样可测) |
levels.py |
关卡数据 |
main.py |
pygame 界面:状态机、绘制、飞出 / 碰撞动画 |
test_game.py |
T01~T06 自动化测试 |
界面用状态机管理 MENU / PLAYING / LEVEL_CLEAR / ALL_CLEAR / FAILED 五种状态,飞出与碰撞分别用 FlyingArrow、ShakeEffect 两个动画对象实现,与逻辑层解耦。
四、AIGC 使用过程
本次开发全程借助 Claude Code 完成。以下记录 4 次有代表性的协作过程:
| 子任务 | 借助何种 AIGC 技术 | AI 实现或提供了什么 | 效果如何 | 人工修改 |
|---|---|---|---|---|
| 环境搭建 | Claude Code | 检测到 Python 3.14 下 pip install pygame 因缺少预编译 wheel、源码编译报错而失败,改用 pygame-ce(导入名仍为 pygame) |
一次安装成功,游戏正常导入 pygame | 确认 pygame-ce 与作业要求兼容后采纳 |
| 路径检测 | Claude Code | 生成四方向路径检测函数,用 while 沿方向逐格检测并处理边界 |
基本正确,边缘朝外箭头不越界 | 初版用下标直接访问,我补充了「越界返回空」的兜底,并统一为 path_clear 语义 |
| 关卡设计 | Claude Code | 生成关卡数组,并写了一个 solve() 求解器自动校验可通关性 |
第 4 关首次设计出现「两个箭头面对面互指」的死锁,求解器直接定位 | 根据求解器定位重新设计第 4 关,直至校验通过 |
| 碰撞动画 | Claude Code | 实现飞出动画与「前顶弹回 + 变色」的碰撞反馈 | 基本可用,反馈明显 | 调整动画时长与位移幅度,让碰撞更自然 |
说明:以上记录均来自本次真实开发过程(环境报错、求解器定位死锁等都有对应日志),并非项目完成后补写。
五、测试结果
采用自动化测试(python -m unittest test_game -v),共 8 个用例全部通过:
| 编号 | 测试内容 | 预期结果 | 实际结果 | 是否通过 |
|---|---|---|---|---|
| T01 | 点击前方无阻挡的箭头 | 箭头飞出棋盘并消失 | 箭头被消除,剩余数减 1 | ✅ |
| T02 | 点击前方有阻挡的箭头 | 箭头不消失,失误次数减 1 | 箭头仍在,mistakes_left 减 1 |
✅ |
| T03 | 点击边缘且朝外的箭头 | 正常消失,不发生越界 | 四个方向的边缘箭头均正常消除 | ✅ |
| T04 | 消除本关全部箭头 | 显示通关并进入下一关 | 逐关通关,最后一关 all_clear |
✅ |
| T05 | 失误次数耗尽 | 显示失败并允许重新开始 | mistakes_left 归 0,状态变 failed |
✅ |
| T06 | 游戏进行中重新开始 | 布局和失误次数恢复 | 棋盘与失误次数均复位 | ✅ |
此外还补充了两个关卡校验测试:所有关卡必须可通关、求解器给出的顺序每一步都必须合法。
六、心得体会
这次作业让我第一次完整地用 AIGC 工具「协同开发」一个小游戏,有几个明显的收获:
-
AI 大幅缩短了环境与样板代码的时间。pygame 在 Python 3.14 下装不上的坑,如果自己查可能要折腾很久,AI 直接给出了改用
pygame-ce的方案,一次解决。 -
AI 生成的代码必须经过验证,不能直接信任。最典型的是关卡设计——AI 第一次给的第 4 关其实存在「面对面互指」的死锁,根本无法通关。我自己写的
solve()求解器把这个问题暴露了出来,这让我意识到「可通关性」这种业务约束,光靠 AI 生成是不保险的,必须靠程序化校验兜底。 -
把逻辑和界面拆开,收益很大。核心的路径检测、关卡求解都是纯逻辑,可以脱离图形界面用
unittest直接测,T01~T06 全部自动化通过。这比每次打开游戏手动点要可靠得多,也是这次项目里我最满意的一点。 -
对 AI 提问的质量决定产出质量。当我把需求拆成「棋盘表示、路径检测、可通关判定、动画反馈」几个清晰的子问题分别去问时,AI 的产出明显更可用;而笼统地要求「写个小游戏」反而容易得到无法运行的代码。
总的来说,AIGC 是很好的「副驾驶」,但最终的判断、验证和设计决策仍然要由自己来完成——尤其是「关卡能否通关」「边界会不会越界」这类正确性问题。

浙公网安备 33010602011771号