[P] 结对项目:影蛇舞

Posted on 2025-04-06 23:56  Daytoy1014  阅读(72)  评论(0)    收藏  举报

[P] 结对项目:影蛇舞

项目 内容
这个作业属于哪个课程 2025年春季软件工程
这个作业的要求在哪里 [I.1] 个人作业:阅读和提问
我在这个课程的目标是 学习现代软件构建的工程方法,锻炼团队协作能力。在团队的共同合作下产出符合流程的高质量软件。
这个作业在哪个具体方面帮助我实现目标 体验结对编程,锻炼极限开发

Chapter.0 Belua multorum es capitums.(你是多首的怪物。)

引入

→ 📖 Q0.1(P) 请记录下目前的时间。

2025/3/20 13:30

调查

→ 📖 Q0.2(I) 作为本项目的调查:请如实标注在开始项目之前对 Wasm 的熟悉程度分级,可以的话请细化具体的情况。

I. 没有听说过;

II. 仅限于听说过相关名词;

III. 听说过,且有一定了解;

IV. 听说过,且使用 Wasm 实际进行过开发(即便是玩具项目的开发)。

I. 没有听说过

总结

→ 📖 Q0.3(P) 请记录下目前的时间。

2025/3/30 14:13

Chapter.1 不畏迷茫,只管前进。(迷子でもいい、前へ進め。)

结对过程

→ 📖 Q1.1(P) 请记录下目前的时间。

2025/3/30 14:14

→ 📖 Q1.2(P) 请在完成任务的同时记录,并在完成任务后整理完善:
  1. 浏览任务要求,参照 附录A:基于 PSP 2.1 修改的 PSP 表格,估计任务预计耗时;
  2. 完成编程任务期间,依次做了什么(比如查阅了什么资料,随后如何进行了开发,遇到了什么问题,又通过什么方式解决);
  • 预估时间:
Personal Software Process Stages 个人软件开发流程 预估耗时(分钟) 实际耗时(分钟)
PLANNING 计划 5
- Estimate - 估计这个任务需要多少时间 5
DEVELOPMENT 开发 202
- Analysis & Design Spec - 需求分析 & 生成设计规格(确定要实现什么) 10
- Technical Background - 了解技术背景(包括学习新技术) 30
- Coding Standard - 代码规范 2
- Design - 具体设计(确定怎么实现) 30
- Coding - 具体编码 60
- Code Review - 代码复审 20
- Test Design - 测试设计(确定怎么测,比如要测试哪些情景、设计哪些种类的测试用例) 10
- Test Implement - 测试实现(设计/生成具体的测试用例、编码实现测试) 40
REPORTING 报告 50
- Quality Report - 质量报告(评估设计、实现、测试的有效性) 20
- Size Measurement - 计算工作量 10
- Postmortem & Process Improvement Plan - 事后总结和过程改进计划(总结过程中的问题和改进点) 20
TOTAL 合计 257
  • 我们首先通过题目的描述和要求进行讨论解决方法。我们主要考虑快以及不发生碰撞。起初我们采用贪心的想法,但是发现对于有些果子以及蛇的位置,直接贪心肯定会发生碰撞。
    为了解决这个问题,我们分类讨论分析多种位置情况,结果发现,蛇只会和第二节身子相撞,不会与第三节身子和蛇尾相撞,于是就简化了碰撞的复杂度,蛇头只能向三个方向行动。 然后分类讨论不同位置情况,利用贪心,我们开始代码编写。同时因为果子肯定在场地里面,所以可以减少部分场地边界的判断。

测试

→ 📖 Q1.3(P) 请说明针对该任务,你们设计和实现测试的方法及过程,包括但不限于:出于对需求的哪些考虑设计了哪些测试用例、如何评估所设计测试的有效性 等等。

我们重点针对碰撞情况(越界情况)进行测试。

最开始随便设计一个参数进行测试,看看代码是否能正确运行,然后进行课程组的测试。

