软件工程与软件工程实践第二次个人作业
| 项目 | 内容 |
|---|---|
| 这个作业属于哪个课程 | 2026 软件工程与软件工程实践 |
| 这个作业要求在哪里 | 第二次个人作业:利用 AIGC 完成“一箭又一箭”小游戏 |
| 这个作业的目标 | 使用 Python 和 AIGC 完成“一箭又一箭”小游戏,实践需求分析、图形交互、路径检测、测试与过程记录。 |
| 学号 | 102302152 |
| GitHub 仓库 | dkb0704/arrow-again |
一箭又一箭:用 Python 与 Codex 完成一个箭头解谜小游戏
说明:本项目使用 ChatGPT / Codex 辅助开发,规则分析、主要代码、测试和文档整理均有 AI 参与。下面按实际发生的开发阶段说明 AI 做了什么、怎样验证,以及我本人试玩后提出的具体改进。截图来自项目自己的渲染代码,演示 GIF 为自动化事件回放。
一、项目展示
1. 开始界面

开始页包含游戏名称、开始按钮、三关选择和简短规则。界面采用暖白背景和四种箭头配色;颜色辅助辨认方向,真正的方向仍由箭头图形表达。
2. 游戏过程与碰撞反馈

棋盘放在左侧,右侧集中显示当前关卡、剩余箭头数、剩余失误机会,以及重开和提示按钮。点击路径畅通的箭头,它会沿朝向飞出;点击被阻挡的箭头,则保留棋盘状态并扣除一次失误机会。

碰撞反馈包括短暂晃动、双方变红和文字说明。这样即使没有音效,也能知道这一次点击为什么没有成功。
3. 通关与失败界面


清空第一、二关后显示通关结果,点击“下一关”继续;第三关完成后显示“全关卡完成”。失误机会归零后显示失败结果,可以重新开始当前关卡。
4. 演示 GIF

