2026秋软件工程个人作业(二)——《一箭又一箭》游戏开发实践

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

前言

又到了我最期待的软工作业环节!

我花了大概一天时间制作、以及打磨我的项目,包括但不限于美化游戏界面、添加神人音效等,目前来看效果令我很是满意。下面我将进行我关于这次软工作业的汇报,同时在项目和博文中我会塞很多私货。本项目制作不易,各位看官姥爷如果喜欢我的作品,请点击链接前往我的仓库送上一颗星星,感激不尽!

13nl

一、项目展示

1.演示视频

请前往百度网盘查看:
通过网盘分享的文件:一箭又一箭演示视频
链接: https://pan.baidu.com/s/119rAEPSqAdevA0xjh5lQ2g?pwd=xkfx 提取码: xkfx

录屏软件安装包来自一位刘姓同学,特此感谢。

由于我的录制的视频有1分29秒,没办法制作成赛博琥珀,但是一位方姓的热心同学帮我录制了主要功能的动图,在这里表示感谢。
E109820F290991F67F0D8403583A0245
722A91F6716F6170C3A597CFC4E8AA08
0FF143DD4DE7C6E172B4ED2C4463CF81

2.开始画面

开始画面最初是想模仿假面骑士EX-AID中Mighty Action X游戏的开幕画面,连开始游戏按钮也模仿,想想太过于麻烦,干脆让gpt给我生成了一张,详情请看下文AIGC使用记录。是的我是特摄厨,看我一命通关

特殊效果为鼠标悬停到按钮上,按钮会变大,并且点击后会播放音效,详情请看演示视频。我不会告诉你我抠这个按钮的图抠到想s

1开始界面

3.游戏过程画面

以下为游戏过程画面,本来UI界面想参考baoshuo大佬的,后面觉得不妥,还是让gpt给我生成了一个样图。

画面右侧三个按钮都是可以交互的,并且鼠标悬停时按钮会微微闪烁。在棋盘中,鼠标悬停到有箭头的格子上方时格子会微微闪烁,同时为格子加上一层橙色边框。点击格子后箭头若无阻挡,可正常飞出画面,同时深绿色变为浅绿色;若不能,箭头会颤抖并变为红色,同时扣掉一次失误机会,播放失误音效。保证关卡的箭头每次都是随机生成并且一定能够通关。

是的没错,爱心素材来自于Minecraft中的生命值,而扣掉一次机会同样会播放Minecraft中玩家的受击音效,同时爱心变黑心,类似于掉血!在整个游戏过程中还会播放MC主世界的背景音乐哦!具体效果请看演示视频。

二编:过两天有空了会增加新功能并发布新版本

三编:已经上传了新版本,修复了在别人电脑上无法运行的bug并且添加了AI自动求解关卡以及自动提示下一步的功能

2游戏画面

4.通关界面:

通过当前关卡后会显示星级、失误次数以及用时。失误0次就是三星,以此类推。与此同时也会播放MC中玩家的升级音效作为通关音效。

通关音效的创意来自一位姓何的同学@Victoria_L,在这里对他表示感谢。

3通关画面

5.失败界面:

失败后会播放“厚辣,干巴跌”音效!我自己想的神人音效
能绷住的可以确诊面瘫了

4失败画面

6.全部通关界面:

点击“再玩一次”可以回到第一关。

5全部通关画面

二、项目介绍

1. 游戏规则

《一箭又一箭(OneArrowAgain)》是一款基于 Python + Pygame 开发的箭头益智解谜游戏。

棋盘中的箭头共有 上、下、左、右 四个方向。玩家需要观察箭头前方是否存在其他箭头:

  • 如果前方没有箭头阻挡,点击后箭头会沿当前方向飞出棋盘;
  • 如果前方存在箭头阻挡,则本次操作失败,并扣除一次失误机会;
  • 每关共有 3 次失误机会,生命值耗尽后挑战失败;
  • 当棋盘上的所有箭头被成功清除后,即可完成当前关卡。

随着游戏进行,关卡中的箭头数量会逐渐增加,需要玩家更加仔细地分析箭头之间的阻挡关系,并寻找正确的消除顺序。