后面设计了一些特殊情况,比如(1,1)(1,8)(8,1)(8,8)等边界情况,测试是否碰撞。同时针对蛇需要“绕”一下的情况设计测试样例。

再后面,用随机生成的方式写了一个评测程序,进行大量的随机测试,测试蛇的行动是否合理,是否会碰撞。

→ 📖 Q1.4(I) 请说明单元测试对软件开发的作用。

单元测试可以在软件开发中帮助我们尽早发现和修正错误,确保每个模块按照预期工作,从而在重构或扩展代码时降低出错风险。它能提高代码质量、便于维护和增强团队协作效率。

总结

→ 📖 Q1.5(P) 请记录下目前的时间,并根据实际情况填写 附录A:基于 PSP 2.1 修改的 PSP 表格 的“实际耗时”栏目。

15:12 结束代码编写,开始测试
16:47 完成测试

17:52 复查代码和测试
18:40 完成测试复查,修改了测试程序的bug

Personal Software Process Stages 个人软件开发流程 预估耗时(分钟) 实际耗时(分钟)
PLANNING 计划 5 3
- Estimate - 估计这个任务需要多少时间 5 3
DEVELOPMENT 开发 202 257
- Analysis & Design Spec - 需求分析 & 生成设计规格(确定要实现什么) 10 5
- Technical Background - 了解技术背景(包括学习新技术) 30 10
- Coding Standard - 代码规范 2 1
- Design - 具体设计(确定怎么实现) 30 30
- Coding - 具体编码 60 58
- Code Review - 代码复审 20 10
- Test Design - 测试设计(确定怎么测,比如要测试哪些情景、设计哪些种类的测试用例) 10 20
- Test Implement - 测试实现(设计/生成具体的测试用例、编码实现测试) 40 123
REPORTING 报告 50 30
- Quality Report - 质量报告(评估设计、实现、测试的有效性) 20 10
- Size Measurement - 计算工作量 10 10
- Postmortem & Process Improvement Plan - 事后总结和过程改进计划(总结过程中的问题和改进点) 20 10
TOTAL 合计 257 290
→ 📖 Q1.6(I) 请写下本部分的心得体会。

第一阶段的任务相对基础,更多是为整个结对编程项目做好准备。这个部分的目标主要是熟悉开发流程、明确合作方式,并掌握项目所需的技术栈。在这一过程中,我们选择了 Rust 作为开发语言,这对我们来说是一个全新的尝试。

因为我们是熟人,沟通起来没有障碍,也能直接表达各自的看法。不过有时候正因为太熟了,彼此都比较有主见,一些实现细节会反复讨论,效率不算特别高。但这些讨论也并非没有收获,有时一个小小的分歧反而能让我们跳出思维定式,发现更优的解决方案。

我们还花了不少精力在测试上,希望尽量覆盖各种情况。为此写了自动生成随机数据的测试工具,虽然这个过程有些繁琐,加上对 Rust 的调试流程不熟练,卡了不少时间,但也确实提升了我们对语言本身和测试工具链的掌握程度。

这部分虽然不算困难,但在合作节奏、技术选型、思路交流等方面都起到了重要的磨合作用。希望在后面的开发中,我们能在这个基础上配合得更高效。

Chapter.2 即使迷茫,也要前行。(迷子でもいい、迷子でも進め。)

结对过程

→ 📖 Q2.1(P) 请记录下目前的时间。

2025/3/31 20:35

→ 📖 Q2.2(P) 请在完成任务的同时记录,并在完成任务后整理完善:
  1. 浏览任务要求,参照 附录A:基于 PSP 2.1 修改的 PSP 表格,估计任务预计耗时;
  2. 完成编程任务期间,依次做了什么(比如查阅了什么资料,随后如何进行了开发,遇到了什么问题,又通过什么方式解决);
  1. 预估时间
