2026秋软件工程第二次个人作业—— 一箭又一箭

项目 内容
这个作业属于哪个课程 https://edu.cnblogs.com/campus/fzu/202601SofwareEngineering
这个作业要求在哪里 https://edu.cnblogs.com/campus/fzu/202601SofwareEngineering/homework/16717
这个作业的目标 使用 Python 和 AIGC 完成“一箭又一箭”小游戏
学号 102401403
GitHub 仓库 https://github.com/pyyy123/arrow-game

一、项目展示

1. 开始界面

dream_start

2. 游戏过程

游戏界面

演示 GIF:demo.gif

3. 失败界面

失败界面

4. 通关界面

通关界面

二、项目介绍

游戏规则

棋盘上分布着朝向上、下、左、右四个方向的箭头。玩家点击某个箭头后:

  • 如果箭头前进方向上没有其他箭头阻挡,它会飞出棋盘并被消除;
  • 如果路径上有其他箭头,它不会消失,并会晃动并变色作为碰撞反馈;
  • 每次点击被阻挡的箭头消耗一次失误机会;
  • 清空本关全部箭头即可通关,失误耗尽则失败。

界面设计

游戏包含三种界面状态:

  • 开始界面:标题、玩法说明、开始按钮;
  • 游戏界面:顶部 HUD(关卡、剩余箭头、剩余失误)、棋盘、重新开始按钮;
  • 通关/失败界面:半透明遮罩 + 结果文字 + 操作按钮。

主题为“梦境”,背景为淡紫色,配有云朵和梦境精灵装饰,箭头带有柔光效果。

主要功能

  • 四种方向箭头;
  • 鼠标点击交互;
  • 路径阻挡检测;
  • 飞出动画与碰撞晃动反馈;
  • 失误次数机制;
  • 3 个可通关关卡;
  • 通关、失败、重新开始、下一关。

三、实现思路

1. 箭头、方向的表示

用一个二维列表 grid 表示棋盘,每个格子的值是整数:

  • 0 表示空;
  • 1/2/3/4 分别表示上、下、左、右。

方向到行列增量的映射:

DIR_VEC = {
    UP:    (-1, 0),
    DOWN:  ( 1, 0),
    LEFT:  ( 0, -1),
    RIGHT: ( 0, 1),
}

这样在路径检测时只需要按方向累加即可,不需要为四个方向分别写四套循环。

2. 关卡表示

每个关卡是一个字典,包含 name、mistakes 和 grid:

"level_1": {
    "name": "第1关:5x5 简单",
    "mistakes": 5,
    "grid": [
        [0, 0, 1, 0, 0],
        ...
    ],
}

LEVEL_ORDER 控制关卡顺序,方便后续扩展。

3. 路径检测(重点)

核心函数 is_blocked(row, col):

def is_blocked(self, row, col):
    direction = self.grid[row][col]
    dr, dc = DIR_VEC[direction]
    r, c = row + dr, col + dc
    while 0 <= r < self.rows and 0 <= c < self.cols:
        if self.grid[r][c] != 0:
            return True
        r += dr
        c += dc
    return False

从当前格子出发,沿方向逐步前进,只要在棋盘内且遇到非空格子就返回 True;走出棋盘则返回 False。这样同时处理了“被挡住”和“边缘飞出”两种情况,不需要额外判断边界。

4. 飞出动画与碰撞反馈

飞出:点击无阻挡箭头后,把 (row, col) 加入 animating_cells,并创建 FlyAnimation。动画期间 grid 仍保留该箭头,动画结束后再置 0。这样 count_arrows() 在动画期间不会误判通关。

碰撞:点击被阻挡箭头时,把 (row, col) 加入 bad_effects,绘制时根据剩余时间做水平晃动并变色。

四、AIGC 使用过程

开发过程中我主要使用 ChatGPT 和 DeepSeek 辅助开发,下面记录 3 次有代表性的过程。

记录 1:飞出动画优化(ChatGPT)

子任务 借助何种 AIGC 技术 AI 实现或提供了什么 效果如何 人工修改
飞出动画 ChatGPT 分析缓动与 alpha 曲线,给出优化建议 指出 alpha 线性衰减过早、距离与 alpha 缓动不一致 未采纳 alpha 曲线建议,保留线性 alpha,仅参考了写法建议