2. 界面设计

游戏整体采用 森林、自然、休闲解谜 风格,以米白色、绿色和橙色为主要配色。

目前游戏界面主要包括:

  • 开始界面:游戏标题、背景图、开始按钮及悬停动画;
  • 模式选择界面:用于选择游戏模式,并预留限时模式、无尽模式和人机对战等后续功能;
  • 游戏界面:显示当前关卡、剩余箭头、生命值和游戏用时;
  • 操作区域:提供撤销、重新开始、返回首页、AI 自动求解和 AI 提示一步等功能;
  • 结算界面:显示通关或失败状态、关卡用时、失误次数和星级评价;
  • 鸣谢界面:展示项目开发过程中使用的技术以及提供帮助的人员和资源。

3. 主要功能

游戏目前实现了以下功能:

  • 四方向箭头与路径阻挡检测;
  • 箭头飞出动画和错误碰撞反馈;
  • 3 个难度逐渐增加的关卡;
  • 随机生成且保证可解的关卡;
  • 生命值、计时和星级评价系统;
  • 撤销、重新开始和返回首页功能;
  • AI 自动求解当前关卡;
  • AI 提示下一步可操作箭头;
  • 背景音乐以及点击、错误、通关、失败等交互音效;
  • 开始、模式选择、游戏、胜利、失败、全部通关和鸣谢等多种游戏状态。

4. 项目特色

本项目不仅实现了基础的箭头消除玩法,还加入了 随机可解关卡生成、撤销机制、动画反馈、计时与星级评价、AI 辅助求解、背景音乐和多种交互音效。

每次开始新游戏时,程序都会重新生成不同的棋盘布局。关卡并不是完全随机地放置箭头,而是在生成过程中利用路径检测算法不断判断箭头是否存在可消除方向,从而保证生成的棋盘至少存在一种正确的通关顺序。

在此基础上,我进一步实现了一个 基于游戏规则的自动求解算法。程序可以分析当前棋盘状态,寻找完整的箭头消除顺序,并按照该顺序自动执行。

同时,游戏还提供了 “AI 提示一步” 功能。当玩家不知道下一步应该点击哪个箭头时,程序会调用同一个求解算法分析当前棋盘,并将解法中的第一步通过高亮效果提示给玩家,而不会直接替玩家完成操作。

这样既可以让玩家在遇到困难时获得帮助,也可以利用自动求解功能验证随机生成的关卡是否能够正常完成。


5. 项目运行与打包

项目开发完成后,使用 PyInstaller 将 Python 程序打包为 Windows 可执行文件(.exe)。

打包完成后,无需打开 PyCharm 或手动运行 Python 文件,直接双击生成的 OneArrowAgain.exe 即可启动游戏。

经过实际运行测试,打包后的程序能够正常完成:

  • 游戏启动;
  • 图片资源加载;
  • 背景音乐和音效播放;
  • 箭头点击与动画;
  • 随机关卡生成;
  • AI 自动求解;
  • AI 提示下一步;
  • 关卡切换;
  • 胜利、失败及全部通关结算。

说明项目已经能够以独立 Windows 应用程序的形式正常运行。

该 exe 文件同步发布在我的 GitHub 仓库中,同时仓库中保留了多次 commit 记录,用于展示项目的持续开发过程。

二编:

经测试,最初发布的 exe 在部分其他电脑上无法正常运行。经过排查,发现原因是程序使用了系统字体,当目标电脑中不存在对应字体时,程序可能出现异常。

因此后续将字体文件直接加入项目资源,并通过相对资源路径进行加载,使程序不再依赖目标电脑已经安装的字体。

三编:

已经上传新版本,修复了在其他电脑上运行时可能因为缺少字体导致程序异常的问题,同时新增了:

  • AI 自动求解当前关卡;
  • AI 提示下一步功能;
  • 更完善的跨电脑资源加载方式。
    6dist

12commit

三、实现思路

1. 箭头与方向表示

游戏中的每个箭头使用字典进行表示,主要记录箭头所在的行、列以及方向,例如:

{
    "row": 2,
    "col": 3,
    "direction": "RIGHT"
}