Personal Software Process Stages 个人软件开发流程 预估耗时(分钟) 实际耗时(分钟)
PLANNING 计划 5
- Estimate - 估计这个任务需要多少时间 5
DEVELOPMENT 开发 282
- Analysis & Design Spec - 需求分析 & 生成设计规格(确定要实现什么) 10
- Technical Background - 了解技术背景(包括学习新技术) 30
- Coding Standard - 代码规范 2
- Design - 具体设计(确定怎么实现) 60
- Coding - 具体编码 100
- Code Review - 代码复审 10
- Test Design - 测试设计(确定怎么测,比如要测试哪些情景、设计哪些种类的测试用例) 10
- Test Implement - 测试实现(设计/生成具体的测试用例、编码实现测试) 60
REPORTING 报告 50
- Quality Report - 质量报告(评估设计、实现、测试的有效性) 20
- Size Measurement - 计算工作量 10
- Postmortem & Process Improvement Plan - 事后总结和过程改进计划(总结过程中的问题和改进点) 20
TOTAL 合计 337
  1. 我们根据题目要求,首先进行了讨论,将问题转换为蛇头为起点,果子为终点,存在障碍物且不发生碰撞的最短路径问题。
    我们首先想到的是采用bfs算法,蛇头为了不碰撞身体,只有三个方向可以走,再考虑障碍物位置,进行bfs搜索。如果没找到路径,就返回-1,否则就返回第一步的方向。
    我们紧接着讨论了这个想法的可行性,我们发现存在一些障碍的情况导致,蛇可能需要“绕一下”,会走“回头路”,这就导致,普通的visited数组无法解决这个问题。
    遇到这个问题,我们查询了相关资料,并询问了大模型,最终我们选择A*的算法来解决这个问题。visited数组增加一个参数来进行判断。

代码可复用性与需求变更

→ 📖 Q2.3(P) 请说明针对该任务,你们对 🧑‍💻 T1 中已实现的代码进行了哪些复用和修改。

因为T1的代码是基于贪心算法实现的,而我们现在需要的是A*算法,所以我们对T1的代码进行了重构,主要是将贪心算法的部分替换为A*算法的实现。我们保留了原有的函数结构和变量命名,以便于理解和维护。
对于碰撞判断部分,蛇身碰撞和边界判断依旧使用了T1的代码,只是增加了对障碍物的判断。

→ 📖 Q2.4(I) 请说明在编码实现时,可以采取哪些设计思想、考虑哪些设计冗余,来提高既存代码适应需求变更的能力。
  • 设计思想:
    • 模块化设计:将功能划分为独立、职责单一的模块(如碰撞检测、评分函数、路径搜索等),便于替换或扩展。
    • 高内聚低耦合:每个模块只负责自己的逻辑,尽量减少模块之间的依赖。
  • 设计冗余:
    • 预留扩展字段:在数据结构中预留字段或支持元数据字段,便于将来加入新状态或标记。
    • 冗余参数设计:函数定义中提前包含一些暂未使用但可能有用的参数,提升未来功能接入的灵活性。

头脑风暴环节

**→ 📖 Q2.5(P) **只吃一个食物可满足不了贪吃蛇的欲望,请一起思考并简述以下场景中贪吃蛇的策略:

🧑‍💻 T2 的基础上,场地里不再是只有 1 个果子,而是总共有 n 个果子 (1 < n < 10 ),果子随机分布在场地中且不会刷新,保证不与障碍物重叠,保证每个果子均可达,且至少存在一条成功吃掉所有果子的路线,其余条件保持不变,请你找出一条吃完所有果子的行动路径。

采用“优先吃最近果子”的贪心策略,选取距离当前蛇头最近的果子,使用A*算法(T2算法)判断是否可达,当无法到达时引入回退机制,尝试次优目标或重构路径。

总结

→ 📖 Q2.6(P) 请记录下目前的时间,并根据实际情况填写 附录A:基于 PSP 2.1 修改的 PSP 表格 的“实际耗时”栏目。

2025/3/31 21:53 中途暂停

2025/3/31 22:25 继续

2025/4/1 0:18 结束

