一、项目基本信息

项目 内容
这个作业属于哪个课程 前往班级
这个作业要求在哪里 前往查看
这个作业的目标 使用 Python 和 AIGC 完成“一箭又一箭”小游戏
学号 102401309
GitHub 仓库 前往主页

二、项目展示

2.1 开始界面

主页面

说明:标题画面含三行规则提示与「新游戏 / 选关 / 继续游戏」三个入口。有未完成存档时才会显示「继续游戏」。

2.2 游戏过程

过程

说明:玩家观察箭头方向与阻挡关系,点击箭头使其飞出或受阻;顶栏实时显示关卡名、余箭、余次与用时。

2.3 通关 / 失败

成功

失败

说明:通关显示星级、得分、用时、失误;失败可「再战」;全部通关显示全通画面。

2.4 视频

试玩


三、项目介绍

3.1 游戏目标

玩家需要观察箭头方向和相互阻挡关系,通过合理顺序点击箭头,使全部箭头飞出棋盘。

3.2 基础规则

状态 行为
前方无箭头 箭头飞出并消失
前方有箭头 箭头不能消失,消耗一次失误次数,播放碰撞反馈
全部箭头清空 当前关卡通过
失误次数归零 当前关卡失败
点击重开 恢复进入当前关卡时的初始状态

3.3 操作

鼠标左键        :点击箭头 / 按钮
「撤销」按钮     :回退最近一次结算(无历史时禁用)
「重开」按钮     :恢复本关开局快照
鼠标滚轮        :以鼠标位置为中心缩放棋盘
鼠标中键拖拽    :平移棋盘
Home 键         :缩放归位到适合窗口
标题「选关」     :进入关卡选择界面
标题「继续游戏」 :恢复上次未完成的关卡

四、实现思路

4.1 项目架构

项目采用:

状态机 + 规则 / 表现分离

核心模块:

main.py                      入口 + 主循环
    ↓
scenes.py                    场景状态机(标题/选关/对局/结果)
 ┌──┴─────────┐
view.py     anim.py          表现层:绘制 / 摄像机 / 动画
    ↑
rules.py  solver.py  score.py  save.py   规则层(不 import pygame)
    ↑
levels.json                   关卡数据(数据 / 规则分离)

说明:规则层负责盘面、射线、余次、快照、撤销、评分、求解与存档,全部为纯逻辑;表现层只把规则层结果画出来并处理输入。关卡坐标只进 levels.json,改关不改判定。

4.2 箭头表示

单支箭头使用:

id  row  col  dir

例如:

{
  "id": "a",
  "row": 1,
  "col": 0,
  "dir": "right"
}

4.3 路径检测(关键代码)

定义四方向增量:

DIRS = {
    "up": (-1, 0),
    "down": (1, 0),
    "left": (0, -1),
    "right": (0, 1),
}

从箭头相邻格开始逐格扫描,核心代码如下(rules.py):

def _ray(self, row, col):
    idx = self.arrow_at(row, col)
    if idx is None:
        return None
    arrow = self.arrows[idx]
    dr, dc = DIRS[arrow["dir"]]
    r, c = row + dr, col + dc
    # 关键:先判断格子在不在盘内,再读占用。
    # 否则 Python 负索引会绕到网格另一头,边缘朝外箭会判错。
    while 0 <= r < self.rows and 0 <= c < self.cols:
        j = self._blocked_by(r, c, idx)
        if j is not None:
            return False, j      # 先碰到箭 → 阻挡
        r += dr
        c += dc
    return True, None            # 一路空到边界 → 可飞

五、关卡设计

5.1 当前关卡

关卡 规模 箭头数量 余次 主要训练内容
L0 教程 3×5 3 5 认识飞出与阻挡
L1 顺序入门 4×4 5 3 先清除挡路箭头
L2 交叉 5×5 7 3 行列交叉阻挡
L3 收束 5×6 9 3 较长依赖关系
L4 脉冲走廊 6×7 12 4 大盘 + 明显分支
L5 交错方阵 7×8 16 4 多出口 + 中间链
L6 深空编队 8×9 20 5 大盘观察、行列交织
L7 终端迷阵 9×10 26 5 高难度基础关

六、游戏测试

6.1 基础测试

编号 测试内容 预期 实际 是否通过
T01 点击无阻挡箭头 飞出消失 规则层 + 冒烟通过
T02 点击被阻挡箭头 不消失、扣次 规则层通过
T03 点击边缘箭头 正常飞出 规则层通过
T04 清空关卡 进入通关流程 冒烟通过
T05 余次耗尽 进入失败流程 冒烟通过
T06 中途重开 恢复开局 冒烟通过

