软件工程第二次作业
| 项目 | 内容 |
|---|---|
| 这个作业属于哪个课程 | H202601软件工程与软件工程实践 |
| 这个作业要求在哪里 | 2026 秋软件工程个人作业(第二次) |
| 这个作业的目标 | 使用 Python 和 AIGC 完成“一箭又一箭”小游戏 |
| 学号 | 102401433 |
| GitHub 仓库 | https://github.com/uzk20/homework2 |
一、项目展示
开始界面

游戏进行中

通关界面

失败界面

二、项目介绍
游戏规则
本游戏核心玩法为箭头消除闯关,棋盘上随机分布若干朝向上下左右(U/D/L/R)四个方向的箭头。玩家通过鼠标点击箭头触发消除判定:若被点击的箭头沿自身朝向到棋盘边界的路径中,没有任何其他箭头阻挡,该箭头会飞出棋盘并消失;若路径上存在其他箭头阻挡,则箭头无法消除,同时消耗一次失误机会。玩家需要按照合理顺序消除所有棋盘箭头,全部清空即可通关解锁下一关;若游戏预设的失误次数全部耗尽,则游戏失败,可选择重新游玩当前关卡。
界面设计
本次游戏共设计三个核心界面,界面布局简洁清晰、交互逻辑直观,适配新手玩家操作:
1. 开始界面:展示游戏名称、简易玩法提示、开始游戏按钮,是用户进入游戏的首个交互界面,操作入口明确;
2. 游戏主界面:核心游玩界面,包含棋盘游戏区域、实时关卡数显示、剩余可失误次数统计、重新开始按钮;
3. 结果界面:分为通关界面和失败界面,通关时展示闯关成功提示、进入下一关按钮;失败时展示游戏结束提示、重新开始按钮。
主要功能
本次开发完整实现作业要求的11项核心基础功能,具体如下:
1. 支持上下左右四个方向箭头的渲染与展示;
2. 实现箭头点击选中与交互判定功能;
3. 完成箭头飞行路径检测逻辑,精准判断是否可消除;
4. 实现无阻挡箭头飞出、消失的核心消除功能;
5. 实现有阻挡箭头无法消除、累计失误的功能;
6. 实时统计并展示剩余失误次数,次数耗尽触发游戏失败;
7. 全部箭头消除后触发关卡通关,自动解锁下一关;
8. 支持游戏中随时点击按钮重新开始当前关卡;
9. 内置多组可通关关卡数据,关卡难度循序渐进;
10. 实现游戏通关、失败的弹窗提示与界面切换;
三、实现思路
3.1 箭头与方向的表示
为了精准存储每一个箭头的位置和朝向,本次采用字典数据结构存储箭头信息。其中字典的键为箭头所在的(行, 列)坐标元组,字典的值为箭头方向字符,使用 U/D/L/R 分别对应上、下、左、右四个方向,数据存储简洁、查找效率高,便于后续路径检测和点击判定。
arrows = {
(0, 4): "R",
(1, 1): "R",
(2, 2): "U",
(3, 0): "D",
(1, 3): "L"
}
3.2 关卡数据
所有关卡数据统一通过字符串元组进行定义,每一个字符串代表棋盘的一行内容,字符串中的字符对应棋盘格子:. 代表空白无箭头格子,U/D/L/R 代表对应位置、对应方向的箭头。该方式让关卡数据直观易懂,新增、修改关卡仅需修改字符串内容,无需改动核心逻辑代码,拓展性极强。
LEVELS = [
(
"....R",
".R..D",
"R..UD",
".L.U.",
"L..D.",
),
(
"L..L.",
"U.D.R",
".R.R.",
"D..D.",
".L.R.",
),
(
"L.U.L",
".D..U",
"L.R.U",
".D..L",
"D.R.D",
),
]
3.3 路径检测(重点)
路径检测是本游戏的核心核心逻辑,通过自定义 can_fly 函数实现,主要功能是判断指定位置的箭头是否可以顺利飞出棋盘。
实现思路:首先根据箭头的方向字符,匹配对应的行列偏移量,向上行递减、向下行递增、向左列递减、向右列递增。从箭头的下一格位置开始,沿着固定方向逐格遍历棋盘:若遍历过程中遇到其他箭头,说明路径被阻挡,直接返回False,箭头无法消除;若遍历坐标超出棋盘边界,说明路径无阻挡,箭头可以顺利飞出,返回True。
def can_fly(arrows, row, col, rows, cols):
# 方向偏移映射:上下左右对应的行列变化
DIRECTION_DELTA = {"U": (-1, 0), "D": (1, 0), "L": (0, -1), "R": (0, 1)}
direction = arrows[(row, col)]
dr, dc = DIRECTION_DELTA[direction]
# 从箭头的下一格开始检测
r, c = row + dr, col + dc
# 逐格遍历路径
while 0 <= r < rows and 0 <= c < cols:
if (r, c) in arrows:
return False
r += dr
c += dc
return True
踩坑记录:函数初期编写时,循环边界判断仅写了 r >= 0 and c >= 0,只限制了坐标下限,没有设置棋盘行列上界。导致朝右、朝下的箭头检测时,行列坐标会无限递增,无法跳出循环,直接造成程序死循环卡死。后续排查日志、调试代码后,补齐了 r < rows and c < cols 上界判断。
3.4 动画与反馈
为提升游戏交互质感,本次新增飞出动画和错误碰撞反馈效果,优化用户游玩体验:
1. 飞出动画:当箭头判定可以消除时,将该箭头信息加入动画列表。游戏每一帧刷新时,根据箭头方向持续偏移像素坐标,实现匀速飞出效果,经过固定帧数渲染后,移除动画对象和原箭头,完成消失动画,过渡自然不生硬。
2. 碰撞错误反馈:当箭头被阻挡、无法消除时,触发失误反馈。首先将箭头颜色改为红色,同时利用sin三角函数生成周期性偏移量,让箭头产生左右晃动的动态效果。
四、AIGC 使用过程
本次游戏开发由AIGC辅助完成代码编写、功能调试等工作,共记录3次核心使用过程,均为真实开发场景,包含提问、AI产出、实际效果、人工修改四个核心要素,具体如下:
1. 路径检测代码的生成与修改
我的提问:用Python写一个四方向的路径检测函数,输入箭头坐标、棋盘行列数,判断箭头沿自身方向到棋盘边界之间是否有其他箭头阻挡,有阻挡返回False,无阻挡返回True。
AI 提供的内容:给出了完整的DIRECTION_DELTA方向偏移字典,同时编写了can_fly逐格遍历检测代码,整体逻辑框架正确,实现了逐格判断是否存在箭头阻挡的核心功能。
实际效果:代码整体思路符合需求,但边界判断存在漏洞,仅判断了坐标大于等于0的下限,未设置棋盘行列的上界,朝右、朝下的箭头检测会触发程序死循环,导致游戏卡死。
我的修改:通过打印日志排查问题,发现坐标会无限增大、无法退出循环。修改while循环条件,补充 r < rows and c < cols 上界判断,限定坐标始终在棋盘范围内遍历,修复死循环bug,函数运行正常。
2. 方向绘制角度错误修复
我的提问:使用Python图形库,通过旋转三角形的方式绘制上下左右四个方向的箭头,保证每个方向箭头朝向准确。
AI 提供的内容:给出了三角形顶点坐标定义和坐标旋转变换公式,通过角度换算实现箭头方向切换,完成四方向箭头绘制代码。
实际效果:绘制完成后,上下方向箭头朝向颠倒,D(向下)箭头被绘制成朝上,U(向上)箭头被绘制成朝下。初期误以为是路径检测逻辑出错,多次调试。
我的修改:逐行核对旋转公式,发现AI代码中使用了负角度进行旋转,导致方向倒置。删除角度负号,使用标准的 math.radians(angle) 角度换算,重新校准四个方向的旋转角度,纠正了箭头朝向。
3. 可通关关卡数据生成与优化
我的提问:帮我生成3组5×5的棋盘关卡数据,包含U/D/L/R四种箭头,要求关卡无死锁、可正常通关,难度循序渐进。
AI 提供的内容:输出了三组符合格式的字符串元组关卡数据,箭头分布均匀,满足棋盘格式要求。
实际效果:手动试玩测试时,发现部分关卡存在箭头相互阻挡的死锁问题,没有可行的消除顺序,无法通关,不符合游戏开发需求。
我的修改:遵循「从边缘向内依次消除」的通关逻辑,逐关试玩排查,调整死锁位置的箭头方向和坐标,重新排布关卡箭头布局。优化后所有关卡均存在合理通关顺序。
五、测试结果
本次针对作业要求的6项核心测试用例进行完整功能测试,覆盖常规操作、边界场景、异常场景,所有功能均测试通过,具体测试结果如下:
| 编号 | 测试内容 | 预期结果 | 实际结果 | 是否通过 |
|---|---|---|---|---|
| T01 | 点击前方无阻挡的箭头 | 箭头飞出棋盘并消失 | 与预期一致 | 通过 |
| T02 | 点击前方有阻挡的箭头 | 箭头不消失,剩余失误次数减1 | 与预期一致,剩余失误次数从3变2 | 通过 |
| T03 | 点击位于边缘且朝向棋盘外的箭头 | 箭头正常消失,不发生越界错误 | 与预期一致 | 通过 |
| T04 | 消除本关全部箭头 | 显示通关并进入下一关 | 与预期一致 | 通过 |
| T05 | 失误次数耗尽 | 显示失败并允许重新开始 | 与预期一致 | 通过 |
| T06 | 游戏进行中重新开始 | 箭头布局和失误次数恢复初始状态 | 与预期一致 | 通过 |
六、PSP 表格
结合本次游戏开发全流程,对各阶段任务的预估耗时、实际耗时进行统计记录,整体开发节奏合理,具体数据如下:
| 任务 | 预估耗时(小时) | 实际耗时(小时) | 差异(小时) |
|---|---|---|---|
| 需求分析与游戏设计 | 1 | 1 | 0 |
| Python 与图形库学习 | 2 | 2.5 | +0.5 |
| 游戏界面实现 | 2 | 2 | 0 |
| 路径与碰撞逻辑实现 | 2 | 3 | +1 |
| 关卡设计 | 1 | 1.5 | +0.5 |
| AIGC 辅助开发 | 1 | 1 | 0 |
| 测试与修改 | 1 | 1.5 | +0.5 |
| README 与博客撰写 | 1 | 1.5 | +0.5 |
| 合计 | 11 | 13 | +2 |
七、心得体会
本次借助Python和AIGC完成“一箭又一箭”小游戏开发,让我收获了满满的实战经验,也深刻体会到软件工程开发的严谨性,颠覆了我以往简单的编程认知。
在本次开发中,AIGC成为了高效的辅助工具,能够快速帮我搭建代码框架、生成基础功能代码、提供算法思路,极大缩短了开发周期。但我也清晰认识到不能盲目信任AIGC生成的代码。AI擅长处理通用、基础的逻辑,但对于边界条件、细节逻辑、场景适配、数据合理性等问题,经常出现漏洞。比如本次遇到的路径检测死循环、箭头绘制方向颠倒、关卡死锁无解等问题,都是AI输出内容的典型缺陷,这些细节问题无法靠AI自动规避,必须依靠自己逐行读代码、调试测试、排查问题才能修复。
同时,本次开发让我积累了大量真实的排错经验。从最初边界判断缺失导致的程序卡死,到角度公式错误导致的界面异常,再到关卡数据不合理导致的功能bug,每一个问题都让我明白,编程开发没有一蹴而就的成果,细节决定程序的成败。以往我习惯一次性写完所有代码再运行,本次开发我尝试了逐模块测试的思路:先搭建窗口基础框架,再实现箭头渲染,接着完成点击交互、路径检测,最后优化动画和关卡。这种模块化开发方式让bug定位更精准,调试效率大幅提升,也让我理解了软件工程模块化、分层开发的核心意义。

浙公网安备 33010602011771号