这段GIF演示了一次受阻点击及第一关的完整消除过程。自动回放通过与鼠标操作相同的事件处理器执行,没有另做一套演示页面;它展示了程序的实际状态变化。
二、项目介绍
1. 游戏规则
- 每个箭头占一个格子,只能沿上、下、左、右中的一个方向移动。
- 点击箭头后,检查它前方直到棋盘边界的整条路径。
- 路径没有其他箭头时,当前箭头飞出并消失。
- 路径有其他箭头时,当前箭头保留,剩余失误机会减 1。
- 每关有 3 次失误机会,棋盘清空即通关,机会用尽即失败。
- 重新开始会恢复本关初始布局和失误机会。
这里的“阻挡”只取决于位置。例如 → · · ↑ 中,最后一个箭头虽然朝上,仍然会挡住第一个向右的箭头。不能只检查紧邻的一格,也不能根据阻挡者的朝向决定是否碰撞。
2. 已实现功能
| 类别 | 功能 |
|---|---|
| 基础界面 | 开始、游戏、通关、失败、全部完成界面 |
| 核心规则 | 单格四方向箭头、全路径检查、边界处理、消除与失误 |
| 关卡流程 | 3 个固定原创关卡、下一关、失败重试、当前关卡重开 |
| 视觉反馈 | 加速飞出、碰撞晃动、碰撞变色、剩余数量和进度条 |
| 扩展功能 | 首页关卡选择、单步提示、R/H/Esc 快捷键 |
| 工程支持 | 独立规则模块、自动化测试、中文字体随包分发、素材生成脚本 |
扩展功能只保留了关卡选择和提示。没有加入复杂机关、账号或排行榜,以便把时间集中在规则正确和流程完整上。
3. 运行方式
实际开发和验证环境为 macOS 26.6.2、Python 3.11.15、Pygame 2.6.1。项目采用 Python 3.9+ 语法,推荐使用 Python 3.11;Windows 和 Linux 的安装方法在 README 中提供,但尚未实际验证其桌面运行效果。
进入项目目录后执行:
python -m pip install -r requirements.txt
python main.py
建议使用虚拟环境。启动后用鼠标左键点击箭头;R 重开,H 提示,Esc 返回首页。提示仅高亮一个当前可消除的箭头,不扣机会,也不代替玩家点击。
三、实现思路
1. 模块划分
项目分成四个主要文件:game.py 负责规则与状态,levels.py 保存关卡,ui.py 负责界面和动画,main.py 负责事件循环。
这样可以先验证规则,再调整界面。如果改变颜色或按钮位置,不需要修改路径检测;如果给规则写测试,也不需要先打开窗口。
2. 箭头与关卡的表示
关卡使用字符串元组,. 表示空格,U/D/L/R 分别表示上、下、左、右。例如第一关的布局为:
('..UD.',
'.LR.D',
'.D..D',
'R....',
'LDD.R')
游戏运行时转换为字典:键为 (row, col),值为方向。消除一个箭头就是删除一个字典元素,判断某格是否被占用也可以直接查字典。行向下增加,列向右增加;绘图时再把网格坐标换算成像素坐标。
3. 路径检测:从相邻格一直扫描到边界
四个方向统一表示为向量:
DIRECTIONS = {
'U': (-1, 0), 'D': (1, 0),
'L': (0, -1), 'R': (0, 1),
}
下面是核心检测代码的节选,完整实现在 Game.blocker():
dr, dc = DIRECTIONS[self.arrows[pos]]
r, c = pos[0] + dr, pos[1] + dc
while 0 <= r < self.height and 0 <= c < self.width:
if (r, c) in self.arrows:
return r, c
r, c = r + dr, c + dc
return None
这段代码有三个关键点:
- 从相邻格开始,避免把自己当作障碍。
- 每次检查前先判断坐标是否在棋盘内,边缘向外的箭头会直接通过。
- 遇到第一个被占用的格子就返回,不关心对方朝向;遇到空格继续前进。
一次检测最多扫描一行或一列,因此时间复杂度为 O(max(行数, 列数)),额外空间为 O(1)。对本项目的小棋盘足够使用。
4. 状态变化与动画
规则层只有 playing、won、lost 三种状态。成功点击删除箭头,棋盘为空就标记胜利;受阻点击只扣一次机会,归零就标记失败。结束状态不再接受规则点击。
界面层还区分开始页和全关完成页。成功点击后,逻辑棋盘立即删除箭头,同时保存一个包含位置、方向和持续时间的动画副本。之后每帧改变副本的绘制位置,产生飞出效果;最后一个箭头飞完才显示结果。
碰撞时不改棋盘,只让选中的箭头短暂晃动,并标记阻挡位置。动画期间锁定棋盘点击,避免连续点击造成失误重复扣除;重开和返回首页仍可立即使用,并取消正在播放的动画。
重开不依赖“撤销若干次删除”,而是直接从原始关卡字符串重新构造棋盘,同时清除提示和动画状态。
5. 三关如何保证可通关
| 关卡 | 名称 | 棋盘 | 箭头数量 |
|---|---|---|---|
| 1 | 初见方向 | 5×5 | 12 |
| 2 | 交错之间 | 6×6 | 22 |
| 3 | 一步之遥 | 7×7 | 34 |
关卡设计采用逆向插入思路:从空棋盘开始,每次插入一个当时出口方向为空的箭头。按照插入的相反顺序删除,就能得到一条合法通关路线。生成结果固定保存在 levels.py,实际游戏不依赖随机生成。
此外,测试还对固定关卡运行求解器并逐步重放。求解器每次挑选一个当前能飞出的箭头。因为删除只会减少阻挡,不会增加阻挡,所以这个基础玩法中不需要回溯;如果剩余箭头全被挡住,就可以判定当前布局无解。这个结论不能直接推广到含移动机关的游戏。
三关的自动重放都成功,步数分别为 12、22、34,失误机会均保持为 3。具体通关坐标保存在项目的试玩说明中。
四、AIGC 使用过程
| 子任务与要求 | 工具 | AI 实际完成了什么 | 验证效果与问题 | 人工修改情况 |
|---|---|---|---|---|
| 实现四方向检测、失误、通关与重开 | Codex | 先写 12 项规则测试,再编写统一向量扫描和状态管理 | 从模块尚未实现时的导入失败,到 12 项通过;保留原始输出 | 暂无;代码和测试由 AI 完成 |
| 至少设计三关并验证可解 | Codex | 生成原创固定布局,增加方向齐全、阻挡和求解重放测试 | 15 项测试通过;三关均找到完整解,未出现无解关卡 | 暂无;本人试玩另行记录 |
| 完成动画、中文界面和展示材料 | Codex | 增加 6 项事件测试,实现界面、动画锁定、截图和 GIF | 21 项通过;修正首页说明文字与装饰棋盘距离偏近的问题 | 暂无;该排版调整由 AI 完成 |
| 本人试玩后改善提示入口 | Codex | 根据我提出的按钮不突出问题,调整为深青绿色背景、白色文字和更深的悬停色 | 保留修改前后截图,并重跑测试 | 我完成三关试玩并提出具体反馈;代码由 AI 修改 |
| 复核规则与提交质量 | Codex 独立审查 | 运行测试,用独立坐标关系算法检查小棋盘,检查字体字符 | 2,000 次阻挡比较一致;未发现阻断性问题 | 代码复核由 AI 完成 |
有两个实际遇到的环境问题:首次依赖安装因受限环境网络访问失败而中断;首次启动桌面窗口返回退出码 134。换到允许联网、可访问桌面的运行环境后,同一份游戏代码成功运行。这也提示我,排查时应先区分安装或桌面环境问题与游戏逻辑问题。
开发记录按阶段保存在 docs/development/aigc-log.md,对应测试输出、提交记录和图片可互相核对。项目中的 AI 代码比例较高,因此必须重点阅读坐标换算、路径扫描和状态切换,确保能解释提交内容。
本人试玩带来的一次实际改进
我给出的反馈是,按钮和面板的色值接近,容易混在一起。Codex 据此保留布局和功能,只把提示按钮改成更醒目的深青绿底与白字。