我向 ChatGPT 展示了 FlyAnimation.draw 的代码,并问了三个问题:

  1. 飞出动画能否更自然?
  2. 渐隐 alpha 会不会在飞出距离长时提前变透明?
  3. 有没有更简洁或更流畅的写法?

ChatGPT 指出:距离用了 ease-out cubic,但 alpha 是线性的,视觉上会出现“先冲后飘”的割裂感;而且 alpha = 255 * (1 - p) 在 p=0.5 时已经降到 128,对 560px 的飞行距离来说太早淡出。

它建议:

  • 距离用 ease-out quad 1 - (1-p)**2;
  • alpha 也加缓动,例如 alpha = 255 * (1 - p**2) 或 alpha = 255 * clamp((1-p)/0.4, 0, 1);
  • 可选加缩放增强纵深;
  • 用 convert_alpha()、Vector2 位移、rect.move 等优化写法。

我评估后没有采纳 alpha 曲线的建议,因为本游戏的飞出动画时长只有 0.28 秒,线性 alpha 在实际观感中已经足够自然,换成曲线反而会让前段过亮、后段过暗。我最终保留了原有的 alpha = int(255 * (1 - progress)) 写法,没有改动这段代码。

屏幕截图 2026-09-18 135634

屏幕截图 2026-09-18 135655

记录 2:路径检测边界分析与飞出逻辑(ChatGPT)

子任务 借助何种 AIGC 技术 AI 实现或提供了什么 效果如何 人工修改
路径检测 ChatGPT 补充边界测试用例,分析飞出期间 grid 未清空的问题 指出动画期间其他箭头仍会把它算作阻挡物 评估后保留原方案,并加注释说明

我让 ChatGPT 为 is_blocked 补充边界测试用例,包括:

  1. (0,0) 位置朝上(越界判断);
  2. 两个箭头背对背,互不阻挡;
  3. 空 grid 上的行为;
  4. 同一行/列多个箭头。

ChatGPT 给出了详细分析:

  • 边界安全:is_blocked 不会数组越界,因为 r 一旦越界,while 条件立刻不成立;
  • 不会把自己算作阻挡:检测起点是 row + dr, col + dc,不是 (row, col);
  • 关键发现:代码无法区分「静止箭头」和「正在飞出的箭头」。如果飞出动画开始后 grid 里还保留着 1–4,其他箭头会把它算作阻挡物。

它建议:如果游戏规则是“箭头一旦开始飞出就不再阻挡其他箭头”,应该在启动飞行动画时立刻把原格清空:

self.grid[row][col] = 0

我评估后认为,本游戏的设计是“飞出动画期间箭头仍占位”——这样视觉上箭头还没飞出棋盘,其他箭头就仍应把它当阻挡物。如果按 AI 建议立刻清空 grid,会导致动画期间路径检测结果和视觉不一致。

因此我保留了自己原有的方案:用animating_cells标记正在飞出的格子,动画结束才在update里把 grid置 0。这段逻辑最终没有改动。

屏幕截图 2026-09-18 140326

屏幕截图 2026-09-18 140354

屏幕截图 2026-09-18 140510

记录 3:README 模板与撰写(DeepSeek)

子任务 借助何种 AIGC 技术 AI 实现或提供了什么 效果如何 人工修改
README 撰写 DeepSeek 生成完整的 README 结构模板 框架清晰,但内容偏通用,与项目实际不符 逐节替换为实际内容,修正 6 处不符

我向 DeepSeek 提问:“帮我写一份 Pygame 项目的 README 模板,项目是一个点击式箭头解谜小游戏,名叫‘一箭又一箭’。”DeepSeek 给出了一份结构清晰的 Markdown 模板,包含项目名称、游戏简介、开发环境、安装运行、操作说明、截图、项目结构、关卡说明、素材来源等章节。

