2026 秋软件工程个人作业(第二次)

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

一、项目展示

本项目是一款基于 Python 和 Pygame 开发的箭头解谜游戏。玩家需要观察箭头方向,判断箭头前方是否存在阻挡,并按照正确顺序点击箭头。游戏加入了计时评级、关卡解锁、最佳成绩保存、音乐音效、主题切换、自动求解和提示功能。实现上,我将项目分为关卡数据、游戏逻辑、进度存档和界面控制几个模块,并通过状态机管理首页、选关页、游戏页和结果页之间的跳转。
完整视频演示:https://github.com/Yi-shang0101/arrow_game/blob/main/演示视频.mkv

1、菜单界面

菜单界面有着“开始游戏”、“选择关卡”、“设置”和“退出游戏”选项
01_menu

2、游戏过程

游戏成功流程如下(成功会有掌声)😊
2026-09-1819-37-06-ezgif.com-video-to-gif-converter
游戏失败流程如下(失败会有罐头笑声)🤣
2026-09-1819-41-25-ezgif.com-video-to-gif-converter

二、项目介绍

1、游戏玩法

游戏棋盘由若干带方向的箭头组成,箭头方向包括上、下、左、右四种。

玩家需要观察箭头前方的路径,并按照合适的顺序点击:

  • 如果箭头与棋盘边界之间没有其他箭头,箭头可以飞出棋盘;
  • 如果前方存在其他箭头,箭头会被阻挡并播放碰撞反馈;
  • 点击被阻挡的箭头会消耗一次失误机会;
  • 每关初始有 3 次失误机会;
  • 清空棋盘中的全部箭头后,本关通关;
  • 失误次数耗尽或超过时间限制后,本关失败。

2、关卡和评级

游戏目前包含 5 个固定关卡:

关卡 名称 棋盘大小 箭头数量 难度
1 初识方向 4×4 10 普通
2 交错路径 5×5 19 普通
3 层层解锁 6×6 30 普通
4 纵横迷阵 7×7 40 困难
5 极限交织 8×8 51 专家

普通难度的评级规则如下:

完成时间 结果
≤15 秒 A
≤25 秒 B
≤35 秒 C
>35 秒 失败

困难和专家关卡会根据棋盘规模增加允许时间。只有前一关获得 A 或 B 评价,才能解锁下一关。已经解锁的关卡可以通过“选择关卡”页面反复挑战,并保存最佳成绩。

3、主要功能

本项目实现了以下功能:

  1. 开始界面和独立的关卡选择界面;
  2. 上、下、左、右四种方向箭头;
  3. 箭头路径阻挡判断;
  4. 箭头飞出动画和碰撞反馈;
  5. 失误次数和重新开始功能;
  6. 游戏成功和失败页面;
  7. A、B、C 时间评级;
  8. 最佳成绩保存和关卡解锁;
  9. 音乐音量和音效音量调节;
  10. 白天、护眼和夜间三种显示模式;
  11. H 键提示当前可以消除的箭头;
  12. A 键和“自动求解 A”按钮;
  13. 首页背景箭头悬停高亮和点击发射;
  14. 成功、失败、按钮和箭头操作音效;

4、页面组成

页面 主要功能
首页 开始游戏、选择关卡、设置和退出游戏
选择关卡页 查看关卡难度、解锁状态和最佳成绩
规则说明页 显示当前关卡规则和评级要求
游戏页 显示棋盘、计时、剩余箭头和失误次数
通关页面 显示完成时间、评级和后续操作
失败页面 显示失败原因并提供重新开始等操作
设置页面 调节音乐、音效和显示主题

5、项目特色

本项目在基础玩法上增加了以下功能:

  • 根据关卡难度设置不同的评级时间;
  • 支持反复挑战并保存最佳成绩;
  • 提供当前关卡自动求解功能;
  • 支持音乐、音效和主题设置;
  • 首页背景箭头具有悬停和点击交互效果;
  • 使用独立模块管理游戏逻辑、关卡、存档和界面;
  • 使用自动化测试验证核心功能。

三、程序结构与实现思路

1、关卡数据表示

关卡数据保存在 levels.py 中,使用二维列表表示棋盘,U/D/L/R 分别表示上、下、左、右,None 表示空格。

