软工第二次作业
一箭又一箭——用 Python + Pygame 完成 AIGC 小游戏
| 项目 | 内容 |
|---|---|
| 这个作业属于哪个课程 | 软件工程与软件工程实践 |
| 这个作业要求在哪里 | 2026秋软件工程个人作业(第二次) |
| 这个作业的目标 | 使用 Python 和 AIGC 完成"一箭又一箭"小游戏 |
| 学号 | 102402154 |
| GitHub 仓库 | https://github.com/haneryang/arrow-game |
0 开做之前
玩了两把原版"一箭又一箭",整理出几个关键点:
- 箭头是单格的,方向只有上/下/左/右;
- 点击后沿方向走到边界,路上有箭头就被挡住;
- 被挡要扣生命,有变红/抖动反馈;
- 关卡必须真的能通关;
- 失误 3 次失败、清空箭头进下一关。
想做的扩展:不规则拼豆棋盘、星级评价、combo 连击、撤销/提示/暂停。
1 项目展示
- 一款 Pygame 实现的拼豆风箭头解谜小游戏
- 技术栈:Python 3.13、pygame-ce 2.5
界面
开始界面是深蓝绒布垫上的标题和"开始游戏"按钮。进入游戏后:
- 顶部:
LEVEL 01/06、SCORE、TIME、三颗红心、暂停按钮; - 中间:不规则拼豆形状棋盘,箭头是彩色珠子带
^ > v <方向符; - 底部:
R重开 / U撤销 / H提示 / Esc暂停,连击时显示x2/x3。
细节
- 箭头飞出变绿色,沿方向飞出棋盘;