其中:

  • row:表示箭头所在的行;
  • col:表示箭头所在的列;
  • direction:表示箭头方向,可取 UP、DOWN、LEFT、RIGHT。

所有箭头统一存放在列表 arrows 中,程序根据这些数据完成棋盘绘制、鼠标点击判断以及路径检测。

2. 关卡表示

游戏目前共设置 3 个关卡,每一关本质上都是一组箭头数据。

关卡 箭头数量
第一关 10
第二关 15
第三关 20

每次开始新游戏时,程序都会随机生成新的箭头布局。为了避免随机生成出“无解关卡”,程序加入了可解关卡生成逻辑。

为了保证随机生成的关卡可解,在放置每个箭头时,程序会尝试四种方向,并利用已有的路径检测函数判断该方向是否可行:

for direction in (
    "UP",
    "DOWN",
    "LEFT",
    "RIGHT"
):
    candidate = {
        "row": row,
        "col": col,
        "direction": direction
    }

    test_arrows = (
        generated_arrows
        + [candidate]
    )

    if not is_blocked(
        candidate,
        test_arrows
    ):
        valid_directions.append(
            direction
        )

其中,valid_directions 用于保存当前箭头所有可以正常飞出的方向。如果四个方向都不可行,则说明本次生成无法保证可解,需要重新生成:

if not valid_directions:
    success = False
    break

最后再从所有可行方向中随机选择一个方向:

direction = random.choice(
    valid_directions
)

通过这种方式,程序在随机生成关卡的同时,对每个箭头的方向进行可消除性检查,从而保证最终生成的关卡至少存在一种正确的消除顺序。

3. 路径检测方法

路径检测是游戏的核心逻辑。

当玩家点击某个箭头时,程序会根据箭头的方向,检查其所在的同一行或同一列上,前方是否还存在其他箭头。

例如,当箭头方向为 RIGHT 时,只需要判断是否存在与当前箭头处于同一行,并且位于它右侧的其他箭头:

if direction == "RIGHT":
    if other_row == row and other_col > col:
        return True

其他三个方向的判断方法类似:

# 向左
other_row == row and other_col < col

# 向上
other_col == col and other_row < row

# 向下
other_col == col and other_row > row

如果在对应方向上找到其他箭头,说明当前箭头被阻挡,返回 True;如果检查完所有箭头后都没有发现阻挡,则返回 False。

因此,路径检测的核心思路可以概括为:

根据箭头的方向,在同一行或同一列中判断其前方是否存在其他箭头。

如果没有阻挡,箭头可以正常飞出棋盘;如果存在阻挡,则判定本次操作失败。

4. AI 自动求解算法

为了帮助玩家分析当前棋盘,同时验证随机生成的关卡是否可以顺利完成,我在游戏中加入了 AI 自动求解功能。

这里的“AI”并不是调用大语言模型或者机器学习模型,而是一个基于游戏规则实现的 自动搜索与求解算法。

由于本游戏中一个箭头能否被消除,只取决于它当前方向的前方是否还存在其他箭头,因此可以不断寻找当前棋盘中没有被阻挡的箭头,并将其依次移除。

4.1 复制当前棋盘

在进行求解时,程序首先复制当前箭头列表:

test_arrows = [
    arrow.copy()
    for arrow in current_arrows
]

这样求解过程只修改临时棋盘,而不会直接影响玩家当前正在操作的真实棋盘。

同时创建一个 solution 列表,用于保存求解得到的完整操作顺序:

solution = []

4.2 寻找当前可以飞出的箭头

只要临时棋盘中仍然存在箭头,就遍历当前所有箭头:

while test_arrows:

    found_arrow = False

    for arrow in test_arrows:

        if not is_blocked(
                arrow,
                test_arrows
        ):

这里直接复用了之前实现的 is_blocked() 路径检测函数。

如果:

is_blocked(...) == False

说明该箭头当前方向前方没有其他箭头阻挡,因此它可以正常飞出棋盘。

找到可以消除的箭头后,将它加入解法:

solution.append(
    arrow.copy()
)

然后在模拟棋盘中删除该箭头:

test_arrows.remove(
    arrow
)

