跳到正文

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

2026 秋软件工程个人作业(第二次):I like arrow

项目 内容
这个作业属于哪个课程 H202601 软件工程与软件工程实践
这个作业要求在哪里 2026 秋软件工程个人作业(第二次)
这个作业的目标 使用 Python 和 AIGC 完成“一箭又一箭”小游戏 ,并且进行测试还有优化
学号 102401533
GitHub 仓库 ddxww/arrow-order

前言

GitHub Release 已发布:https://github.com/ddxww/arrow-order/releases/tag/v1.0.4
本次设计游戏花费了大量的额度,有没有好心人募捐我100美元上架steam。
演示视频在b站发布了一版,并非最新的版本,应该算是1.0:
https://www.bilibili.com/video/BV1mGep6AE5i/?spm_id_from=333.1387.list.card_archive.click&vd_source=223f93c9fabb753053717ab58090373a
2.0演示视频:
https://www.bilibili.com/video/BV1gVeP6SE72/?spm_id_from=333.1387.homepage.video_card.click
游戏的画面大概如下:
软件工程作业更新 2.0 演示

一、项目展示

我把游戏命名为《一箭又一箭·箭序》。项目使用 Python 3.13 和 pygame-ce 2.5.8 开发,默认窗口大小为 960×800,也支持按窗口大小缩放。游戏可以直接运行源码,也已经打包为 Windows EXE。

界面没有沿用参考项目的浅绿色方案,而是使用纯黑背景、深灰面板、浅紫主色、暖金色提示和亮莓红色碰撞反馈。后续在原有界面上加入了黑色高级 HUD 视觉:细网格背景、实时状态芯片、棋盘负载进度条、任务选择难度刻度和通关报告层。棋盘、箭头和按钮都由 Pygame 绘制,中文字体随项目一同分发。

1. 开始界面

开始页提供“开始游戏”“关卡选择”和“无尽模式”入口,右上角可以分别开关音乐和音效。

游戏开始界面

2. 关卡选择

普通模式共有 6 个固定关卡。初始只开放第一关,通关后逐关解锁;已经解锁的关卡可以重复挑战,关卡卡片会记录最好成绩。

关卡选择界面

3. 游戏过程

游戏页上方显示当前关卡、剩余箭头和剩余失误次数,中间是棋盘,下方有提示、重新开始和返回按钮。鼠标移到箭头上时,所在格会高亮。

游戏过程界面

路径畅通时,箭头会沿自身方向飞出棋盘,动画结束后再从数据中删除。若路径上有其他箭头,当前箭头会前冲、回弹并变红,同时标出最近的阻挡者。

箭头碰撞反馈

使用提示后,程序只高亮一个当前可以消除的箭头,不会自动替玩家完成操作。

提示高亮状态

每关有 3 次失误机会。机会只剩 1 次时,游戏会出现红色视野边缘和双拍心跳提示;机会耗尽后进入失败页面。清空棋盘则显示本关用时、剩余机会、提示使用次数和星级。

单关通关结算

挑战失败:
挑战失败提示
挑战失败结算

无尽模式累计通关 3 次后,会解锁一次特殊 CG。这个奖励不会改变普通关卡的解锁进度和最好成绩。

无尽模式特殊 CG

完整玩法演示:哔哩哔哩视频。上面的图片均来自我的 GitHub 项目展示区,由项目程序实际渲染,不是设计稿。

二、项目介绍

1. 游戏规则

棋盘的每个格子为空,或者放置一支朝上、下、左、右的箭头。玩家用鼠标左键点击箭头后,程序从箭头前方的相邻格开始,沿其方向一直检查到棋盘边界。

  • 路径上没有其他箭头:播放飞出动画,随后消除该箭头。
  • 路径上存在其他箭头:箭头保留在原位,播放碰撞反馈,并扣除一次失误机会。
  • 阻挡者的方向不影响判断,两个箭头之间即使隔着空格也仍然会阻挡。
  • 点击空格、棋盘外、已消除的位置或使用右键,不会改变棋盘,也不会扣除次数。
  • 清空本关全部箭头后通关;3 次机会用完后失败,可以重新开始本关。

动画期间只接收一个棋盘动作,防止重复点击造成一次删除多个箭头或连续扣除机会。重开、静音和关闭窗口仍然可以使用。

2. 固定关卡

作业要求至少 3 个可通关关卡,我设计了 6 个固定关卡,难度按棋盘大小、箭头数量和阻挡关系逐步增加。每一关都含有四种方向。