Personal Software Process Stages 个人软件开发流程 预估耗时(分钟) 实际耗时(分钟)
PLANNING 计划 5 3
- Estimate - 估计这个任务需要多少时间 5 3
DEVELOPMENT 开发 282 177
- Analysis & Design Spec - 需求分析 & 生成设计规格(确定要实现什么) 10 5
- Technical Background - 了解技术背景(包括学习新技术) 30 30
- Coding Standard - 代码规范 2 1
- Design - 具体设计(确定怎么实现) 60 20
- Coding - 具体编码 100 71
- Code Review - 代码复审 10 10
- Test Design - 测试设计(确定怎么测,比如要测试哪些情景、设计哪些种类的测试用例) 10 10
- Test Implement - 测试实现(设计/生成具体的测试用例、编码实现测试) 60 30
REPORTING 报告 50 11
- Quality Report - 质量报告(评估设计、实现、测试的有效性) 20 5
- Size Measurement - 计算工作量 10 3
- Postmortem & Process Improvement Plan - 事后总结和过程改进计划(总结过程中的问题和改进点) 20 3
TOTAL 合计 337 191
→ 📖 Q2.7(I) 请写下本部分的心得体会。

我们在这个部分经历了2个阶段的设计。

首先是想使用简单的BFS去搜索是否有可达路径,但经过讨论后,我们发现了一种情况:当蛇必须绕一大圈甚至“回头”才能抵达目标位置时,普通的 BFS 会错误地把某些本应可达的位置标记为不可达。

这个问题暴露了我们在设计状态空间时的不足。BFS 本身不是不能处理,只是我们当时为了图方便,使用了一个过于简化的 visited 数组,忽略了蛇身动态变化的影响。在意识到这个问题后,我们通过查找资料,转向了 A* 算法,因为它支持启发式搜索,看起来能更“聪明”地找到合适路径。但回过头来看,其实只要在 BFS 中对访问状态建模得更细致,例如把蛇身长度或回合数纳入状态判重条件,也应该是可以解决问题的。