接着重新分析剩余棋盘。

4.3 判断当前局面是否可解

程序使用变量:

found_arrow

记录当前一轮是否找到可消除箭头。

如果遍历完整个棋盘以后,一个可以飞出的箭头都没有找到:

if not found_arrow:
    return None

则说明当前棋盘无法继续消除,可以认为当前状态不存在有效解法。

如果所有箭头最终都被成功删除,则返回完整的消除顺序:

return solution

因此,solve_level() 得到的结果本质上类似于:

[
    第一步可以点击的箭头,
    第二步可以点击的箭头,
    第三步可以点击的箭头,
    ...
]

直到整个棋盘被清空。

4.4 为什么这种方法可以工作

本游戏具有一个比较重要的特点:

当一个箭头被成功移除后,棋盘上的箭头只会减少,不会增加新的障碍物。

因此,删除一个当前可以正常飞出的箭头后,不会让其他箭头前方增加新的阻挡,反而可能使原本被阻挡的箭头变成可以消除的状态。

程序只需要不断重复:

寻找当前没有被阻挡的箭头 → 删除 → 重新分析棋盘

就可以逐步得到完整的消除顺序。


5. AI 自动求解功能

获得完整解法之后,程序还需要让 AI 按照解法真正执行游戏操作。

首先使用:

ai_solution

保存 solve_level() 返回的完整解法,并通过:

ai_solving

记录当前是否处于 AI 自动求解状态。

每次准备执行下一步时,从解法列表中取出第一个箭头:

next_step = ai_solution.pop(0)

然后在真实棋盘 arrows 中找到对应的箭头:

for arrow in arrows:

    if (
            arrow["row"] == next_step["row"]
            and arrow["col"] == next_step["col"]
            and arrow["direction"] == next_step["direction"]
    ):

找到以后,并不是直接把箭头从列表中删除,而是:

flying_arrow = arrow
fly_offset = 0

将它交给游戏原本已经实现的箭头飞行动画系统处理。

这样做有两个好处:

  1. AI 操作和玩家操作使用同一套箭头飞行动画;
  2. 不需要为 AI 单独编写一套棋盘消除逻辑。

因此,AI 自动求解时可以看到箭头按照正确顺序依次飞出棋盘,而不是瞬间全部消失。


6. AI 提示下一步

除了自动完成整个关卡以外,我还实现了一个更加适合正常游戏的 “AI 提示一步” 功能。

当玩家点击“AI 提示一步”按钮时,程序首先调用:

solution = solve_level(
    arrows
)

分析当前棋盘。

如果求解成功,则取完整解法中的第一步:

next_step = solution[0]

因为 solution[0] 就表示:

在当前棋盘状态下,下一步可以安全点击的一个箭头。

然后程序在真实棋盘中找到对应箭头:

for arrow in arrows:

    if (
            arrow["row"] == next_step["row"]
            and arrow["col"] == next_step["col"]
            and arrow["direction"] == next_step["direction"]
    ):

        hint_arrow = arrow

程序并不会自动替玩家点击这个箭头,而是将它保存到:

hint_arrow

中,并设置提示持续时间:

hint_until = (
    pygame.time.get_ticks()
    + 2500
)

也就是让提示效果持续约 2.5 秒。

在绘制棋盘时,如果某个箭头正是 hint_arrow,程序会对它进行额外的高亮显示,从而告诉玩家:

这个箭头是当前局面下可以安全消除的一步。

这种设计将 “AI 自动完成” 和 “AI 辅助玩家思考” 区分开来。

其中:

  • AI 自动求解适合用于展示算法效果、测试关卡和快速通关;
  • AI 提示一步只提供一个操作建议,不会直接完成关卡,更适合作为正常游戏中的辅助功能。

7. AI 求解功能与关卡生成之间的关系

随机可解关卡生成和 AI 自动求解虽然属于两个不同的功能,但二者实际上使用了相同的核心规则:

is_blocked()

其中:

  • 随机关卡生成时,使用 is_blocked() 判断箭头方向是否满足可消除条件;
  • 玩家点击箭头时,使用 is_blocked() 判断本次操作是否正确;
  • AI 自动求解时,使用 is_blocked() 寻找当前可以安全消除的箭头;
  • AI 提示时,同样通过求解器寻找下一步正确操作。