关卡 名称 棋盘大小 箭头数 三星目标时间 设计重点
1 初识箭序 5×5 9 45 秒 边缘飞出与简单阻挡
2 留意空隙 5×5 12 55 秒 隔着空格也会阻挡
3 交错之间 6×6 19 75 秒 横向和纵向依赖交错
4 逐一解锁 6×6 23 85 秒 连续解除多层阻挡
5 四向交织 7×7 31 110 秒 更长的路径与更高密度
6 最后之序 7×7 36 125 秒 综合四方向判断

关卡模板不会在游戏过程中被修改。开始和重开时,程序重新复制一份棋盘,因此不会出现重玩后布局缺失的问题。

3. 附加功能

完成基础玩法后,我加入了几项附加功能:

  • 每次挑战有 3 次提示,提示会高亮一个当前可以飞出的箭头,但不会替玩家点击。
  • 关卡逐关解锁,并将最好成绩、星级和音乐设置保存到本地。
  • 通关至少获得 1 星;剩余 2 次及以上机会再得 1 星;在目标时间内完成再得 1 星。
  • 音效和背景音乐可以分别关闭。背景音乐与操作音效由项目代码合成,没有使用商业游戏素材。
  • 无尽模式会随机生成 5×5 至 7×7 的可解棋盘,不改变普通关卡进度。
  • 游戏右下角提供奖杯成就入口,目前包含三个成就:“👍”需要完成全部六个普通关卡;“完美通关”需要六关全部达到三星;“我爱arrow”需要无尽模式累计通过三关。未完成时显示锁定状态和当前进度,解锁状态会保存到本地。
  • 程序已使用 PyInstaller 打包为 Windows EXE,运行时不需要安装 Python,也不需要联网。

三、实现思路

1. 项目结构

我没有把所有内容写在一个文件里,而是把规则、关卡、计分、随机生成和界面流程分开:

game.py                  游戏状态、事件循环、绘制、动画和音频
arrowgame/rules.py       路径检测、消除与求解
arrowgame/levels.py      六个固定关卡
arrowgame/scoring.py     计时、星级和最好成绩
arrowgame/endless.py     随机可解关卡生成
tests/                   规则、流程、计分和无尽模式测试

其中 rules.py 不依赖 Pygame,可以直接用普通二维数据测试。这样在界面发生变化时,核心规则仍然能单独验证。

2. 箭头、方向和关卡的表示

棋盘用二维网格表示,. 是空格,U/D/L/R 分别表示上、下、左、右。四个方向统一映射为行列增量:

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

例如第一关的关卡模板是:

(
    "U.U.U",
    ".....",
    "L.U.R",
    ".....",
    "D.D.D",
)

关卡数据保存在不可变的字符串元组中,真正开始游戏时调用 fresh_board() 转成列表。消除箭头只修改这份运行中的副本。

3. 路径检测

路径判断的重点是从“箭头前方的下一格”开始检查,而不是从箭头本身开始;循环时先判断坐标是否仍在棋盘内,再读取格子。这样可以避免 Python 负索引把上边界错误地读成最后一行。

def first_blocker(board, row, col):
    for r, c in path_cells(board, row, col):
        if board[r][c] not in EMPTY:
            return r, c
    return None


def can_exit(board, row, col):
    rows, cols = _shape(board)
    if not (0 <= row < rows and 0 <= col < cols):
        return False
    if board[row][col] in EMPTY:
        return False
    return first_blocker(board, row, col) is None

path_cells() 根据方向增量逐格前进,直到离开边界。只要路径上遇到一个非空格,first_blocker() 就返回最近阻挡者;一路没有遇到箭头时,can_exit() 才返回 True。一次判断只扫描一行或一列,时间复杂度为 O(max(行数, 列数)),额外空间为路径长度;当前棋盘最大为 7×7,这部分开销很小。

4. 关卡可解性

固定关卡在加载时会检查棋盘是否为矩形、是否包含四种方向,并运行求解器。求解器找到当前能飞出的箭头,尝试删除后继续搜索;所有箭头都能删除时返回完整顺序,找不到合法动作则判定无解。

def solve_order(board):
    initial = tuple(tuple(row) for row in board)

    @lru_cache(maxsize=None)
    def search(state):
        if count_arrows(state) == 0:
            return ()
        for row, col in available_arrows(state):
            rest = search(remove_arrow(state, row, col))
            if rest is not None:
                return ((row, col),) + rest
        return None

    return search(initial)