Chapter.3 这就是我的前进、到我出场了!!!!!(It's MyGO!!!!!)

结对过程

→ 📖 Q3.1(P) 请记录下目前的时间。

2025/4/2 19:28 开始

→ 📖 Q3.2(P) 请在完成任务的同时记录,并在完成任务后整理完善:
  1. 浏览任务要求,参照 附录A:基于 PSP 2.1 修改的 PSP 表格,估计任务预计耗时;
  2. 完成编程任务期间,依次做了什么(比如查阅了什么资料,随后如何进行了开发,遇到了什么问题,又通过什么方式解决);
  • 预估时间
Personal Software Process Stages 个人软件开发流程 预估耗时(分钟) 实际耗时(分钟)
PLANNING 计划 5
- Estimate - 估计这个任务需要多少时间 5
DEVELOPMENT 开发 267
- Analysis & Design Spec - 需求分析 & 生成设计规格(确定要实现什么) 5
- Technical Background - 了解技术背景(包括学习新技术) 30
- Coding Standard - 代码规范 2
- Design - 具体设计(确定怎么实现) 60
- Coding - 具体编码 120
- Code Review - 代码复审 10
- Test Design - 测试设计(确定怎么测,比如要测试哪些情景、设计哪些种类的测试用例) 10
- Test Implement - 测试实现(设计/生成具体的测试用例、编码实现测试) 30
REPORTING 报告 50
- Quality Report - 质量报告(评估设计、实现、测试的有效性) 20
- Size Measurement - 计算工作量 10
- Postmortem & Process Improvement Plan - 事后总结和过程改进计划(总结过程中的问题和改进点) 20
TOTAL 合计 322
  • 我们首先针对问题进行讨论,然后记录需要考虑的因素,进行建模,在这期间,主要询问大模型,帮助我们分析,然后利用传统的方式进行第一版开发。后面经过和别人的测试,发现效果不好,尝试深度学习开发,训练不出来,放弃,重新进行传统方式的改进,利用大模型,增加更多的评估变量。

需求建模和算法设计

→ 📖 Q3.3(P) 请说明你们如何建模这一需求。

在本任务中,我们将蛇的每一步行动建模为一个多目标评分问题,通过对各方向的综合打分来进行最优决策。我们根据对战模式的不同,分别设计并采用了两套差异化策略体系,以更好地适应 1v1 和 4v4 的博弈环境。

4v4 模式:更注重对抗与生存

  • 在 4v4 场景中,地图空间较大、敌人数量少,我们更强调“果子控制力”与“局部对抗中的生存能力”。
  • 建模时,我们重点考虑以下评分项:
    • safety_score: 避免被对方蛇头围堵;
    • free_score: 使用洪水填充评估当前自由空间;
    • food_score: 结合我方与敌方到果子的相对距离评估“吃到果子的优势”(实现了果子竞速建模);
    • center_score: 鼓励靠近地图中心,增强后续可行动性。
  • 策略特点: 以对抗为导向,控制局部资源,防止头对头碰撞,稳定吃果。

1v1 模式:更注重快速得分与多目标评估

  • 在 1v1 多蛇环境中,空间拥挤、节奏快,强调果断吃果子与避开混战,我们采用了简化模型、快速评估策略。
  • 建模时采用以下核心评分项:
    • food_score: 纯粹使用距离驱动,快速吃到最近果子;
    • danger_score: 避免进入敌方密集区域或墙角;
    • free_score: 粗略估计自由格子数量,确保蛇不被封死。
  • 策略特点: 快速、果断、避免碰撞为主,牺牲复杂性换取实时性。
→ 📖 Q3.4(P) 请说明针对该任务,你们采取了哪些策略来优化决策。具体而言,怎么避免死亡?怎么吃到更多果子?如何编程实现。

一、如何避免死亡

我们通过多维度判断来确保蛇尽可能存活,尤其在与敌方接近或空间受限的情况下,更加保守和避险。

  1. 安全性评分(safety_score
    • 计算当前位置与敌方蛇头的最小曼哈顿距离;
    • 距离越远评分越高,避免被头对头夹死;
  2. 空间评分(free_score
    • 使用洪水填充算法,估计当前方向的可行动空间大小;
    • 避免进入死胡同或封闭区;
  3. 边界惩罚与陷阱惩罚(danger_score
    • 如果当前位置靠近墙角或边界,或者空间极小,则给予惩罚;
  4. 敌人预测与头对头碰撞规避
    • 模拟敌方可能的移动方向,若发生头对头冲突,则当前方向降权;

二、如何吃到更多果子

为了最大化得分,我们在路径规划中积极争抢果子,尽量选取我方“能更快吃到”的目标果子。

  1. 果子接近度评分(fruit_score
    • 对每个方向,使用A*计算当前蛇头到所有果子的最小距离;
    • 距离越近,评分越高;
  2. 果子控制力评分
    • 若我方比其他所有蛇更快吃到某个果子,则提升得分;
  3. 中心控制策略(center_score
    • 鼓励靠近地图中心,提升未来吃果子灵活性;

软件度量

→ 📖 Q3.5(P) 请说明你们如何量度所实现的程序模块的有效性,例如:“如何说明我们的程序模块对弈能力很强?”尝试提出一些可能的定量分析方式。

在多轮测试对抗中,统计输赢情况以及死亡情况,统计胜率和死亡率。胜率越高,死亡率越低越有效。

总结

→ 📖 Q3.6(P) 请记录下目前的时间,并根据实际情况填写 附录A:基于 PSP 2.1 修改的 PSP 表格 的“实际耗时”栏目。

2025/4/2 20:40 完成部分代码,因为要软工开会,中途暂停,完成了evaluate_safety

2025/4/2 23:13 继续完成代码
2025/4/3 00:25 结束第一版本

2025/4/6 11:00 继续

2025/4/6 13:00 吃饭

2025/4/6 13:40 继续

2025/4/6 18:00 暂停

2025/4/6 21:00 继续

2025/4/6 23:30 结束

Personal Software Process Stages 个人软件开发流程 预估耗时(分钟) 实际耗时(分钟)
PLANNING 计划 5 3
- Estimate - 估计这个任务需要多少时间 5 3
DEVELOPMENT 开发 267 638
- Analysis & Design Spec - 需求分析 & 生成设计规格(确定要实现什么) 5 3
- Technical Background - 了解技术背景(包括学习新技术) 30 40
- Coding Standard - 代码规范 2 1
- Design - 具体设计(确定怎么实现) 60 60
- Coding - 具体编码 120 459
- Code Review - 代码复审 10 10
- Test Design - 测试设计(确定怎么测,比如要测试哪些情景、设计哪些种类的测试用例) 10 5
- Test Implement - 测试实现(设计/生成具体的测试用例、编码实现测试) 30 60
REPORTING 报告 50 13
- Quality Report - 质量报告(评估设计、实现、测试的有效性) 20 5
- Size Measurement - 计算工作量 10 3
- Postmortem & Process Improvement Plan - 事后总结和过程改进计划(总结过程中的问题和改进点) 20 5
TOTAL 合计 322 654
→ 📖 Q3.7(I) 请写下本部分的心得体会。

这个部分我们思考和讨论了非常久,需要考虑的因素非多。反复推敲才最终选定分1v1与4蛇策略。

结对项目总结

结对过程回顾和反思

→ 📖 Q4.1(P) 提供两人在讨论的结对图像资料。
→ 📖 Q4.2(P) 回顾结对的过程,反思有哪些可以提升和改进的地方。

在结对的过程中,我们的配合默契度较高,讨论也很顺畅,但是在一些问题上会有争论,导致效率降低。我们可以尝试使用一些工具来帮助我们更好地进行讨论,比如使用白板工具进行可视化讨论。
还有就是对一些问题纠结太多导致不能及时打代码,导致很多纸上谈兵。

→ 📖 Q4.3(I) 锐评一下你的搭档!并请至少列出三个优点和一个缺点。
  • 优点:

    • 执行力强;
    • 查找资料的能力很强;
    • 思维敏捷;
  • 缺点

    • 有时候太急了!

对结对编程的理解

→ 📖 Q4.4(I) 说明结对编程的优缺点、你对结对编程的理解。
  • 结对编程的优点:
    • 问题发现更及时:两人实时讨论,一方编码时另一方思考更高层逻辑或细节盲区,可以更早发现 bug 或潜在风险,减少返工。
    • 思维互补,提升方案质量:两个人往往有不同的理解和解决问题方式,在沟通中容易碰撞出更优的思路,有时候一个人没想到的点,另一个人能及时补上。
    • 学习效率高,知识共享快:尤其是一个人对某个工具或语言更熟时,另一个人能在实践中快速上手,边做边学,效率远胜单人摸索。
  • 结对编程的缺点:
    • 效率未必更高,甚至可能更低:如果两人节奏不一致,或者讨论太久卡在一个问题上,反而会拖慢整体进度;有时一个人独立实现反而更快。
    • 容易产生冲突:尤其是认识较熟的搭档,更容易出现“坚持己见”的情况,对代码风格、结构、优先级的分歧可能影响效率。

我认为结对编程的核心不是“轮流写代码”,而是“共同思考,持续对齐”。它更适合需要深入逻辑推理、算法设计或结构架构的开发任务,比如本次结对项目,讨论路径规划、评分策略这些复杂问题时,结对编程显著提升了我们方案的深度和代码的可靠性。

结对编程不是适合所有任务的“万能解”,但对于需要多人思维协作的问题来说,它是一个非常有价值的开发方式。

代码实现提交

→ 📖 Q4.5(P) 请提供你们完成代码实现的代码仓库链接。

https://github.com/Daytoy1014/2025BUAA-SE-PAIR