因此,整个游戏的核心逻辑可以概括为:

路径阻挡检测
      ↓
 ┌────┼────┐
 ↓    ↓    ↓
玩家操作  关卡生成  AI求解
                  ↓
             AI提示一步

这样可以避免针对不同功能重复编写大量相似代码,也使游戏规则在不同模块中的判断结果保持一致。

四、AIGC 使用过程

1.AIGC 使用记录

在项目开发过程中,我使用 ChatGPT 辅助进行作业分析、功能设计、代码实现和界面优化。AI 主要用于提供实现思路和代码参考,最终内容均结合项目实际情况进行了调整和验证。

GPT牛比!

子任务 借助何种 AIGC 技术 AI 实现或提供了什么 实际效果 人工修改
作业内容分析 ChatGPT 将课程作业要求完整提供给 ChatGPT,请其分析任务内容并整理开发步骤与博客结构,帮助明确需要完成的功能、测试、AIGC 记录、PSP 表格等内容 AI 将较长的作业要求拆分为多个阶段,使项目开发目标更加清晰,便于按步骤逐项完成 根据自己的开发进度调整任务顺序,并删减部分不需要立即完成的内容
随机可解关卡生成 ChatGPT 提出按照“正确消除顺序的反方向”生成箭头的方法,在生成每个箭头时调用路径检测函数筛选可行方向 解决了完全随机生成关卡可能出现无解布局的问题,生成的关卡能够正常完成 将生成逻辑接入原有项目,并将三个关卡的箭头数量设置为 10、15、20,通过实际试玩验证关卡可解
游戏开始界面设计 ChatGPT / AIGC 图像生成 根据森林、自然、休闲解谜风格生成游戏开始界面视觉方案和背景图,并给出按钮悬停放大、上浮动画的实现建议 整体风格符合预期,但生成的背景图中自带开始按钮,与实际交互按钮存在位置和大小差异 将开始按钮单独制作成透明图片覆盖原按钮,并多次调整按钮大小、中心位置和悬停缩放比例
游戏交互与反馈优化 ChatGPT 提供箭头飞出动画、碰撞抖动、生命值、撤销、计时、星级评价以及音效播放等功能的实现思路 基本功能能够运行,使游戏的交互反馈比最初版本更加完整 根据实际运行效果调整动画速度、音量、按钮位置和状态切换逻辑,并补充成功、失败及背景音乐等资源

2.AIGC 使用记录截图

  • 作业内容分析

最开始的那个翻不到了,所以新开了一个对话。
7ai1

  • 随机可解关卡生成
    8ai2

  • 游戏开始界面设计

9ai3

  • 游戏交互与反馈优化
    10ai4

3.AIGC 使用总结

AIGC 在本项目中主要承担了思路辅助、代码参考和界面设计建议的作用。AI 生成的内容并不能直接完全应用到项目中,例如界面尺寸、按钮位置、随机关卡逻辑以及动画效果都需要结合实际程序进行修改和测试。

在使用 AIGC 的过程中,我会先理解 AI 给出的实现方案,再将其整合到现有代码中,并通过运行程序发现问题、调整参数和修改逻辑。因此,AIGC 提高了开发效率,但最终功能的实现和调试仍需要结合项目实际情况人工完成。

五、测试结果

在完成游戏主要功能后,对程序的核心功能、界面交互以及游戏状态切换进行了测试,测试结果如下。