这里使用带缓存的深度优先搜索,既能给出可解结论,也能保存一条合法通关顺序。游戏页新增“自动求解”按钮,点击后会按这条合法顺序逐支播放飞出动画;运行时按钮会显示“停止自动求解”,再次点击会取消后续解题步骤,让当前箭头完成后恢复手动操作。提示高亮状态下也可以直接启动,启动时只取消高亮,不退还已经使用的提示次数。自动求解期间棋盘点击会被忽略,但停止、重开、返回和静音仍然有效。它既方便演示,也方便检查动画和通关结算流程。

无尽模式采用反向插入方式生成棋盘:每次只把新箭头放在当时可以飞出的位置,因此反向删除时一定存在合法顺序。程序还会检查箭头数量、四种方向和依赖深度;随机尝试没有在限定次数内得到合适布局时,会对已验证的固定关卡做旋转或镜像作为保底。

5. 动画和状态切换

程序区分首页、选关、游戏、飞出动画、碰撞反馈、单关通关、失败、全部完成、无尽结算等状态。同一时刻只处理一个棋盘动作。

飞出动画约 0.18 秒,动画结束时才真正删除格子。碰撞反馈约 0.14 秒,先扣除一次机会,再播放前冲回弹和变色;最后一次碰撞反馈结束后才进入失败页。缩短反馈时长后,连续点击的等待感更低,同时仍保留清楚的动画反馈。所有动画都按经过时间推进,没有使用 sleep() 阻塞主循环,所以窗口在动画中仍能关闭或重开。

重开会清空旧动画并重新复制关卡模板。结果页出现后,按钮区域会重新生成,底层棋盘不再接收点击。

四、AIGC 使用过程

本项目主要使用 Codex 协助需求分析、编码、测试、打包和文档整理。下面的记录来自实际开发会话,没有把项目完成后的总结倒写成虚构过程。
下面选取 3 次具有代表性的过程,分别对应星级与胜利反馈、无尽模式与特殊 CG、最后一次机会反馈。每次都按“我的要求—AI 完成—实际效果—我的修改”记录,并附上开发过程截图。本节的 3 次代表性过程和对应截图另整理在 AIGC 使用过程记录,包括星级与胜利反馈、无尽模式与特殊 CG、最后一次机会的心跳和红色边缘效果。

次数 子任务 我提出的要求 AI 完成的内容 实际效果 我是否修改及修改内容
1 需求分析 阅读课程作业和参考博客,先复述要求,再给出完整方案,每个阶段留确认节点 整理了规则、界面、六关、测试、打包和博客材料的计划,并建立 PRD 方案覆盖了作业的基础要求,也列出了提示、存档等扩展 有。我确认采用 Python + Pygame、6 个固定关卡、每关 3 次机会和 3 次提示
2 界面设计 界面要清楚,但配色不能和参考博客一样;完整版完成后再将背景改为黑色 先生成首页、选关、游戏、提示、碰撞和结果页预览,再统一调整深色主题 第一版字体偏细,部分状态数字也不一致;黑底初版还需要重新检查文字对比 有。我确定纯黑背景、深灰面板和浅色文字,并保留四方向彩色箭头
3 规则与关卡 按已确认方案完成四方向判断、六关、动画、提示和重开 将纯规则放入独立模块,为六关生成合法解序,并接入完整游戏流程 四方向、远距离阻挡、边缘和重开测试通过;六关均可自动清空 有。我要求先给出可玩的 EXE,再由我本人上机检查手感;自动解序没有被当作本人试玩
4 扩展与反馈 增加星级、计时、音乐、最后一次机会反馈和无尽模式 增加三星规则、本地成绩、程序合成音乐与心跳、随机可解关卡及相应测试 新增功能测试通过;音频设备不可用时也能静音运行 有。我提供反馈图片并决定展示时机;没有把原商业游戏的代码、关卡或音频放入项目
5 测试与交付 打包 Windows 程序、上传 GitHub,并按作业结构写博客草稿 生成 EXE、ZIP、README、测试报告、截图和 Markdown 草稿;创建并推送公开仓库 源码运行、资源加载和 33 项当前自动检查通过 有。我保留最终发布和课程提交操作,博客中的学号、本人试玩和心得由我最后确认

代表性过程一:星级评价和胜利反馈

我提出了按剩余机会和通关时间评定三颗星的要求,并要求三星时显示指定图片、播放胜利音效。AI 完成计时、星级计算、最好成绩保存和结算反馈后,我又要求把得星条件写到界面中,并让图片和声音过渡更自然。

星级评价和胜利反馈的 AIGC 协作截图

代表性过程二:无尽模式

我要求随机生成第 1~6 关难度区间内的可解棋盘,无尽模式不评价星级,累计通关三次后显示特殊 CG。AI 增加了随机生成、通关计数,允许失败后重试原棋盘。

