软工第二次作业

“一箭又一箭” 小游戏开发博客

一、基本信息

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

二、项目展示

  • 开始界面:

开始界面

  • 游戏过程:

游戏过程

  • 碰撞反馈:

碰撞反馈

  • 提示功能:

提示功能

  • 通关界面:

通关界面

  • 失败界面:

失败界面

  • 全部通关:

全部通关

  • 演示动图(自动通关第 1 关,含一次故意碰撞):

演示

三、项目介绍

游戏规则:棋盘上分布着若干带方向的箭头(上 ↑ / 下 ↓ / 左 ← / 右 →)。点击一个箭头后,程序检查该箭头前进方向上、到棋盘边界之间是否还有其他箭头:

  • 无阻挡 → 箭头飞出棋盘并被消除;

  • 有阻挡 → 箭头不能消除,发生碰撞(抖动 + 红色光圈 + “被挡住了!” 提示),并消耗 1 次失误机会;

  • 失误次数耗尽 → 本关失败,可重新开始;

  • 清空全部箭头 → 通关,进入下一关。

界面设计:深色主题,包含开始界面、游戏界面(顶部信息栏 + 中央棋盘)、通关 / 失败 / 全部通关结算界面。箭头按方向使用不同颜色(上绿、下橙、左蓝、右红),信息栏显示当前关卡、剩余箭头、剩余失误(红心)、用时。

主要功能:3 个可通关关卡(已通过可解性自动验证)、鼠标点击交互、飞出 / 碰撞动画、失误机制、通关 / 失败 / 重开流程、快捷键(R 重开、H 提示)。

特色(附加功能):提示功能(高亮一个当前可飞出的箭头)、每关计时、通关星级评价(0 失误 3 星、1 次 2 星、2 次 1 星)、程序实时生成的飞出 / 碰撞提示音。全部视觉元素均为代码绘制,无任何外部素材。

四、实现思路

1. 箭头、方向与关卡如何表示

箭头用 Arrow 类表示,记录行号、列号、方向(UP/DOWN/LEFT/RIGHT 四个整数常量)与动画状态:

class Arrow:

    def \_\_init\_\_(self, r, c, d):

        self.r, self.c = r, c      # 所在行列

        self.d = d                 # 方向

        self.state = "idle"        # idle / flying / colliding

        self.t = 0.0               # 动画进度

棋盘是二维数组 grid,元素为 Arrow 或 None(空格)。关卡数据用字符直观书写,加载时转换:

LEVELS = \[

    \_lv(\[

        "← → · · ·",   # 第 1 关

        "· · ↑ · ·",

        "↓ · · → ·",

        "· ↑ · · ←",

    ]),

    ...

]

2. 路径检测(核心逻辑)

点击箭头后,从箭头所在格出发,沿其指向方向逐格检查到棋盘边界,只要遇到任意非空格即判定 “被阻挡”:

def path\_blocked(self, r, c):

    a = self.grid\[r]\[c]

    if a is None:

        return False

    d = a.d

    if d == UP:

        for rr in range(r - 1, -1, -1):     # 向上逐格

            if self.grid\[rr]\[c] is not None:

                return True

    elif d == DOWN:

        for rr in range(r + 1, self.rows):  # 向下逐格

            if self.grid\[rr]\[c] is not None:

                return True

    elif d == LEFT:

        for cc in range(c - 1, -1, -1):     # 向左逐格(从 c-1 开始,避开自身格)

            if self.grid\[r]\[cc] is not None:

                return True

    else:                                    # RIGHT

        for cc in range(c + 1, self.cols):

            if self.grid\[r]\[cc] is not None:

                return True

    return False

以作业中的两个例子验证:

  • → · · ↑ ·:第一个 → 的右侧存在 ↑,逐格检查到 (0,3) 时返回 True(被阻挡);

  • ↑ · · · →:最后一个 → 右侧全为空,循环自然结束返回 False(可飞出)。

边界处理是重点:向上检测从 r-1 开始、向左从 c-1 开始,保证顶行 / 最左列的箭头不会越界、也不会把自己当成阻挡者(详见下文 AIGC 记录 1、2)。

3. 游戏流程状态机

用字符串状态管理界面流程:start → play → clear / over / all_clear。update(dt) 负责推进动画(飞出:位移 + 缩小 + 淡出;碰撞:正弦抖动 + 红色光圈)与胜负判定,绘制与逻辑分离。

五、AIGC 使用过程

本次开发全程使用大模型编程助手(本作业实际使用豆包)辅助,记录了 4 次具有代表性的协作过程。以下是过程摘要:

子任务 借助何种 AIGC 技术 AI 实现或提供了什么 效果如何 人工修改
需求分析与代码骨架 豆包(大模型对话) 根据作业要求生成游戏框架:常量、关卡数据结构、棋盘渲染、点击消除 基础版可运行 无
路径检测 豆包(大模型对话) 生成四个方向的检测代码 向上 / 向下正确,但向左检测存在边界 Bug(遍历含自身格,导致边缘 ← 被误判为阻挡) 编写单元测试定位问题后,把边界从 range(c, -1, -1) 改为 range(c-1, -1, -1),测试通过
关卡设计 豆包(大模型对话) 生成 3 关的关卡数组 第 2 关初版存在死锁无法通关 编写 “可解性贪心验证” 测试发现死锁(3 个箭头互相阻挡),重新设计第 2 关布局并通过验证
碰撞动画与附加功能 豆包(大模型对话) 生成碰撞抖动 / 飞出动画代码,提示、星级、音效等附加功能 基本可用,动画速度偏快 / 抖动过猛 人工试玩后调整动画时长(飞出 0.30s、碰撞 0.50s)、抖动幅度,并修复 “飞出中的箭头仍占格导致快速连点误判碰撞” 的问题