6.2 扩展测试

编号 测试内容 预期 实际 是否通过
T07 撤销成功飞出 箭头恢复 规则层 test_undo_fly 通过
T08 撤销恢复余次 余次还原 规则层 test_undo_blocked 通过
T09 solver 求解 返回合法通关序 规则层 test_solver_all_levels 通过
T10 solution 一致 参考解清空本关 规则层 test_reference_solution 通过
T11 存档 重启后恢复 规则层 test_save_roundtrip 通过

另由冒烟测试覆盖:评分 / 星级(test_score)、碰撞返回动画(BlockedReturn)、摄像机缩放 / 平移、音效容错;exe 打包待无 Python 环境实测。


七、AIGC 使用过程

本部分来自真实开发记录。

7.1 第一次:策划与架构(Cursor)

项目 内容
工具 Cursor
我的需求 把作业说明书拆成可落地的策划案与代码框架
AI 提供内容 玩法拆解、增量分层、规则表、流程、接口分表
实际效果 可作骨架,偏说明书口吻
我做的修改 按策划案重写,关卡外置为数据文件
最终结论 保留其分层与增量思路,落地为「状态机 + 规则/表现分离」

7.2 第二次:核心规则 / 测试(Claude Code)

项目 内容
工具 Claude Code
我的需求 实现射线判定、撤销、关卡可解性核验
AI 提供内容 _ray 边界处理、快照撤销、依赖图求解、自动化测试
实际效果 规则层 11 项测试通过
我做的修改 修正 L1/L3 参考序、pygame SysFont 坑
最终结论 规则层与表现层分离后,判定可脱离 pygame 先行测试

7.3 第三次:扩展功能(ChatGPT + Claude Code)

项目 内容
工具 ChatGPT + Claude Code
我的需求 扩展优先级分析与实现(撤销/评分/存档/摄像机/UI/音效/打包)
AI 提供内容 优先级表、可运行代码、关卡数据、测试用例
实际效果 E1–E9 全部落地,测试通过
我做的修改 修正 L7 大盘溢出、统一 E 编号、补注释
测试结果 规则层 + 冒烟全过

7.4 后续 AIGC 记录

日期 功能 工具 AI 结果 人工修改 测试结果
09-22 关卡 + solver ChatGPT/Claude 依赖图求解 采纳 通过
09-22 撤销 Claude 快照栈 采纳 通过
09-22 评分/存档 Claude score/save 模块 采纳 通过
09-22 UI/音效/打包 Claude 霓虹配色 + 自制音效 + spec 采纳 通过

八、扩展功能

8.1 扩展一:撤销一步

问题:误点被挡的箭会扣失误次数,降低容错体验。

设计:Session 内维护快照栈,每次结算前 _snapshot() 保存盘面与余次;undo() 弹栈恢复。

实现:rules.py 增加历史栈(上限 20),scenes.py 增加「撤销」按钮(无历史时禁用)。计时不回退,避免刷时间。

测试:T07/T08 通过。

8.2 扩展二:得分 / 计时 / 星级

最终规则:

总分 = 700 × 准确度 + 300 × 时间分   (0–1000)
准确度 = 1 − 失误次数 / 初始余次
时间分 = 用时 ≤ par_time 记满分,超时最多再给 2×par_time 的线性衰减
星级  = 得分 ≥ 900 三星,≥ 700 两星,否则一星

实现:game/score.py 纯逻辑;PlayScene 累计 elapsed(撤销不回退);结果画面显示星级/得分/用时/失误。

8.3 扩展三:保存进度

保存内容:unlocked_levelin_progress(关卡/箭头/余次/用时)、best(每关最佳分)。

保存时机:每次结算后自动保存;通关时解锁下一关并记最佳;失败清进行中。

加载时机:标题「继续游戏」读取 in_progress 恢复盘面、余次与用时。

异常存档处理:版本不符或 JSON 损坏时回退默认值,不影响启动。

8.4 扩展四:AI 自动求解

核心思想:把「谁必须先被清除」建模为 blocker → blocked 依赖图;删除箭头只会减少阻挡,故「不断选当前可飞箭」等价于 Kahn 拓扑排序,无需 DFS。

求解代码(solver.py):

def solve(level):
    arrows, adj, indeg = build_dependency_graph(level)   # j 挡 i → 边 j→i
    q = deque(i for i, d in enumerate(indeg) if d == 0)   # 入度 0 = 当前可飞
    order = []
    while q:
        i = q.popleft()
        order.append(i)
        for j in adj[i]:
            indeg[j] -= 1
            if indeg[j] == 0:
                q.append(j)
    return None if len(order) != len(arrows) else [arrows[i]["id"] for i in order]