无尽模式和特殊 CG 的 AIGC 协作截图

代表性过程三:最后一次机会反馈

我要求剩余一次机会时显示指定图片,随后渐隐,并加入心跳和红色视野边缘。第一版反馈出现得太突然,心跳也不够明显,因此我又要求补充淡入淡出、增强低频,并让红色边缘随心跳轻微变化,同时保证棋盘仍然清晰。

最后一次机会效果的 AIGC 协作截图

这几轮协作中,AI 写了主要代码,我负责给出规则边界、选择功能、查看界面效果并决定是否接受结果。课程要求提交者理解关键代码,因此我还需要能说明方向增量、路径检测、关卡副本、动画状态和存档分别解决了什么问题。

最后一次机会反馈的图片:

最后一次机会反馈

五、测试结果

测试环境为 Windows、CPython 3.13.5、pygame-ce 2.5.8 和 SDL 2.32.10。2026 年 9 月 15 日重新运行当前源码:unittest 测试 26 项全部通过,另直接运行 7 项纯规则测试也全部通过,共 33 项。

编号 测试内容 预期结果 实际结果 是否通过
T01 点击前方无阻挡的箭头 箭头飞出棋盘并消失 动画结束后只删除一次,箭头数量减一 通过
T02 点击前方有阻挡的箭头 箭头不消失,失误次数减 1 返回最近阻挡者,箭头保留并播放碰撞反馈,机会减一 通过
T03 点击位于边缘且朝向棋盘外的箭头 正常消失,不发生越界错误 上、下、左、右四条边均能正确处理 通过
T04 消除本关全部箭头 显示通关并进入下一关 前五关进入单关结算,第六关进入全部完成页 通过
T05 失误次数耗尽 显示失败并允许重新开始 第三次碰撞反馈结束后进入失败页,重开恢复本关 通过
T06 游戏进行中重新开始 箭头布局和失误次数恢复 布局、3 次机会、3 次提示和动画均恢复 通过
T07 检查四个方向的相邻及远距离阻挡 路径上的任意箭头都会阻挡,身后及其他行列不影响判断 四个方向均找到最近阻挡者,隔着空格也没有漏判或误判 通过
T08 点击空格、棋盘外或在动画期间重复点击 无效输入不扣次数,动画期间只执行第一次有效操作 棋盘和机会保持正确,没有重复删除或连续扣次 通过
T09 使用提示、通关解锁并重新读取存档 提示只扣一次,下一关解锁,最好成绩和声音设置能够恢复 提示高亮可消除箭头;重新创建游戏对象后进度和设置读取正确 通过
T10 连续生成并求解无尽模式棋盘 棋盘含四种方向、数量符合难度范围,而且始终存在完整解序 随机关卡与保底布局均通过可解性检查,失败重试不改变原棋盘 通过

除作业指定的 T01 至 T06 外,我还检查了这些情况:

范围 实际检查结果
四方向与隔空阻挡 相邻和远距离阻挡均正确;身后及其他行列不会误判
六关可解性 六关均包含四个方向,自动求解得到完整合法顺序并清空棋盘
输入与状态 空格、越界位置和动画期间重复点击不会造成额外删除或扣次
计时与星级 暂停画面不计入用时,结算后计时冻结,星级边界与最好成绩更新正确
存档兼容 旧存档可以读取,不可信字段会被忽略,音效和音乐设置分别保存
音频降级 没有音频设备时游戏仍可运行;音乐、操作音效和心跳互不占用通道
无尽模式 随机棋盘保持可解;失败重试保持原棋盘;通关次数不改变普通关卡进度
资源缺失 个别反馈图片缺失时回退到普通结果页,不影响核心玩法

自动测试只能说明程序在设定输入下符合预期,不能代替作业要求的本人试玩。本人上机试玩记录将在发布前据实补入:

关卡 试玩日期 是否通关 操作感受与修改
1 初识箭序 2026/9/16
2 留意空隙 2026/9/16 尚可
3 交错之间 2026/9/16 还行
4 逐一解锁 2026/9/16 还不错
5 四向交织 2026/9/16 酣畅淋漓!
6 最后之序 2026/9/16 还不错

本人通过游戏的截图:

本人通关截图

游戏更新与问题修复

完成初版后,我继续根据实际操作反馈做了两次更新。第一次发现:使用提示后,如果手动点击了提示箭头,再点击“自动求解”,程序仍可能按照旧的初始解序访问已经清空的格子,导致游戏退出。修复后,自动求解启动时会读取当前棋盘并重新生成合法解序;队列遇到已经消除的坐标时会跳过,失效时也会重新计算,不再抛出异常。