LEVELS = [
    {
        "name": "初识方向",
        "difficulty": "normal",
        "description": "先找朝向边界的箭头,逐步打开通路。",
        "board": [
            [None, "D", None, "R"],
            ["L", None, "U", None],
            ["L", "L", "U", "U"],
            [None, None, "D", "U"],
        ],
    },
]

项目一共设计了 5 个固定关卡,关卡规模从 4×4 逐渐增加到 8×8。

2、方向和时间评级

logic.py 中使用方向增量统一处理四种箭头

DIRECTIONS = {
    "U": (-1, 0),
    "D": (1, 0),
    "L": (0, -1),
    "R": (0, 1),
}

不同难度拥有不同的评级时间:

DIFFICULTY_RULES = {
    "normal": {
        "label": "普通",
        "A": 15.0,
        "B": 25.0,
        "C": 35.0,
        "time_limit": 35.0,
    },
    "hard": {
        "label": "困难",
        "A": 25.0,
        "B": 40.0,
        "C": 55.0,
        "time_limit": 55.0,
    },
    "expert": {
        "label": "专家",
        "A": 35.0,
        "B": 55.0,
        "C": 75.0,
        "time_limit": 75.0,
    },
}

评级函数如下:

def time_grade(seconds, rules=None):
    rules = rules or DIFFICULTY_RULES["normal"]

    if seconds <= rules["A"]:
        return "A"
    if seconds <= rules["B"]:
        return "B"
    if seconds <= rules["C"]:
        return "C"

    return None

3、箭头路径检测

核心函数 can_exit() 位于 logic.py 中。

它从当前箭头的下一格开始,沿箭头方向逐格扫描。如果扫描到其他箭头,就说明当前箭头被阻挡。

def can_exit(board, row, col):
    """沿射线检查到边界;阻挡者的方向不影响判断。"""
    if not (0 <= row < len(board) and
            0 <= col < len(board[0])):
        return False

    direction = board[row][col]

    if direction is None:
        return False

    dr, dc = DIRECTIONS[direction]
    r, c = row + dr, col + dc

    while 0 <= r < len(board) and 0 <= c < len(board[0]):
        if board[r][c] is not None:
            return False

        r += dr
        c += dc

    return True

4、点击箭头和碰撞处理

Game.click() 负责处理玩家点击:

def click(self, row, col, automatic=False):
    if (
        self.state != "PLAYING"
        or self.animation
        or (self.auto_solving and not automatic)
    ):
        return "ignored"

    if not (
        0 <= row < len(self.board)
        and 0 <= col < len(self.board[0])
    ):
        return "ignored"

    direction = self.board[row][col]

    if direction is None:
        return "ignored"

    self.hint = None
    kind = "exit" if can_exit(
        self.board, row, col
    ) else "bump"

    if kind == "bump":
        self.mistakes -= 1

    self.animation = Animation(
        row, col, direction, kind
    )

    return kind

如果箭头可以飞出,就创建 exit 动画;如果被阻挡,就创建 bump 动画并扣除一次失误机会。

箭头不会在点击瞬间删除,而是在动画完成后删除:

if animation.kind == "exit":
    self.board[animation.row][animation.col] = None

    if self.remaining == 0:
        self.grade = time_grade(
            self.elapsed,
            self.level_rules
        )
        self.progress.record(
            self.level_index,
            self.elapsed,
            self.time_limit
        )
        self.state = (
            "ALL_CLEAR"
            if self.level_index == len(self.levels) - 1
            else "LEVEL_CLEAR"
        )

这样可以防止动画播放过程中重复删除棋盘数据。

5、自动求解算法

自动求解函数也位于 logic.py

def solve(board):
    """返回一种解法;死锁返回 None。"""
    validate_board(board)

    work = [row[:] for row in board]
    result = []

    while any(
        cell is not None
        for row in work
        for cell in row
    ):
        moves = available_moves(work)

        if not moves:
            return None

        for r, c in moves:
            work[r][c] = None
            result.append((r, c))

    return result

算法会复制一份临时棋盘,在临时棋盘上不断删除当前可以飞出的箭头,并记录删除顺序。

游戏实际运行时,自动求解仍然按照普通飞出动画执行:

def auto_solve(self):
    if (
        self.state != "PLAYING"
        or self.animation
        or self.auto_solving
    ):
        return False

    solution = solve(self.board)

    if not solution:
        return False

    self.auto_queue = list(solution)
    self.auto_solving = True
    self.auto_step_started = False
    self.hint = None
    self.hint_time = 0.0

    return True

自动求解期间会锁定玩家的手动棋盘点击,但仍然可以重新开始或返回首页。

四、AIGC 使用过程

4.1 使用工具

本项目主要使用 ChatGPT/Codex 辅助完成需求分析、代码编写、调试、测试和文档整理。

AIGC 主要参与了以下工作:

  • 分析游戏规则和功能需求;
  • 设计项目文件结构;
  • 编写路径检测和游戏状态逻辑;
  • 生成和验证关卡数据;
  • 编写界面、动画和音频代码;
  • 编写自动化测试;
  • 根据运行结果定位和修复问题;
  • 整理 README、测试报告和博客内容。

4.2 代表性协作记录

4.2 AIGC 协作过程总览

阶段 使用的 AIGC 工具 我的需求 AI 完成内容 实际效果 人工修改或验证
需求拆解与基础架构 ChatGPT/Codex 先分析“一箭又一箭”的玩法,再设计 Python 游戏结构 设计 main.pylogic.pylevels.pyprogress.py 的模块划分 项目形成了逻辑、界面、关卡和存档分离的结构 我确认采用 Pygame、二维棋盘和状态机,并根据课程要求调整功能范围
路径判断 ChatGPT/Codex 实现上、下、左、右四个方向的箭头检测 生成 DIRECTIONScan_exit() 和阻挡判断逻辑 四个方向均可正确判断,箭头能够区分畅通和阻挡 我补充边界、隔空阻挡、身后箭头、空格点击和越界测试,并要求修正坐标处理问题
基础关卡 ChatGPT/Codex 设计至少 3 个可以正常通关的关卡 生成基础关卡棋盘和 solve() 求解器 初始三关均能够通过求解器找到合法通关顺序 我根据作业要求检查关卡数量,并使用求解器和实际运行验证关卡可解
计时和评级 ChatGPT/Codex 加入 A≤15 秒、B≤25 秒、C≤35 秒和超时失败 增加计时器、time_grade() 评级函数和结果页用时显示 普通关卡能够按时间显示 A、B、C 或失败 我要求计时从“开始挑战”后才开始,并补充低帧率、评级边界和最后一支箭头动画测试
首页布局调整 ChatGPT/Codex 根据截图重新调整标题、按钮和背景元素 修改按钮尺寸、居中布局、悬停高亮和背景箭头颜色 首页布局更加集中,文字和按钮没有明显重叠 我提供界面截图并提出具体调整要求,通过重新渲染截图检查位置、颜色和高亮效果
音乐和音效 ChatGPT/Codex 加入主菜单音乐、游戏音乐、成功、失败和按钮音效 编写 AudioManager,统一加载、播放和停止音频 页面切换时能够切换音乐,操作时播放对应音效 我整理并提供音频资源,验证音频设备不可用时能够自动静音,并检查结果音效能及时停止
困难和专家关卡 ChatGPT/Codex 增加 7×7 困难关和 8×8 专家关,并根据难度调整评级时间 生成第 4、5 关,并配置困难和专家评级阈值 五个关卡均能通过求解器验证,旧版存档可以继续使用 我检查关卡规模、难度和评分要求,并要求增加旧存档迁移测试
自动求解 ChatGPT/Codex 增加“自动求解 A”按钮和 A 键快捷键 调用当前棋盘的 solve(),按照正常动画自动完成 自动求解会逐支播放飞出动画,并正常进行计时和结算 我要求自动求解时锁定手动棋盘点击,但保留重开和返回首页功能,并通过测试验证

代表性协作过程

1、首页ui调整
image
2、音乐和音效的调节
image
3、困难和专家关卡的设计
image

五、测试结果

编号 测试内容 预期结果 实际结果 是否通过
T01 点击前方无阻挡的箭头 箭头飞出棋盘并消失 动画结束后箭头从棋盘中删除 通过
T02 点击前方有阻挡的箭头 箭头不消失,失误次数减 1 箭头返回原位,失误次数减少 1 通过
T03 点击位于边缘且朝向棋盘外的箭头 箭头正常消失,不发生越界 上、下、左、右边缘均能正常处理 通过
T04 消除本关全部箭头 显示通关结果并进入后续流程 显示评级和通关页面 通过
T05 失误次数耗尽 显示失败并允许重新开始 第三次碰撞后进入失败页面 通过
T06 游戏进行中重新开始 棋盘和失误次数恢复初始状态 棋盘、失误次数、提示和动画均被重置 通过