记录 1:需求分析与代码骨架。 我向 AI 说明作业要求(四种方向箭头、路径检测、失误次数、至少 3 关、通关 / 失败界面、重新开始),AI 给出了 pygame 方案的整体结构:常量与颜色、关卡数据、Arrow 类、Game 类(加载关卡、坐标换算、路径检测、点击处理、绘制)。实际效果:基础骨架可以直接运行,棋盘和箭头正常显示,点击可消除箭头。

记录 2:路径检测与边界 Bug 修复。 AI 初版生成的向左检测代码为 for cc in range(c, -1, -1),会把箭头自身所在格也算进阻挡路径 —— 最左列的 ← 永远无法飞出。我编写了针对边界情况的单元测试(最左端 ←、最顶端 ↑、最右端 →、最底端 ↓ 均应可飞出且不越界),测试失败后把边界条件改为 range(c - 1, -1, -1),全部测试通过。这也是作业测试项 T03 的直接来源。

记录 3:关卡设计(死锁的发现与修复)。 AI 生成第 2 关初版布局后,我写了一个 “可解性验证器”:只要存在可消除箭头就一直消除,若最终仍有剩余则说明存在死锁。验证器立刻发现第 2 关剩余 3 个箭头互相阻挡、永远无法通关(例如同一行出现 → … ← 且二者中间无任何可移除的箭头)。我重新设计了第 2 关:(1,1)↓ 被 (4,1)← 阻挡、(2,3)→ 被 (2,5)↑ 阻挡,但阻挡者本身可被先消除,验证器确认三关全部可解。

记录 4:动画、音效与附加功能。 AI 生成的碰撞动画使用正弦抖动 + 红色光圈,飞出动画使用 “位移 + 缩小 + 淡出”。试玩后发现两个问题:一是动画速度偏快、反馈不清晰,我调整了 FLY_TIME 与 COLLIDE_TIME;二是飞出动画期间箭头仍占据棋盘格,导致快速连点时被误判为碰撞,我改为 “点击成功立即从棋盘移除,动画对象单独管理”。随后在 AI 辅助下增加了提示(H)、计时、星级评价与实时生成的提示音。

六、测试结果

1. 自动化测试

运行 python -m unittest test_game -v,共 20 项测试全部通过,覆盖:四方向路径检测与边界、点击消除 / 阻挡、失误耗尽、通关与关卡切换、重新开始、提示功能、星级计算、三关可解性、各界面离屏渲染冒烟测试。另外进行了真实窗口冒烟测试(游戏可正常启动、退出,音效初始化正常)。

2. 作业要求的测试项

编号 测试内容 预期结果 实际结果 是否通过
T01 点击前方无阻挡的箭头 箭头飞出棋盘并消失 箭头播放飞出动画后消失,剩余箭头数 -1 通过
T02 点击前方有阻挡的箭头 箭头不消失,失误次数减 1 箭头抖动并显示 “被挡住了!”,失误次数 3→2 通过
T03 点击位于边缘且朝向棋盘外的箭头 箭头正常消失,不发生越界错误 最上 / 最下 / 最左 / 最右的朝外箭头均正常飞出,无越界 通过
T04 消除本关全部箭头 显示通关并进入下一关 显示 “恭喜通关!” 与星级 / 用时,点击 “下一关” 进入第 2 关 通过
T05 失误次数耗尽 显示失败并允许重新开始 显示 “挑战失败”,点击 “重新开始” 恢复本关初始布局 通过
T06 游戏进行中重新开始 箭头布局和失误次数恢复 箭头、剩余数量、失误次数、计时全部复位 通过

七、PSP 表格

说明:本项目在 AI 辅助下整体耗时较短。

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

八、心得体会

AI 带来的帮助:本次作业中 AI 最明显的价值是 “把想法变成可运行代码” 的速度 —— 需求分析、界面绘制、路径检测等都可以在对话中快速得到初稿,节省了大量查文档和写样板代码的时间。尤其有用的是让 AI 生成测试用例与验证器:用 “可解性贪心验证” 自动找出关卡死锁,这类系统性检查比人工试玩可靠得多。

出现的问题:AI 生成的代码并非总是正确。本次遇到的典型问题有:路径检测边界处理错误(向左检测包含自身格)、关卡存在死锁、动画反馈不够清晰、飞出动画期间占格导致连点误判。这些问题大多只有通过运行和测试才能发现,说明 “AI 生成 + 人工验证” 缺一不可。

收获:一是对 pygame 的事件循环、动画与状态机有了更系统的理解;二是体会到 “先把规则形式化(路径检测)、再设计数据(关卡数组)、最后用测试固化行为” 的开发顺序;三是认识到 AI 是高效的工具,但读懂并验证 AI 给出的代码才是提交者自己的责任 —— 课程要求 “基本理解自己提交的代码” 正是这个意思。

posted @ 2026-09-21 13:27  槑孖  阅读(19)  评论(0)    收藏  举报