这次改进形成了“实际试玩—发现问题—提出反馈—AI 调整”的过程,让我参与了界面验收和具体设计决策。
五、测试过程与结果
测试使用 Python 自带的 unittest。规则测试不依赖图形库;界面测试在无窗口模式下向真实 GameApp 发送鼠标和键盘事件。运行命令为:
python -m unittest discover -s tests -v
本次实际执行结果:21 项测试通过,0 失败。其中 12 项规则测试、3 项关卡测试、6 项界面事件测试。
| 编号 | 测试内容 | 预期结果 | 实际结果 | 是否通过 |
|---|---|---|---|---|
| T01 | 点击前方无阻挡的箭头 | 飞出并消失 | 逻辑删除箭头,界面产生飞行副本,动画结束后清理 | 通过 |
| T02 | 点击前方有阻挡的箭头,包括中间有空格 | 箭头保留,失误减 1 | 棋盘不变,机会 3→2,产生碰撞反馈 | 通过 |
| T03 | 点击四个边缘分别朝向外侧的箭头 | 正常消失,不越界 | 上、下、左、右子案例均通过 | 通过 |
| T04 | 清空每一关并切换下一关 | 通关、切关,最后显示全部完成 | 事件回放依次得到第一关通关、第二关通关、第三关全部完成 | 通过 |
| T05 | 消耗全部失误机会 | 失败,允许重开 | 状态变为 lost;重开恢复 playing 和 3 次机会 | 通过 |
| T06 | 消除/犯错后重开,动画中重开 | 恢复初始布局及次数 | 初始字典恢复,残留动画清除,R 快捷键有效 | 通过 |
额外检查包括:斜线箭头不阻挡、身后箭头不阻挡、点击空白不扣机会、结束后点击无效、提示不修改棋盘,以及三关的求解重放。
独立代码审查还对所有非空 2×2 布局进行了 2,000 次阻挡比较,结果与独立坐标关系判断一致。这是额外复核,不计入上述 21 项正式测试。
桌面检查中实际观察到了开始页进入游戏、成功删除、受阻扣机会和 R 重开恢复;同时检查了导出的开始、游戏和结果图片。Windows/Linux 桌面尚未实际测试;本人三关试玩结果另见前文。
六、Git 与开发记录
开发过程中按阶段保存了本地 Git 提交,主要包括:
docs: 记录游戏需求设计与真实 AIGC 开发起点
feat: 实现四方向路径检测与失误重开逻辑
feat: 设计三组原创关卡并验证完整通关顺序
feat: 完成中文游戏界面与飞出碰撞动画
test: 验证界面交互并完善演示素材与开发记录
这些提交在相应阶段完成后创建,覆盖设计、实现、测试和改进。GitHub 仓库保留了这些分阶段提交历史,公开版本对学号和提交邮箱做了隐私处理。
仓库包含源码、依赖说明、README、中文字体及许可、测试、截图和开发文档。环境文件、虚拟环境和缓存已忽略,没有游戏运行所需的密码或 API Key。
七、PSP 表格
| 任务 | 预计耗时参考(小时) | 实际耗时估算示例(小时) | 差异(小时) |
|---|---|---|---|
| 需求分析与游戏设计 | 0.30 | 0.25 | -0.05 |
| Python 与图形库学习 | 0.40 | 0.35 | -0.05 |
| 游戏界面阅读与反馈 | 0.30 | 0.25 | -0.05 |
| 路径与碰撞逻辑阅读 | 0.40 | 0.40 | 0.00 |
| 关卡检查与本人试玩 | 0.20 | 0.20 | 0.00 |
| AIGC 辅助开发与沟通 | 0.30 | 0.35 | +0.05 |
| 测试与修改结果检查 | 0.30 | 0.25 | -0.05 |
| README 与博客阅读整理 | 0.40 | 0.45 | +0.05 |
| 合计 | 2.60 | 2.50 | -0.10 |
这份示例把个人投入分成需求理解、代码阅读、试玩与反馈、文档整理等环节。已确认的个人实践包括提供需求与作业链接、通过三关,以及提出提示按钮改进意见。
八、心得与反思
1. AI 的帮助可以从产物中具体看到
本次 AI 的作用不只是补全函数,还包括把作业拆成模块、先写测试、设计关卡、制作界面和整理证据。这些工作缩短了从需求到可运行程序的路径,也使“为什么判断正确”有测试可查,而不仅是凭一次成功运行下结论。
2. 能运行,还不等于完成验证
项目中最值得关注的是几个容易被忽略的细节:方向向量中的行列是否弄反、路径是否只检查相邻格、最后一个动画是否播放完再显示通关、重开是否保留旧状态。AI 给出的代码同样需要逐项验证,不能因为画面好看就认为所有要求已经满足。
关卡可解性也不能只靠“看起来能玩”。逆向构造、求解器重放和本人试玩分别提供不同证据:前两者验证规则和布局,后一项检验实际操作与理解,不能互相替代。
3. 试玩发现的问题不一定是程序错误
我已经通过三关,提出的主要问题却不是路径算法,而是提示按钮不够突出。按钮在代码里已经存在、点击也有效,但如果和背景过于接近,玩家就不容易注意到它。这说明功能测试与实际体验关注的角度不同:前者检查“能不能用”,后者还要检查“是否容易发现和理解”。
这次修改也让我有一个明确的复盘依据:AI 先实现功能,我通过试玩指出具体问题,再让 AI 按反馈调整。这种协作需要人参与判断,而不仅是接收生成结果。项目主要代码由 Codex 完成,个人学习还应落实到能够独立解释相邻格扫描、边界判断、删除不新增阻挡和重开恢复这几个关键点。
棋盘、箭头和其他图形均通过 Pygame 绘制,三组布局独立设计。开发工具为 ChatGPT / Codex,没有接入在线模型 API,游戏运行不需要网络或密钥。

浙公网安备 33010602011771号