测试:T09 八关均返回完整解序,T10 solution 与运行规则一致。

8.5 扩展五:视口拖动 / 缩放

设计:BoardView 维护 zoom(0.45–2.0)与 pan_x/pan_y;滚轮以鼠标位置为中心缩放,中键拖拽平移,Home 归中;进入关卡先 fit 自动适配整盘。

边界:最小缩放 0.45、最大 2.0;大盘(9×10)自动缩小至完整显示。

8.6 扩展六:电子游戏风 UI

设计说明:深色底 + 霓虹(青箭头、红受阻、金星级),HUD 显示关卡/余箭/余次/用时,程序绘制箭头(缩放不糊),按钮禁用态降透明度。

8.7 扩展七:碰撞动画

目标动画:

点击 → 短距离前冲 → 碰撞点 → 闪烁 → 沿反方向缓动返回 → 恢复原位置

最终参数:

前冲时长:0.18s(ease-out cubic)
碰撞停顿:0.18–0.25s(碰撞圆环闪烁)
返回时长:0.25–0.58s(ease-in-out)
总时长:约 0.58s

8.8 扩展八:音效

事件 音效 状态
点击箭头 click.wav
飞出 fly.wav
受阻 blocked.wav
撤销 undo.wav
通关 clear.wav
失败 fail.wav

资源来源:全部为 tools/gen_sfx.py 程序合成的自制短音效,无版权问题。

8.9 扩展九:打包

打包工具:PyInstaller(yi_jian.spec,onefile、无控制台)。

构建命令:

python -m PyInstaller --noconfirm --clean yi_jian.spec

输出:dist/YiJianYouYiJian.exe

测试机器 / 结果:[待补充]


九、GitHub 开发过程

9.1 Commit 记录

时间 Commit 内容
09-21 docs 策划案与库笔记、作业记录与工程搭建
09-22 feat 基础功能完成
09-22 feat 扩展 P0(更多关卡、撤回、计时与等级)完成
09-22 feat 扩展 P1(选关、存档、配色
09-22 feat 扩展 P2(音效、相机移动缩放、打包
09-22 docs 截止总结

以仓库实际 commit 为准。

9.2 GitHub 展示页

仓库:https://github.com/UYESoarin/Software-Engineering/tree/main/AIGCGame

项目截图:

github


十、PSP

任务 预估耗时(小时) 实际耗时(小时) 差异
需求分析与游戏设计 1.5 2.0 +0.5
Python 与图形库学习 1.0 1.0 0
游戏界面实现 2.5 2.0 -0.5
路径与碰撞逻辑实现 2.0 1.5 -0.5
关卡设计 1.5 1.5 0
AIGC 辅助开发 1.5 1.5 0
测试与修改 1.5 1.0 -0.5
扩展功能 3.0 1.5 -1.5
README 与博客撰写 2.0 1.0 -1.0
合计 约 16.5 13.0 -3.5

十一、遇到的问题与解决

问题 原因 解决方法 AIGC 是否参与
L1/L3 参考解与盘面不符 文档参考序写错,被挡箭排在前面 独立脚本核验可解性,修正参考序
pygame SysFont 抛 TypeError 2.6.1 扫描 Windows 注册表字体 bug 改用 Font(path) 直取 msyh.ttc
L7(9×10)棋盘超出窗口 固定 64px 格子 自适应 cell + 摄像机缩放

十二、心得体会

12.1 AIGC 带来的帮助

AIGC 显著加快了策划、代码骨架、扩展方案与测试的产出;依赖图求解等算法思路可直接复用。

12.2 AIGC 暴露的问题

AI 生成的参考解、接口假设可能出错,需独立核验;文档与代码需人工把关一致性。

12.3 人工判断的重要性

关卡可解性、边界条件、版本一致性这些正确性问题,必须由人工验证,AI 无法替代。

12.4 软件工程方面的收获

增量交付、数据/规则/表现分离、自动化测试回归、可拓展接口设计。

12.5 游戏开发方面的收获

状态机、帧循环与 dt 解耦、程序绘制、动画时序、摄像机坐标换算。


十三、最终总结

项目当前完成:基础玩法(11 条要求全部达成)+ 扩展(撤销、评分星级、存档、选关、摄像机、霓虹 UI、碰撞动画、音效、AI 求解、打包配置)。

最终关卡:8 关(L0–L7)。

最终测试:规则层 11 项 + 冒烟全过。

最终版本:v0.2 扩展版本(v1.0 提交版本待打包实测)。

GitHub:https://github.com/UYESoarin/Software-Engineering/tree/main/AIGCGame