自动求解问题修复记录

第二次反馈是点击响应偏慢。原先飞出动画约 0.32 秒、碰撞反馈约 0.26 秒,连续操作时需要等待较长时间。我将它们分别缩短为约 0.18 秒和 0.14 秒,同时保留动画期间一次只处理一个动作的规则,避免快速连点造成重复消除。修改后重新完成响应时长测试、规则测试、六关可解性检查,并重新打包 Windows 程序。

点击响应速度更新记录

这两次更新都先由我提出具体的操作问题,再由 AI 定位代码和修改实现,最后由我查看截图、运行程序并确认修复效果。截图保留了问题描述、修改结果和测试信息,作为本次游戏迭代的记录。

成就系统更新

在后续版本中,我增加了三个可以查看和保存进度的成就:

  • 👍:完成全部六个普通关卡。
  • 完美通关:六个普通关卡全部达到三星,图标为金色奖杯。
  • 我爱arrow:无尽模式累计通过三关。

游戏右下角的奖杯按钮可以打开成就面板。未解锁项目会显示锁定状态和当前进度,达到条件后会变为金色的“已解锁”状态。普通关卡成绩和无尽模式累计次数都会写入本地存档,重新启动游戏后不会丢失。

三项成就系统

六、PSP 表格

预计耗时在实施方案确定时填写。实际耗时根据本次开发会话、Git 提交时间和测试记录整理。

任务 预估耗时(小时) 实际耗时(小时) 差异(小时)
需求分析与游戏设计 1.00 1.60 +0.60
Python 与图形库学习 1.00 1.00 0.00
游戏界面实现 2.00 2.60 +0.60
路径与碰撞逻辑实现 2.00 2.20 +0.20
关卡设计 1.25 1.40 +0.15
AIGC 辅助开发 1.75 1.70 -0.05
测试与修改 2.75 2.50 -0.25
README 与博客撰写 1.25 1.50 +0.25
合计 13.00 14.50 +1.50

这里的 AIGC 辅助开发只统计专门整理提示、检查输出和协调任务的时间。AI 完成界面或规则时所用的时间已经分别计入对应阶段,没有再次相加。

七、心得体会

作业差不多花了一天来测试和优化,虽然感觉还有很多可以优化的比如游戏商城或者道具系统,更重要的是充值系统!,但是额度不允许我继续发挥创造力。这次作业里,AIGC 最直接的帮助是把需求、实现和测试连在了一起。我一开始给出的不只是“做一个箭头游戏”,还确认了每关次数、动画期间如何处理点击、重开要恢复什么、最后一关结束后,还有无尽模式。规则写清楚以后,后面的代码和测试才有统一标准。开发过程中也出现过需要继续检查的问题(也找朋友测试了一下,帮忙提提建议)。第一版预览的中文字体太细,棋盘附近的间距和状态数字不够统一;我提出配色不能照着参考博客做,完整版完成后又把背景改成纯黑。为保证黑底下仍然清楚,卡片、棋盘、按钮、提示和碰撞状态也同步调整成深色体系。测试第一次在受限临时目录中运行还遇到了权限错误。换到正常 Windows 临时目录重新执行后,26 项 unittest 才完整通过;纯规则测试又单独运行了 7 项。还有在运行游戏时,点击提示后再点击自动解题会退出游戏等。这个过程提醒我,命令报错不等于代码一定有错,应该先区分运行环境问题和程序断言失败。我对核心实现的理解是:方向映射决定箭头每一步的行列变化,路径检测只查看箭头前方同一行或同一列;关卡模板必须复制后再修改;动画状态负责保证一次点击只产生一次结果;存档只保存已解锁关卡和成绩,不保存未完成棋盘。求解器能验证关卡存在合法顺序,但不能代替我亲自玩一遍,因为操作手感、文字是否容易读、关卡是否太难都不是“可解”两个字能说明的。游戏差不多做完以后,就自己试玩了所有关卡,毕竟大部分都是ai帮忙做的,对大部分的知识学习也并没有掌握很多,但是更新游戏以及添加图片或是设计ui界面确实挺好玩的,这也算第一次开发游戏,对游戏开发也有了自己的见解。

commit如下:

GitHub Commit 记录

做完后真是燃尽了:
完成作业后的感受

感谢您的观看!奖励你一只可爱的猫咪🐱:

结尾猫咪

To be continued...

posted @ 2026-09-16 14:52  ddddal  阅读(66)  评论(0)    收藏  举报
ddddal 的头像