软件工程作业2:一箭又一箭,一改又一改

项目 内容
这个作业属于哪个课程 H202601 软件工程与软件工程实践
这个作业要求在哪里 2026 秋软件工程个人作业(第二次)
这个作业的目标 使用 Python 和 AIGC 完成「一箭又一箭」小游戏
学号 112401237
Github 仓库 zwoyyzy/one-arrow-game

一、项目展示

完整演示视频-在b站上发布Se_实践,可点击仓库查看有多次commit记录。

🧩 1.开始界面

注: 本游戏设计了主线关卡和随机挑战两种游戏模式,其中关卡选择界面包含 5 个主线关卡。主线关卡采用预先设计的固定关卡数据,每一关的棋盘大小、箭头数量、箭头位置和方向均保持不变。随机挑战模式每次进入时,会从 6×6、7×7、8×8 三种棋盘规格中随机选择一种,并随机生成箭头的位置与方向。生成后,程序会检查箭头之间的阻挡关系并进行求解验证,只有能够正常通关的布局才会提供给玩家。

🧩 2.关卡选择

注: 第一关默认解锁,玩家通关当前关卡后,下一关才会开放。尚未解锁的关卡以深灰色卡片和锁头图标显示,避免玩家跳过前置关卡。已经解锁但尚未完成的关卡会显示“尚未通关”,已完成的关卡则会记录获得的星级和最佳通关时间,方便玩家重新挑战并刷新成绩。

🧩 3.游戏过程

✅ 通关

⭕️失败

🧩 4.全部通关界面

✨ 本游戏更多细节将在项目特色具体介绍 ✨

二、项目介绍

1. 游戏规则

本游戏是一款点击式箭头解谜游戏。棋盘中分布着朝上、下、左、右四个方向的箭头,玩家需要观察箭头的朝向以及箭头之间的阻挡关系,按照合理的顺序将全部箭头清除。> 玩家使用鼠标点击箭头后,程序会沿着该箭头指向的方向检测同一行或同一列:

  • 如果箭头与棋盘边界之间没有其他箭头阻挡,该箭头飞出棋盘并被消除
  • 路径上存在其他箭头,该箭头不能被消除,并通过变红、震动和底部文字提示表现碰撞效果
  • 每个关卡共有 3 次失误机会,点击被阻挡的箭头会扣除一颗红心
  • 当所有箭头都被成功清除后,游戏显示通关界面,并根据通关时间评定一至三星。玩家可以重新挑战、进入下一关或返回首页;当 3 次失误机会全部耗尽时,游戏显示失败界面,玩家可以重新开始当前关卡。
  • 点击“重新开始”按钮后,当前关卡的箭头布局、剩余失误次数和计时都会恢复到初始状态。
  • 游戏计时从进入关卡时开始,暂停游戏后计时停止,继续游戏后恢复计时

2. 界面设计

本游戏采用新粗犷主义Neo-Brutalism作为主要视觉风格。界面以暖白色为背景,通过粗黑边框、右下硬阴影和高饱和度色块突出卡片与按钮,使游戏具有鲜明、活泼的视觉效果。荧光黄主要用于标题和关键信息,电光蓝用于功能按钮,珊瑚红用于失误和碰撞提示。游戏中的图标与箭头均使用 Pygame 几何图形绘制,没有使用原商业游戏的美术素材。
为了保证功能清晰并形成完整的游戏流程,项目设计了以下界面:

  • 开始界面:显示游戏标题和主要模式入口,包括主线关卡、继续游戏、关卡选择和随机挑战。
  • 关卡选择界面:以卡片形式展示5个主线关卡。
  • 游戏界面:顶部状态区域显示当前关卡、剩余箭头、游戏用时和剩余失误次数。剩余失误统一使用3颗红心表示,每次错误点击会扣除一颗。棋盘位于页面视觉中心,右侧提供重新开始、暂停等操作,右下角设置提示和AI自动求解按钮。
  • 通关界面:清除全部箭头后显示通关弹窗,并展示本关用时、操作步数和星级评价。星级根据玩家通关时间与AI参考时间进行计算,最高为三星。玩家可以选择重玩本关、进入下一关或返回首页。
  • 失败界面:当3次失误机会全部耗尽时,显示挑战失败信息,并提供重新开始和返回首页等操作,使玩家能够快速再次挑战。
  • 暂停界面:玩家点击暂停后,游戏画面会变暗,关卡计时同时停止。界面中央显示继续游戏按钮,点击后恢复游戏和计时,防止暂停时间影响最终成绩。
  • 声音设置界面:玩家可以分别控制背景音乐和箭头飞出音效,不需要关闭全部声音,能够根据个人习惯调整游戏的声音反馈。