额外测试:

测试项目 测试内容 实际结果 是否通过
计时评级 测试 15、25、35 秒边界 A、B、C 评级符合设定 通过
超时失败 完成时间超过当前难度限时 进入失败页面 通过
关卡解锁 前一关获得 B 或 A 下一关解锁 通过
C评价限制 前一关只获得 C 下一关保持锁定 通过
最佳成绩 重复挑战并取得更快成绩 只保存更快成绩 通过
存档读取 关闭游戏后重新启动 成绩和解锁状态保留 通过
自动求解 点击“自动求解 A” 按正常动画完成当前关卡 通过
设置页面 拖动音乐和音效滑块 音量立即生效 通过
主题切换 切换白天、护眼和夜间模式 页面颜色立即更新 通过
音频切换 成功、失败和返回操作 对应音效正常播放或停止 通过
背景箭头 悬停和点击首页背景箭头 箭头高亮并播放装饰动画 通过

六、PSP 表格

任务 预计耗时(小时) 实际耗时(小时) 差异(小时)
需求分析与游戏设计 0.8 1.2 +0.4
Python 与 Pygame 学习 1.5 1.0 -0.5
游戏界面实现 1.0 1.5 +0.5
路径与碰撞逻辑实现 1.5 1.5 0
关卡设计与求解验证 1.5 1.5 0
AIGC 辅助开发 2.0 2.5 +0.5
测试与问题修复 1.5 2.2 +0.7
README 与博客撰写 1.2 1.5 +0.3
合计 11.0 12.9 +1.9

七、心得体会

八、心得体会

通过本次“一箭又一箭”小游戏的开发,我认识到一个看似简单的点击游戏,实际上包含了需求分析、数据结构设计、界面设计、事件处理、状态管理、动画、音频、存档和测试等多个软件工程问题。

最开始我认为只需要绘制一个棋盘和几支箭头即可完成游戏,但实际开发后发现,路径判断才是游戏的核心。程序不仅要判断箭头前方是否有阻挡,还要处理边界箭头、隔着空格的阻挡、碰撞反馈、失误次数和动画结束后的棋盘更新。通过将游戏逻辑放在 logic.py 中,将界面和事件处理放在 main.py 中,程序结构更加清晰,也方便单独测试核心规则。

AIGC 在本次开发中提高了我的开发效率。ChatGPT/Codex 可以帮助我快速拆解需求、生成代码框架、设计测试用例和定位错误。例如,在路径检测、计时评级、关卡解锁、音频管理和自动求解等功能中,AI 提供了较多实现思路。但是,AI 生成的代码不能直接作为最终结果,仍然需要通过运行程序、查看截图和执行测试来判断是否正确。

开发过程中也遇到了一些问题。例如,模拟鼠标事件时出现过坐标类型问题;动画期间重复点击可能造成棋盘状态错误;中文字体缺少部分字符时会出现显示异常;成功或失败音效在切换页面时不能立即停止。通过增加边界测试、锁定动画期间输入、增加字体回退机制和使用独立音频通道,这些问题得到了修复。

本项目最终实现了五个不同难度的关卡、A/B/C 时间评级、关卡解锁、最佳成绩保存、音乐音效、主题切换、提示、自动求解和首页背景箭头互动等功能,并完成了 48 项自动化测试。通过这次开发,我进一步理解了二维数组、方向增量、状态机、模块化设计和自动化测试的作用。

不过,我也认识到自己对 Pygame 底层机制、音频系统和游戏架构的理解还不够深入。后续如果继续完善项目,我希望增加随机生成可解关卡、撤销操作、更加详细的成绩统计,并尝试将游戏打包成 Windows 可执行文件。

总体来说,AIGC 可以作为编程学习和项目开发的辅助工具,但不能代替开发者进行思考和验证。只有理解代码的基本原理,并通过测试和实际运行检查结果,才能真正完成一个可靠的软件项目。

posted @ 2026-09-18 22:13  Yishang  阅读(4)  评论(0)    收藏  举报