测试编号 测试项目 预期结果 实际结果 是否通过
T01 正确点击未被阻挡的箭头 箭头沿当前方向飞出屏幕,并从棋盘中消失 箭头正常播放飞行动画并消失,剩余箭头数量减少 通过
T02 点击前方被阻挡的箭头 箭头不能飞出,播放错误反馈并扣除一次生命值 箭头变红并抖动,播放错误音效,生命值减少 1 通过
T03 连续失误 3 次 生命值归零,进入挑战失败结算界面 第 3 次失误后生命值归零,播放失败音效并进入失败界面 通过
T04 清空当前关卡所有箭头 进入通关结算界面,并显示星级、用时等信息 成功进入通关界面,正确显示星级、失误次数和用时 通过
T05 点击“下一关” 加载下一关,生命值和计时器重新初始化 正常进入下一关,箭头数量增加,生命值恢复,计时重新开始 通过
T06 完成全部 3 个关卡 进入全部通关界面,并可以重新开始游戏 第三关完成后进入全部通关界面,“再玩一次”和“返回首页”功能正常 通过
T07 使用“撤销上一步”功能 恢复上一次操作前的箭头和生命值状态 成功恢复上一状态,连续撤销功能正常 通过
T08 点击“重新开始” 当前关卡恢复初始状态,生命值和计时器重置 当前关卡重新加载,生命值恢复为 3,计时重新开始 通过
T09 点击“返回首页” 返回开始界面,并停止游戏背景音乐 成功返回首页,背景音乐停止,开始按钮可以再次进入游戏 通过
T10 音效与背景音乐测试 不同游戏状态播放对应音效,游戏过程中循环播放背景音乐 开始按钮、错误、通关、失败音效均正常播放,背景音乐正常循环 通过

测试总结

经过测试,游戏的箭头消除、路径阻挡检测、生命值、关卡切换、撤销、计时、结算以及音效等主要功能均能够按照预期运行。

测试过程中未发现影响正常游戏流程的严重问题,各游戏状态之间能够正确切换,基本达到了项目预期目标。

六、PSP 表格

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

从 PSP 表格可以看出,本次项目实际耗时比预计耗时多约 3.5 小时。其中,Python 与图形库学习、关卡设计以及测试修改阶段的实际耗时相对较长,主要原因是在开发过程中对游戏进行了多次调整和完善。通过本次开发,我也更加认识到在进行项目时间估算时,需要为调试和功能优化预留一定时间。

七、心得体会

本次开发用时1天,写博客花了半天。本来只用了半天时间已经开发出了符合最基本要求的程序,但是游戏界面长得非常的丑,我不想就这么交上去,所以就慢慢打磨,比如美化界面和添加很多神人音效。请看我的最初作品:

11

再说说开发过程吧。我看着史山代码从500行,叠到1000行,再叠到现在2500行。我没有使用agent,所以和gpt的交互是我不断提出要求,修改功能或者增加新模块,它就给我新的代码,叠盒子一样叠了两千多行。做的过程中感觉自己真挺菜的,看作业刚发没半天,baoshuo就做完了,我却连git功能还得叫ai教我。

但是我必须要说,做出成品的那个瞬间,我心里一股自豪感和满足感油然而生。真的,做完游戏以后我自己反反复复玩了好几遍,就好像在欣赏一个自己亲手雕琢出来的精美玉器。因为,这是我真正意义上第一个亲手做的游戏作品,还融入了我自己想的很多创意。

你要是问我为什么投入这么多时间打磨作品?一部分原因是想让作业更高分,另一部分原因是......好玩啊,你不觉得自己写游戏比玩游戏有意思多了吗?

也许有的人会说,不就ai写的一个破游戏吗,真闹麻了。也有的人会说,一个小作业也屁话这么多,简直豪情在天。是AI写的游戏没错,但开发是我在开发,而ai只是辅助开发的工具。我没提要求,ai能直接呈现成品给我吗?还有这是我自己独立开发出的作品,并且在这篇博文分享自己真实的历程和心得体会,您不想看可以退出去关掉,我没强迫您进来看。

最后感谢各位看官姥爷看到博文的最后,以上就是我这次开发的全部经历了。依旧恳求老师和助教能够欣赏我的作品,为我的作业打上好评。我的源码在仓库上都是公开的,如果觉得下载麻烦,我也会把打包好的exe文件放在上面。本项目制作不易,各位看官姥爷如果喜欢我的作品,请点击链接前往我的仓库送上一颗星星,感激不尽!

最后再次重申:我的作品随便供大家参考,所有的图像、声音素材也放在仓库里供大家下载,但是请你不要照搬。

posted @ 2026-09-15 10:21  yz_Yezi  阅读(213)  评论(0)    收藏  举报