3. 主要功能

  • 箭头消除: 点击前方无阻挡的箭头,使其飞出棋盘并消失。
  • 路径检测: 检测箭头指向的同一行或同一列中是否存在其他箭头。
  • 碰撞反馈: 点击被阻挡的箭头时,箭头变红并震动,同时扣除一次失误机会。
  • 关卡系统: 包含5个固定主线关卡,通关当前关卡后解锁下一关。
  • 随机挑战: 从三种棋盘规格中随机选择一种,生成经过求解验证的随机关卡。
  • 游戏辅助: 提供提示、AI自动求解、暂停和重新开始功能。
  • 计时与星级: 记录通关时间,并参考AI求解时间评定一至三星。
  • 进度保存: 自动保存主线关卡进度、最高星级和最佳时间。
  • 声音设置: 提供背景音乐和游戏音效,并支持分别开启或关闭。
  • 游戏反馈: 包含箭头飞出、碰撞、通关和失败等动画及声音效果。

4. 项目特色

本项目在完成箭头点击、路径检测、碰撞反馈、失误次数和关卡切换等基础要求的基础上,进一步实现了多项扩展功能,使游戏的内容、交互和完整性得到提升。

扩展功能 具体实现
5个主线关卡 设计了5个难度逐渐提高的固定关卡,通关当前关卡后解锁下一关
关卡选择 显示每关的解锁状态、最高星级和最佳通关时间,未解锁关卡以灰色锁定卡片表示
随机挑战 从6×6、7×7和8×8三种规格中随机选择棋盘,并随机生成箭头的位置和方向
AI自动求解 自动计算当前关卡的正确消除顺序,并按照该顺序演示完整通关过程
提示功能 帮助玩家找到当前可以安全飞出的箭头,降低关卡难度
计时与暂停 进入关卡后自动计时,暂停时停止计时,继续游戏后恢复
星级评价 根据玩家通关时间与AI参考时间进行一至三星评价
游戏进度保存 自动保存主线关卡的解锁进度、最高星级、最佳时间和未完成关卡
动画反馈 成功消除时播放箭头飞出动画,发生阻挡时显示变色和震动效果
音乐与音效 加入背景音乐以及飞出、碰撞、通关和失败音效,并支持单独开关
可执行文件 使用PyInstaller将程序打包成Windows可执行文件,没有安装Python的用户也可以运行

下面是一些展示:

AI自动求解

已打包为可执行文件

提示/暂停/重置/声音设置功能

游戏进度保存

注: 游戏使用本地 JSON 文件实现主线关卡的进度保存,并分别处理“当前关卡未通关”和“当前关卡已通关”两种情况。
当玩家尚未通关当前关卡便返回首页时,程序会保存当前关卡编号、剩余箭头的位置与方向、剩余失误次数、操作步数和已经使用的时间。此时首页会显示“继续主线”入口,玩家点击后可以恢复离开前的棋盘状态,并在原有计时基础上继续挑战,而不需要从头开始。
当玩家通关当前关卡并返回首页时,程序会记录该关卡的通关状态、最高星级和最佳时间,同时将下一关的初始状态保存为新的游戏进度。因此,首页的“继续主线”会进入下一关,而不是返回已经通关的关卡。
如果玩家通关了最后一关,程序会保留五个主线关卡的通关成绩,但不会再生成下一关存档。
如果玩家失误次数耗尽,则本次失败对局不会作为未完成进度保留,但之前获得的关卡成绩不会受到影响。
此外,随机挑战模式不保存游戏进度,返回首页后再次进入时会重新生成一个随机关卡。

三、实现思路

本项目使用 Python 和 Pygame 开发,并按照功能拆分代码。game.py 负责游戏流程和鼠标事件,arrow.py 负责箭头对象与路径检测,levels.py 保存主线关卡,random_levels.py 生成随机挑战,ui.py 负责界面绘制,save_manager.py 负责保存游戏进度。