-
被挡箭头先撞过去再弹回,然后红闪;
![image]()
-
通关后显示星星(0失误=3星,1失误=2星,否则1星)和时间/得分/最高连击;
![image]()
-
暂停菜单可继续/重开/回主菜单。
![image]()
2 项目介绍
规则:点击珠子箭头,沿方向到棋盘边界途中无箭头则飞出消除;有箭头则不消失、红闪、扣一颗心。清空全部箭头进下一关,3 颗心用完失败。
主要功能:
- 6 个不规则拼豆形状关卡(小十字、方块、心形、花朵、箭头阵、终局);
- 路径检测、飞出动画、碰撞弹回动画;
- 暂停菜单、重开本关、返回主菜单;
- combo 连击加分(连击越高单步分越高);
- 撤销上一步(U)、提示一个可飞箭头(H);
- 通关星级结算(按失误数给 1~3 星);
- 顶部计时和得分显示。
代码全部在 arrow_game.py:
LEVELS:每关是{grid, mask}二元组,mask 标记哪些格子属于棋盘;can_fly():核心路径检测;click()/undo()/give_hint():操作;draw_*():分层绘制。
3 实现思路
箭头与方向
棋盘是 7×7,方向向量表:
DX = [0, 1, 0, -1] # 上右下左
DY = [-1, 0, 1, 0]
不规则棋盘(mask)
和同学一样,棋盘不是填满的方框,而是用一个 mask 二维数组标记哪些格子属于图案内:
"mask": [
[0,1,1,1,1,1,0],
[1,1,1,1,1,1,1],
...
]
mask 为 0 的位置不画格子背景,也不能放箭头。路径检测时用 in_mask() 判断是否出了图案边界,而不是简单判断坐标出界——这样箭头走出图案轮廓就算飞出成功。
路径检测(核心)
def can_fly(self, r, c, d):
nr, nc = r + DY[d], c + DX[d]
while self.in_mask(nr, nc):
if self.grid[nr][nc]:
return False
nr += DY[d]; nc += DX[d]
return True
状态机
start / play / pause / win_next / win_final / fail 六种状态,事件按状态路由。暂停时冻结计时,通关后冻结时间用于结算。
关卡可解性验证
每关写完都跑一个自动求解脚本:每次找当前能飞的箭头点掉,直到清空。如果出现死锁就调整箭头方向,6 关全部验证通过。
4 AIGC 使用过程
| 子任务 | 借助何种 AIGC | AI 实现/提供了什么 | 效果 | 人工修改 |
|---|---|---|---|---|
| 路径检测 | ChatGPT | 沿方向遍历判断阻挡 | 初版没判边界 | 加 in_mask 判断 |
| 关卡设计 | DeepSeek | 生成 6 组 mask+箭头布局 | L4/L6 出现死锁 | 调整箭头方向并脚本验证 |
| 界面美化 | Copilot | 拼豆配色、顶栏、暂停菜单 | 基本可用 | 调整动画时长、加星星结算 |
| 碰撞动画 | Cursor | 撞过去再弹回的两段动画 | 时序不对 | 把 20 帧分成前 10 帧撞、后 10 帧弹 |
4.1 路径检测越界
AI 写的 while grid[nr][nc] 没先判断是否出 mask 边界,点边缘箭头直接崩。加上 in_mask() 外层判断后正常。
4.2 关卡死锁
AI 给的 L6 有两个箭头面对面互相挡,自动求解脚本跑出来死锁。我把其中一个方向从朝左改成朝右,再跑脚本确认 7 步清空。AI 生成的关卡不能直接用,必须自动验证可解。
4.3 碰撞动画
AI 一开始只做了红闪,没有"撞过去再弹回"。我把动画拆成两段:前 10 帧朝 blocker 方向移动 30 像素,后 10 帧移回来,视觉上像撞了一下弹回。
5 测试结果
| 编号 | 测试内容 | 预期 | 实际 | 通过 |
|---|---|---|---|---|
| T01 | 点前方无阻挡箭头 | 飞出消失 | 绿色飞出后消失 | 通过 |
| T02 | 点前方有阻挡箭头 | 不消失,失误-1 | 红闪,心-1 | 通过 |
| T03 | 点边缘朝棋盘外箭头 | 正常飞出不越界 | 正常飞出 | 通过 |
| T04 | 清空本关箭头 | 通关进下一关 | 显示星星和面板 | 通过 |
| T05 | 失误用尽 | 失败可重开 | 显示"游戏失败" | 通过 |
| T06 | R 键 | 重开本关 | 布局和失误复位 | 通过 |
| T07 | U 键 | 撤销上一步 | 恢复箭头,连击清零 | 通过 |
| T08 | H 键 | 高亮一个可飞箭头 | 金色边框闪烁 | 通过 |
| T09 | Esc | 暂停/继续 | 计时冻结/恢复 | 通过 |
| T10 | 6 关可通关性 | 自动求解无死锁 | 6 关全部 2~9 步清空 | 通过 |
| T11 | 星级 | 0失误3星/1失误2星 | 面板星星数正确 | 通过 |
| T12 | combo | 连击加分,失误清零 | x2/x3 正确 | 通过 |
6 PSP 表格
| 任务 | 预估(h) | 实际(h) | 差异 |
|---|---|---|---|
| 需求分析与设计 | 1.0 | 0.5 | -0.5 |
| Python/Pygame 学习 | 1.0 | 1.5 | +0.5 |
| 界面实现 | 1.5 | 3.0 | +1.5 |
| 路径与碰撞逻辑 | 1.0 | 2.0 | +1.0 |
| 6 关设计与验证 | 1.0 | 2.0 | +1.0 |
| AIGC 辅助 | 1.0 | 1.5 | +0.5 |
| 测试与修改 | 1.0 | 1.5 | +0.5 |
| 博客撰写 | 1.0 | 1.5 | +0.5 |
| 合计 | 8.5 | 13.5 | +5.0 |
7 心得体会
这次作业最大的收获是自动化验证关卡可解性。手写 6 关很容易出现死锁,写个脚本每次找能飞的箭头点掉,跑不通就调方向,比人肉试玩可靠得多。
AIGC 给骨架很快,但边界条件(mask 越界)、交互细节(动画时序)、关卡可玩性都要自己跑起来确认。碰撞动画那种"撞过去弹回"的手感,AI 第一版做不出来,是我拆成两段帧调出来的。
整体来说,AI 适合写常规代码和配色,但"好不好玩、顺不顺手"得自己试。




浙公网安备 33010602011771号