模板的框架是可用的,但内容偏通用,我逐节对照实际项目进行了修改:

  1. 游戏简介:DeepSeek 写的是“改变箭头方向或触发连锁反应”,与我的实际玩法(点击后路径无阻挡则飞出)不符,我改写为真实规则;
  2. 开发环境:DeepSeek 写的是 Python 3.8+、Pygame 2.1+,我按实际写了 Python 3.10+、pygame;
  3. 安装运行:DeepSeek 写的是 git clone https://github.com/yourname/one-arrow-after-another.git,我替换为实际仓库地址,运行命令改成 python main_fixed.py;
  4. 操作说明:DeepSeek 额外写了 ESC 退出、R 重新开始,但我的项目只支持鼠标点击,没有键盘快捷键,我删掉了这两条;
  5. 项目结构:DeepSeek 假设有 scenes/、assets/、levels/level1.py 等目录,与实际不符,我按实际文件列表重写;
  6. 关卡说明:DeepSeek 写的是“连锁反应”“终极考验”等玩法,与实际关卡机制不符,我改为按尺寸和失误次数说明;
  7. 素材来源:DeepSeek 写了 Kenney、OpenGameArt、Freesound、Google Fonts,但我的项目所有图形均由 Pygame 绘制,未使用外部素材,我改为真实来源。

最终 README 在 GitHub 上显示正常,助教可按说明直接运行。

屏幕截图 2026-09-22 105049

readme

五、测试结果

5.1 路径检测逻辑测试(tests/test_logic.py)

编号 测试内容 预期结果 实际结果 是否通过
T01 前方无阻挡 is_blocked 返回 False 与预期一致 ✅
T02 前方有阻挡 is_blocked 返回 True 与预期一致 ✅
T03 边缘箭头朝外 正常飞出,不越界 与预期一致 ✅
T04 四个方向检测 全部返回 False 与预期一致 ✅
T05 左边缘朝左 不越界 与预期一致 ✅
T06 背对背箭头 互不阻挡 与预期一致 ✅
T07 空格子 不可点 与预期一致 ✅
T08 同一行多箭头 最近阻挡生效 与预期一致 ✅
T09 顶部朝上 不越界 与预期一致 ✅

5.2 游戏功能手工测试

编号 测试内容 预期结果 实际结果 是否通过
T01 点击前方无阻挡的箭头 箭头飞出棋盘并消失 与预期一致 ✅
T02 点击前方有阻挡的箭头 箭头不消失,失误次数减 1 与预期一致 ✅
T03 点击位于边缘且朝向棋盘外的箭头 箭头正常消失,不发生越界错误 与预期一致 ✅
T04 消除本关全部箭头 显示通关并进入下一关 与预期一致 ✅
T05 失误次数耗尽 显示失败并允许重新开始 与预期一致 ✅
T06 游戏进行中重新开始 箭头布局和失误次数恢复 与预期一致 ✅

5.3 关卡可通关性验证

运行 python verify_levels.py,三关均输出“有解”,分别需要 8、13、19 步。

屏幕截图 2026-09-22 141926

屏幕截图 2026-09-22 142102

六、PSP 表格

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

七、心得体会

这次作业让我第一次比较系统地用 AIGC 工具参与一个小型项目的完整开发。最大的感受是:AI 能大幅提高起手速度,但不能替代自己理解代码。

具体来说:

1.AI 擅长给结构和模板。 比如界面布局、按钮类、状态机这些“套路化”的部分,ChatGPT 给得很快,我只需要按自己的主题调整颜色和文字;README 模板 DeepSeek 也给了很好的框架。

2.AI 在边界条件上容易出错。 路径检测的越界、关卡死锁、动画频率过高,都是 AI 生成后我实际运行才发现的。这让我意识到“能跑”和“跑对”是两回事,必须自己测试。

3.关卡设计不能完全交给 AI。 AI 生成的布局看起来合理,但用 verify_levels.py 一跑就发现死锁。手工调整并试玩是必须的。

4.AIGC 记录要真实。 我在开发过程中确实和 ChatGPT、DeepSeek 来回修改了很多次,博客里记录的这几次是比较有代表性的。

5.AI 给的模板不能照抄。 DeepSeek 的 README 模板看起来齐全,但里面写的素材来源、项目结构、操作说明和我的项目完全不符,必须逐条对照修改。

6.不采纳 AI 的建议也是一种判断。 比如飞出动画的 alpha 曲线、路径检测的 grid 清空方案,我评估后都保留了原写法,因为原来的设计更符合本游戏的实际需求。

总的来说,这次作业让我对“人机协作开发”有了更具体的认识:AI 是加速器,但方向盘和刹车必须自己握。

posted @ 2026-09-22 14:42  pyue  阅读(40)  评论(0)    收藏  举报