软件工程课程第二次个人作业

一、作业信息

项目 内容
这个作业属于哪个课程 [https://edu.cnblogs.com/campus/fzu/202601SofwareEngineering]
这个作业要求在哪里 [https://edu.cnblogs.com/campus/fzu/202601SofwareEngineering/homework/16717]
这个作业的目标 使用 Python 和 AIGC 完成“一箭又一箭”小游戏,熟悉对AI的使用结果调试
学号 [102401622]
GitHub 仓库 [https://github.com/drkalerq/work1]

二、项目展示

  • 开始界面:标题“一箭又一箭” + 玩法提示 + “开始游戏”按钮。
    image

  • 游戏过程:棋盘上的彩色箭头、顶部信息栏(关卡 / 剩余箭头 / 剩余失误)、底部“重新开始 / 提示”按钮。
    image

  • 通关界面:半透明遮罩 + “本关通关!” + “下一关”按钮。
    image

  • 失败界面:半透明遮罩 + “失败” + “重新开始”按钮。
    image


三、项目介绍

游戏规则

棋盘由网格组成,每格最多一个箭头,方向为上 / 下 / 左 / 右。点击箭头时:

  • 若它前进方向上直到棋盘边界之间没有其他箭头,箭头沿该方向飞出棋盘并消失;
  • 路径上存在其他箭头,箭头不能飞出,会晃动并变红作为碰撞反馈,同时消耗 1 次失误;
  • 清空本关全部箭头 → 通关,进入下一关;失误次数耗尽 → 失败,可重新开始。

界面与功能

  • 三个界面:开始界面、游戏界面、通关/失败界面(全部用 Pygame 绘制)。
  • 游戏界面显示:当前关卡名、剩余箭头数、剩余失误数、棋盘、重新开始按钮、提示按钮。
  • 动画反馈:箭头飞出有平移淡出动画;被挡时有左右晃动 + 变红的反馈。
  • 4 个可通关关卡(3×3 → 6×6,难度递增),均经程序验证存在通关顺序。
  • 扩展功能:提示按钮(高亮一个当前可飞出的箭头,复用关卡求解逻辑)。

特色

  • 核心逻辑(game.py)与界面(main.py)分离,逻辑可单独用 unittest 测试,不依赖 Pygame。
  • 自带关卡可解性求解器,提交前自动校验每一关都能通关,避免“看似能玩其实死局”。

四、实现思路

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

  • 棋盘用字典 arrows: (row, col) -> Arrow 保存当前还活着的箭头,row/col 为网格坐标。
  • 方向用字符 'U'/'D'/'L'/'R',并映射到位移量,便于统一处理四个方向:
class Arrow:
    DIRS = {'U': (-1, 0), 'D': (1, 0), 'L': (0, -1), 'R': (0, 1)}
  • 关卡用字典描述:rows / cols / mistakes / arrows(箭头列表 (行, 列, 方向))。
    这样做的好处是“数据即关卡”,改关卡只改 levels.py,不用动逻辑代码。

2. 路径检测

判断某个箭头能否飞出,核心是沿它的方向一格一格走,检查到边界前是否撞到别的箭头

def is_path_clear(self, arrow):
    dr, dc = Arrow.DIRS[arrow.direction]
    r = arrow.row + dr
    c = arrow.col + dc
    while 0 <= r < self.rows and 0 <= c < self.cols:   # 还在棋盘内才检查
        if (r, c) in self.arrows:
            return False          # 路上有别的箭头 -> 被挡住
        r += dr
        c += dc
    return True                     # 一路畅通直到边界 -> 可飞出

关键点:while 的循环条件 0 <= r < rows and 0 <= c < cols 同时完成了边界判断——
一旦走出棋盘就停止,因此不会数组越界,天然处理了“边缘且朝外的箭头”(T03)。
点击时根据返回值决定飞出还是碰撞:

def click(self, row, col):
    if self.state != 'playing':
        return None
    arrow = self.arrows.get((row, col))
    if arrow is None:
        return None
    if self.is_path_clear(arrow):
        del self.arrows[(row, col)]          # 飞出并消失
        if not self.arrows:
            self.state = 'won'
        return ('fly', arrow)
    else:
        self.mistakes += 1                    # 碰撞:失误 +1
        if self.mistakes >= self.mistakes_allowed:
            self.state = 'lost'
        return ('block', arrow)

3. 关卡可解性求解(保证每关能通关)

因为“移除一个箭头只会减少阻挡、不会增加阻挡”,所以只要存在通关顺序,
贪心法(反复移除任意一个当前可飞出的箭头)一定能找到。若某一步没有任何箭头能飞出却还有剩余,则本关死局。

def is_level_solvable(level):
    remaining = {(r, c): d for (r, c, d) in level['arrows']}
    rows, cols = level['rows'], level['cols']
    def clear(r, c, d):
        dr, dc = Arrow.DIRS[d]
        r2, c2 = r + dr, c + dc
        while 0 <= r2 < rows and 0 <= c2 < cols:
            if (r2, c2) in remaining:
                return False
            r2 += dr; c2 += dc
        return True
    while remaining:
        progressed = False
        for (r, c), d in list(remaining.items()):
            if clear(r, c, d):
                del remaining[(r, c)]; progressed = True; break
        if not progressed:
            return False
    return True

提交前我对 levels.py 里 4 关逐一调用该函数,全部返回 True,确认都可通关。


五、AIGC 使用过程

子任务 借助何种 AIGC 技术 AI 实现或提供了什么 效果如何 人工修改
路径检测算法 hy3 给出四方向统一用位移量 DIRS 表示、并沿方向遍历检测是否撞箭头的 is_path_clear 思路与代码 向上/下/左/右判断均正确,且用 while 边界条件天然避免越界 我补充了中文注释,并单独写了 T03 边界用例验证“边缘朝外箭头不报错”
关卡可解性验证 hy3 给出贪心求解器 is_level_solvable,自动判断关卡是否存在通关顺序 能正确识别死局,我据此校验并挑选了 4 个可通关关卡 我把它也用于“提示”功能(找当前可飞出的箭头),并在博客中解释其原理
碰撞动画与反馈 hy3 补全“被挡箭头晃动 + 变红”的 shaking 计时器,以及“飞出”平移动画的 flying 列表 晃动与飞出动画基本可用,视觉反馈清晰 我调整了晃动幅度(amp=6)和飞出速度(FLY_SPEED=16),并给箭头加了黑色描边更清晰

六、测试结果

环境:Python 3.13 + Pygame 2.6,运行 python -m unittest test_game -v9 项全部通过

编号 测试内容 预期结果 实际结果 是否通过
T01 点击前方无阻挡的箭头 箭头飞出棋盘并消失 剩余箭头数 -1,返回 fly
T02 点击前方有阻挡的箭头 箭头不消失,失误次数减 1 箭头仍在,失误 +1,返回 block
T03 点击位于边缘且朝向棋盘外的箭头 正常消失,不越界报错 四角/四边朝外箭头均 fly,无异常
T04 消除本关全部箭头 显示通关(state=won) 最后一箭点击后 state=='won'
T05 失误次数耗尽 显示失败(state=lost) 失误达上限后 state=='lost'
T06 游戏进行中重新开始 箭头布局和失误次数恢复 restart() 后箭头数、失误、状态均复位
全部关卡可通关 4 关均存在通关顺序 is_level_solvable 全部为 True
整关模拟通关 按策略能逐关通关 TestPlayThrough 4 关均到达 won

七、PSP 表格

下表为示例,请按你自己的真实耗时填写“实际耗时”一列。

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

八、心得体会

  • AI 带来的帮助:路径检测、可解性求解、碰撞动画这类“有固定模式”的代码,AI 一次就能给出可运行骨架,
    我主要在做“理解与微调”——比如UI设计提示,重启游戏失效的修复。
  • 自己的收获:把“游戏规则”翻译成“数据结构 + 算法”的过程,比我预想中更锻炼抽象能力;
    尤其是 is_path_clearwhile 边界条件同时完成越界保护、碰撞判定用“移除箭头只会减少阻挡”来说明贪心正确的那一步,
    让我真正理解了为什么这个游戏“一定存在通关顺序”。在AI生成结果后部分功能可能无法实现,要经过测试后才能发现问题。
posted @ 2026-09-17 19:02  toumaa  阅读(9)  评论(0)    收藏  举报