软件工程第二次作业

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

一、项目展示

开始界面

开始界面

游戏进行中

playing

通关界面

通关界面

失败界面

失败界面

二、项目介绍

游戏规则

本游戏核心玩法为箭头消除闯关,棋盘上随机分布若干朝向上下左右(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定位更精准,调试效率大幅提升,也让我理解了软件工程模块化、分层开发的核心意义。

posted @ 2026-09-16 19:54  uzk  阅读(6)  评论(0)    收藏  举报