1. 箭头与关卡的表示

每支箭头使用“行、列、方向”三个数据表示;四个方向使用二维向量表示

(row, col, direction)

DIRECTION_VECTORS = {
    "up":    (-1, 0),
    "down":  (1, 0),
    "left":  (0, -1),
    "right": (0, 1),
}

主线关卡以字典形式保存,包含棋盘大小、失误上限、箭头列表和参考解法:

return {
    "name": f"第 {level_number} 关",
    "rows": size,
    "cols": size,
    "max_mistakes": max_mistakes,
    "arrows": arrows,
    "solution": solution,
}

项目共设计了5个主线关卡,箭头数量逐渐增加,并保证每关均包含四种方向且可以正常通关。

2. 路径检测

路径检测是游戏的核心。程序从被点击箭头前方的第一个格子开始,沿箭头方向逐格检查,直到到达棋盘边界。

def is_path_clear(arrow, arrows, rows, cols):
    row_step, col_step = DIRECTION_VECTORS[arrow.direction]

    check_row = arrow.row + row_step
    check_col = arrow.col + col_step

    occupied_positions = {
        (other.row, other.col)
        for other in arrows
        if other is not arrow
        and other.state != "flying"
    }

    while 0 <= check_row < rows and 0 <= check_col < cols:
        if (check_row, check_col) in occupied_positions:
            return False

        check_row += row_step
        check_col += col_step

    return True

如果检查过程中发现其他箭头,则返回 False,表示路径被阻挡;如果一直检查到边界都没有发现箭头,则返回 True,表示箭头可以飞出。

3. 主线关卡与随机挑战

主线关卡的数据固定保存在 levels.py 中,因此每一关的棋盘大小、箭头位置和方向保持不变。随机挑战会从三种规格中随机选择一种。
程序随机选择箭头位置和方向,并检查布局是否具有足够的阻挡关系。生成后还会调用自动求解函数进行验证:

while arrows:
    safe_arrows = [
        arrow
        for arrow in arrows
        if is_path_clear(arrow, arrows, rows, cols)
    ]

    if not safe_arrows:
        return None

    arrow = random.choice(safe_arrows)
    solution.append((arrow.row, arrow.col))
    arrows.remove(arrow)

只有能够将全部箭头清除的布局才会作为随机关卡,从而避免生成无法通关的题目。

4. 游戏进度保存

程序使用本地JSON文件保存主线游戏进度。未通关时返回首页,会保存当前关卡、剩余箭头、失误次数、操作步数和已用时间;通关后则记录该关的最高星级和最佳时间,并解锁下一关。

return {
    "level_index": self.level_index,
    "remaining_arrows": [
        [arrow.row, arrow.col, arrow.direction]
        for arrow in self.arrows
        if arrow.state != "flying"
    ],
    "mistakes_left": self.mistakes_left,
    "moves_count": self.moves_count,
    "elapsed_ms": self.get_elapsed_milliseconds(),
}

随机挑战不保存对局进度,每次进入都会重新生成新的关卡。

四、AIGC使用过程

1.使用记录

子任务 借助的 AIGC 工具 我提出的要求 AI 实现或提供的内容 实际效果 我的测试与修改
作业内容分析 ChatGPT 阅读并分析作业要求,梳理必须完成的基础功能、界面要求、测试要求、GitHub要求和扩展功能,帮助我确定整体开发流程 ChatGPT将作业要求整理为需求分析、环境配置、代码结构设计、核心玩法实现、关卡设计、测试和文档编写等阶段,并列出了各阶段需要完成的任务 让我对作业内容和开发顺序有了较清晰的认识,避免遗漏开始界面、失误机制、重新开始和测试记录等要求 我重新阅读原始作业要求,将AI整理的内容与评分标准逐项对照,只保留与本项目有关的功能,并决定先完成基础要求,再实现附加功能
游戏基础结构设计与启动问题调试 Codex 根据作业的11项基本要求设计代码结构,并解决游戏运行后窗口闪退和中文字体显示异常的问题 Codex将项目划分为程序入口、游戏流程、箭头对象、关卡数据和界面绘制等模块。出现闪退后,指导我通过VS Code终端运行程序,根据完整报错定位到ui.py中的字体匹配问题,并提供修改方案 代码结构基本覆盖了作业要求;修复字体加载逻辑后,游戏窗口能够稳定打开,中文标题、按钮和提示文字也能正常显示 我简化了AI最初提供的设计内容,按照先基础功能、后扩展功能的顺序开发。发生闪退时,我将终端报错和截图反馈给Codex,再将修改方案整合到ui.py中,通过多次启动确认问题已经解决
UI页面设计与实现 Gemini Codex 在不使用外部商业游戏素材的情况下,为游戏设计一套具有辨识度、适合使用Pygame几何绘制实现的界面 Gemini主要负责分析和设计UI风格,提出新粗犷主义方案,包括暖白背景、粗黑边框、硬阴影和高饱和度色块;我将确定的设计思路交给Codex,由Codex实现开始界面、游戏界面、关卡选择、暂停界面和结算弹窗 初版实现了统一的视觉风格,但存在棋盘与顶部栏距离过近、按钮拥挤、字体大小不一致、箭头与方格不贴合以及部分图标超出边框等问题 我先从Gemini给出的方案中确定最终风格,再根据实际运行截图不断向Codex提出修改要求,调整棋盘位置、按钮间距、字体、箭头大小和关卡图标。部分自动修改失败的代码由我手动替换并运行验证
主线关卡设计 Codex 设计5个箭头数量逐渐增加的主线关卡,不要填满棋盘,保证四种方向都出现、阻挡关系正确,并且每一关都可以正常通关 Codex将5个关卡设计为5×5至9×9棋盘,箭头数量依次为8、12、16、20和24,并为每一关生成箭头位置、方向和经过验证的参考消除顺序 第一版关卡虽然可以通关,但箭头数量偏少,而且部分箭头在同一行或同一列中的方向过于一致,布局规律明显,解谜性不足 我逐关试玩后,将布局过于规律的问题反馈给Codex,要求重新分散箭头位置、调整方向并增加阻挡关系。修改后,我再次试玩各个关卡,并使用提示和AI自动求解功能检查是否都能正常通关

2.使用截图

🔵 作业内容分析

注: 肯定是要人工认真阅读作业要求的,但还是怕理解不准确或者用遗漏,还是发给ChatGPT让它帮我梳理,并且给我一个大概的流程我心里有底。

🔵 游戏基础结构设计与相关问题调试

注: 先搭个大概结果,然后我运行时遇到闪退以及字体显示异常等问题,把相关问题和报错发给Codex进行进一步更改。

🔵 ui页面设计与实现

注: Gemini+Codex,Gemini负责设计(据说Gemini审美比较好)(确实有比Codex好、我第一版设计非常之一般),Codex负责实干,~~我负责刷手机~~(x)先选定大概的风格,然后Gemini生成具体的设计,再把Gemini设计思路内容发给codex操作,我来把关最后要确定的效果以及有时候codex抽风无法获得写入权限需要人工来修改部分代码。

🔵 主线关卡设计

注: 刚开始箭头数目太少了,并且同一行或者同一列箭头朝向几乎一致,试玩后提出更改。

3.使用心得

在本项目中,我主要按照“提出需求—AI提供方案或代码—实际运行与试玩—发现问题—反馈修改—再次验证”的流程使用AIGC工具。开发前,我使用ChatGPT梳理作业要求和开发流程;开发过程中,使用Gemini辅助确定界面设计风格,再使用Codex完成Pygame代码实现、关卡设计和问题调试。

AI提高了需求分析、代码编写和错误排查的效率,但第一次生成的结果并不一定完全符合实际需求。例如,界面初版存在布局不协调的问题,主线关卡初版也存在排列过于规律的问题。因此,我仍然需要通过运行程序、观察界面、试玩关卡和检查终端报错来判断实际效果,并根据测试结果对AI提供的内容进行修改和完善。

五、测试结果

为保证严谨,自动化和人工测试double check!

1.自动化测试

为了检查游戏核心逻辑是否正确,使用pytest编写了自动化测试。测试代码位于项目的tests/test_game.py中,共设计了T01—T10十类测试。由于T03分别测试了上、下、左、右四种边缘情况,因此pytest实际执行了13个测试项,最终结果为13 passed

具体列表如下:

编号 自动化测试内容 预期结果 实际结果 是否通过
T01 检测前方无阻挡的箭头 is_path_clear()返回True,说明箭头路径畅通 路径检测结果为True 通过
T02 处理前方有其他箭头阻挡的点击 箭头状态变为blocked且不会被删除,剩余失误次数减1 箭头保留在棋盘中,失误次数由3减为2,并生成阻挡提示 通过
T03 检测位于四条边且方向朝外的箭头 上、下、左、右四种边缘情况均返回路径畅通,并且不发生越界 pytest分别执行了4个方向的参数化测试,全部通过 通过
T04 验证5个主线关卡的参考解法 解法中的每个箭头在对应步骤都可以安全飞出,最终箭头列表为空 5个主线关卡均可按照保存的解法完全清除 通过
T05 连续触发3次错误点击 剩余失误次数变为0,游戏状态切换为失败状态 3次错误后进入GAME_OVER状态,并触发失败反馈 通过
T06 重新开始当前关卡 恢复原始箭头布局、3次失误机会和初始操作计数 箭头布局恢复,剩余失误变为3,已用失误和操作步数归零 通过
T07 暂停游戏计时 暂停后计时停止,暂停期间的时间不计入游戏用时 模拟经过2.5秒后暂停,累计有效时间保持为2.5秒 通过
T08 使用提示功能 程序选中的提示箭头必须是当前可以安全飞出的箭头 成功找到安全箭头,路径检测结果为True 通过
T09 保存和读取未完成的主线对局 能够将关卡、剩余箭头、失误次数、步数和时间写入JSON并正确读取 临时存档写入和读取成功,各项数据保持一致 通过
T10 生成随机挑战关卡 棋盘规格符合要求、位置不重复、四种方向齐全,并且存在完整解法 随机关卡的数据格式正确,四种方向齐全,参考解法能够清除全部箭头 通过

自动化测试主要适合判断数据和逻辑是否正确,但界面效果、动画观感和声音质量难以仅通过代码断言进行评价。因此,还是需要人工测试。

2.人工测试

我亲历亲为亲自依次检查了开始界面、游戏界面、关卡选择、暂停、通关和失败等页面,确认各页面布局正常,中文文字显示清晰,按钮可以正常点击和切换。箭头成功飞出、碰撞变色与震动等动画均能正常播放,背景音乐以及飞出、碰撞、通关和失败音效也可以正常使用。提示和AI自动求解能够按照预期完成操作,未通关进度可以通过首页的“继续关卡”正确恢复。此外,我还对打包后的Windows可执行文件进行了启动和试玩,程序无需安装Python即可正常运行。

六、PSP表格

任务 预计耗时(小时) 实际耗时(小时) 差异(小时)
需求分析与游戏设计 2 1.5 -0.5
Python 与图形库学习 2 2.5 +0.5
游戏界面实现 3 4.5 +1.5
路径与碰撞逻辑实现 3 3 0
关卡设计 2 2.5 +0.5
AIGC 辅助开发 2 2 0
测试与修改 2 3 +1
README 与博客撰写 2 3 +1
合计 18 22 +4

本项目预计耗时18小时,实际耗时约22小时。借助AIGC工具,我较快完成了需求分析和初步结构设计,因此这一阶段的实际耗时少于预计。实际增加的时间主要集中在游戏界面实现、关卡调整和程序测试方面。开发过程中,我多次修改界面风格和布局,并对随机挑战、存档、声音设置等功能进行了反复测试,导致最终实际耗时比预计多出4小时。

七、心得体会

这次Codex为主,Gemini打下手,深切体会到了智能体的方便,但也不是百分百托付,有时候一些写入权限获取突然失效,还是需要人工去手动更改代码。并且也需要对代码生成效果进行验证然后更改。还有AI的审美确实很一般,布局之类的也完全不会考虑,人工给提示词反复修改了比较长的时间。然后也是精益求精、尽可能完善功能,算是个人第一次小游戏开发还是挺有意思的,把想法落地放大了我的创造力ദ്ദി˶ー̀֊ー́ )✧
非常感谢老师&助教们的浏览,如果可以的话可以拥有一个还不错的评价吗
爱心

posted @ 2026-09-20 15:06  ijustwannarun  阅读(1)  评论(0)    收藏  举报