[P] 结对项目:影蛇舞

结对项目:影蛇舞

项目 内容
这个作业属于哪个课程 2025年春季软件工程(罗杰、任健)
这个作业的要求在哪里 结对作业:影蛇舞
我在这个课程的目标是 通过学习和团队合作,了解敏捷开发流程。提高个人编码素养,掌握软件工程的核心概念和方法。
这个作业在哪个具体方面帮助我实现目标 在结对中培养合作精神,提升个人能力,增强自我动力,提升软件工程的理论基础。

结对项目:博客问题清单

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

引入

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

3月22日 8:55

调查

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

I. 没有听说过;

我之前没有学习过这种可以将多种语言编译形成网页上都可以运行的代码,因为我之前在前端涉及的都是页面展示之类的简单情形,不涉及效率,因此对于这种架构从来没有听说过。包括TS语言都是在课程组给予链接后方才学会基础语法用于本次作业。

总结

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

3月22日 9:35

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

结对过程

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

3月22日 9:47

→ 📖 Q1.2(P) 请在完成任务的同时记录,并在完成任务后整理完善:
  1. 浏览任务要求,参照 附录A:基于 PSP 2.1 修改的 PSP 表格,估计任务预计耗时;
  2. 完成编程任务期间,依次做了什么(比如查阅了什么资料,随后如何进行了开发,遇到了什么问题,又通过什么方式解决);
Personal Software Process Stages 个人软件开发流程 预估耗时(分钟) 实际耗时(分钟)
PLANNING 计划 5min 3min
- Estimate - 估计这个任务需要多少时间 5min 3min
DEVELOPMENT 开发 113min 101min
- Analysis & Design Spec - 需求分析 & 生成设计规格(确定要实现什么) 10min 9min
- Technical Background - 了解技术背景(包括学习新技术) 0min 0min
- Coding Standard - 代码规范 15min 15min
- Design - 具体设计(确定怎么实现) 5min 5min
- Coding - 具体编码 40min 27min
- Code Review - 代码复审 7min 5min
- Test Design - 测试设计(确定怎么测,比如要测试哪些情景、设计哪些种类的测试用例) 6min 4min
- Test Implement - 测试实现(设计/生成具体的测试用例、编码实现测试) 30min 36min
REPORTING 报告 22min 21min
- Quality Report - 质量报告(评估设计、实现、测试的有效性) 10min 9min
- Size Measurement - 计算工作量 2min 2min
- Postmortem & Process Improvement Plan - 事后总结和过程改进计划(总结过程中的问题和改进点) 10min 10min
TOTAL 140min 125min
  • 完成编程任务期间,依次做了什么(比如查阅了什么资料,随后如何进行了开发,遇到了什么问题,又通过什么方式解决);

在看到这个任务的编程语言要求后,我们首先调研了Assembly和Rust的实现难度。在经过一个小时的调研后,我们发现Assembly实现起来更加轻松高效,于是我们选取了Assembly进行开发。

针对第一部分的具体问题,我们首先在互联网上查询了一些贪吃蛇的算法。但最终发现,对于我们这种贪吃蛇长度不增长,问题规模小的情况,直接采取bfs比较合适。我们最终选取了用bfs求出蛇到果子的最短路径,依据该最短路径决定每一步方向的方法。

测试

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

我们参考了课程组给出的test.js文件,借用greedy_sanke_fn_checker函数并增加更多测试样例,我们主要测试了以下一些情况

  • 测试直接吃到食物
  • 测试角落导航
  • 测试环形身体阻挡路径
  • 测试垂直方向长蛇绕行
  • 测试贴边移动
  • 测试L型身体导航
  • 测试直角转弯逻辑

基本覆盖了所有贪吃蛇程序在实际运行过程中可能遭遇的情况。
评估测试的有效性一方面观察是否覆盖到所有的分支,第二是否考虑到一些边界情况。

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

单元测试(模块测试)是开发者编写的一小段代码,用于检验被测代码的一个很小的、很明确的功能是否正确。

单元测试让你在开发过程中早早发现问题,修复起来也轻松多了。这就像是在做菜时尝一尝味道,看看需要不需要调整,总比做完了才发现放多了盐好。
代码质量提升: 它迫使你写出可测试的代码,通常这也意味着你的代码质量会更高。因为你得考虑到代码的结构和依赖,这样的代码通常更加模块化,易于维护。
降低测试成本: 由于测试是基于小单元实现的,定位问题,修复bug十分迅速。因此,测试的成本大大减少。

总结

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

3月22日 12:30

→ 📖 Q1.6(I) 请写下本部分的心得体会。

初识结对编程,对于小小的程序员是一件很新奇的事情。作为一名领航员(偶尔是驾驶员),观看搭档写程序是件很有趣的事情,有时候会因为搭档无法完全理解自己的意思导致代码实际编写效果与预期不同。而且,双方对于某个问题存在分歧,真的是谁也拗不过谁,不过在思维的碰撞中确实找到了解决问题最好的办法。
此阶段是一个磨合阶段,两人在一起,我相信可以解决问题,互相学习,提升自己的能力,也能促进彼此的成长。在磨合的过程中,即使会花费较多的时间,但是在体验中我明确了搭档了的side,在编程时也会考虑以前无法单人考量的过程。
最关键的,培养了我的表达能力!

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

结对过程

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

3月23日 9:12

→ 📖 Q2.2(P) 请在完成任务的同时记录,并在完成任务后整理完善:
  1. 浏览任务要求,参照 附录A:基于 PSP 2.1 修改的 PSP 表格,估计任务预计耗时;
  2. 完成编程任务期间,依次做了什么(比如查阅了什么资料,随后如何进行了开发,遇到了什么问题,又通过什么方式解决);
Personal Software Process Stages 个人软件开发流程 预估耗时(分钟) 实际耗时(分钟)
PLANNING 计划 5min 5min
- Estimate - 估计这个任务需要多少时间 5min 5min
DEVELOPMENT 开发 94min 102min
- Analysis & Design Spec - 需求分析 & 生成设计规格(确定要实现什么) 7min 6min
- Technical Background - 了解技术背景(包括学习新技术) 0min 0min
- Coding Standard - 代码规范 5min 8min
- Design - 具体设计(确定怎么实现) 5min 3min
- Coding - 具体编码 30min 28min
- Code Review - 代码复审 7min 7min
- Test Design - 测试设计(确定怎么测,比如要测试哪些情景、设计哪些种类的测试用例) 10min 8min
- Test Implement - 测试实现(设计/生成具体的测试用例、编码实现测试) 30min 42min
REPORTING 报告 15min 21min
- Quality Report - 质量报告(评估设计、实现、测试的有效性) 7min 10min
- Size Measurement - 计算工作量 5min 8min
- Postmortem & Process Improvement Plan - 事后总结和过程改进计划(总结过程中的问题和改进点) 3min 3min
TOTAL 114min 128min

在本次作业中,相比于上次的作业我们仅仅是多了障碍物的存在,对于BFS寻路没有什么影响。所以,我们发现我们上一次的作业基本可以套用,只需要加一个Set类型变量表示障碍物,于是我们较快地决定贪吃蛇运行策略,迅速完成了编码。

代码可复用性与需求变更

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

我们修改了eedySnakeMoveBarriers的函数实现,添加了barriers参数表示障碍物,添加了isBarrier函数判断某个坐标是否为障碍物。我们要求蛇不能走到标注为“障碍物”的各自。

通过这种方式,我们迅速完成了第二次作业的编码。

→ 📖 Q2.4(I) 请说明在编码实现时,可以采取哪些设计思想、考虑哪些设计冗余,来提高既存代码适应需求变更的能力。
  • 开闭原则(OCP)对扩展开放,对修改关闭。通过抽象和接口隔离变化点。
  • 策略模式: 将算法或行为封装为独立策略,运行时动态切换。
  • 模块化与微服务 按功能拆分模块/服务,变更影响局部化。
  • 数据冗余:存储派生字段避免频繁计算,牺牲空间换灵活性。例如5 * 5和8*8的格子可以尽可能地开到更大的数组以适应需求
  • 接口冗余:预留扩展接口,即使当前仅有一种实现。或者将一些可能会变化或者很可能再次使用的设置接口,利于扩展

头脑风暴环节

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

🧑‍💻 T2 的基础上,场地里不再是只有 1 个果子,而是总共有 n 个果子 (1 < n < 10 ),果子随机分布在场地中且不会刷新,保证不与障碍物重叠,保证每个果子均可达,且至少存在一条成功吃掉所有果子的路线,其余条件保持不变,请你找出一条吃完所有果子的行动路径。
若一条果子到其他果子存在2条以上路径,则蛇一定不会困毙。通过BFS搜索单个果子到其他果子的路径,建立一张图。所以问题就变成了,如何访问图的节点,找到一条可以经过所有点的路径。由于度为1的节点只能最后访问,我们从度为1的节点开始搜索,总能找到一条路径。(因为其他点的度不小于2,否则将不存在路径)

总结

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

3月23日 11:23

→ 📖 Q2.7(I) 请写下本部分的心得体会。

再进结对编程,本阶段作为领航员明显感觉到驾驶员可以很好地听懂自己的意思,本阶段的指导给出后,驾驶员在很短地时间内就完成了本阶段的任务。结对编程也许是一个促进友谊的特殊活动吧,在编程过程中展示程序员的一面,成为一名编程上的朋友。

另外,本阶段触发的测试bug,让我们对测试的重要性,因为已经复用了上一次的代表,似乎没有做好回归测试,导致出现了一些问题。不过,没有在submit出现问题,都是好事。

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

结对过程

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

3月31日20.30

→ 📖 Q3.2(P) 请在完成任务的同时记录,并在完成任务后整理完善:
  1. 浏览任务要求,参照 附录A:基于 PSP 2.1 修改的 PSP 表格,估计任务预计耗时;
  2. 完成编程任务期间,依次做了什么(比如查阅了什么资料,随后如何进行了开发,遇到了什么问题,又通过什么方式解决);
Personal Software Process Stages 个人软件开发流程 预估耗时(分钟) 实际耗时(分钟)
PLANNING 计划 10 8
-Estimate -估计这个任务需要多少时间 10 8
DEVELOPMENT 开发 390 322
Analysis & Design Spec 需求分析 & 生成设计规格(确定要实现什么) 20 15
Technical Background 了解技术背景(包括学习新技术) 0 0
- Coding Standard - 代码规范 30 20
- Design - 具体设计(确定怎么实现) 30 25
- Coding - 具体编码 120 110
- Code Review - 代码复审 20 30
- Test Design - 测试设计(确定怎么测,比如要测试哪些情景、设计哪些种类的测试用例) 30 38
- Test Implement - 测试实现(设计/生成具体的测试用例、编码实现测试) 40 85
REPORTING 报告 70 72
- Quality Report - 质量报告(评估设计、实现、测试的有效性) 20 23
- Size Measurement - 计算工作量 20 17
- Postmortem & Process Improvement Plan - 事后总结和过程改进计划(总结过程中的问题和改进点) 30 32
TOTAL 合计 370 402

本次最初计划采用强化学习,但是由于没有可靠的训练,以及对于强化学习的理解不够深入。经过尝试后发现不理想放弃采用,继而采用了一种启发式的算法来解决此次任务。
为了搜索好的算法,我们前去网站观看较好地贪吃蛇算法,不过由于其问题大多不会考虑对抗,yield的使用不熟练,因此放弃。

设计启发式的算法,两人对“好”的定义,纠结了一会,(以蛇为主体/以果子为主体),最后决定是评判果子的得分来进行抉择。

需求建模和算法设计

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

在对抗中,意味着出现了多个目标果子和一个动态的障碍物,因此首先需要选取相对最近最优的目标果子,同时预测躲避障碍物。在这个过程中,可能无最近的果子和到达果子的路线,这时,将不能输出无法找到路径,而是尽可能地活下去,选取出现障碍物最小概率的点。

→ 📖 Q3.4(P) 请说明针对该任务,你们采取了哪些策略来优化决策。具体而言,怎么避免死亡?怎么吃到更多果子?如何编程实现。

由于场上存在众多果子,为了尽可能地吃果子,需要计算所有果子相对我们的距离 \(d\),然后计算果子相对其他蛇的距离,综合评估出最近的果子,这些果子评为“好果子”。选取“好果子”,作为目标进行寻路。当场上不存在“好果子”,都是“坏果子”时,那么我们就会自旋,或者随机游走,等待好果子的出现。

蛇蛇死亡来源于撞墙和其他蛇的碰撞,我们引入寻找果子时,需要远离其他蛇。假设蛇尽可能会选取较近的目标,那么对于“好果子”的选取,就尽量选择距离“坏果子”最远的“好果子”。

此外,当存在碰撞风险时,即两蛇头部可选区域重合,我们将计算蛇头命中各自最小概率的格子进行选取,具体为统计所有蛇头到达此处的次数(假设每个格子的概率相同)。

死亡一种为困毙,为了避免这种情形,引入外移惩罚。在移动时,当蛇头随机选取方向,降低外移到边界的概率,因为大多数的困毙来源于走到角落。

编程对于上述策略的实现,我们采用了评价函数,量化决策的方向,根据计算得到的评价值,选择最优的方向。如果子的分数为\(score = \sum{d_e} - d_{mine} \times k\),。其中\(d_f\)为果子到敌人蛇头的距离,\(d_{mine}\)为蛇头到自己的距离,\(k\)为调整系数。通过此来区分“好果子”和“坏果子”。

软件度量

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

根据假设,

给出公式一:\(\frac{Times_{die}}{Times_{live}}\) 来评估生存效果。其中\(Times_{die}\)为死亡次数,\(Times_{live}\)为存活次数。通过此公式,我们可以评估程序的有效性。

公式二: \(\frac{round_{die}}{round}\) 来计算死亡的回合数,根据此我们可以知晓死亡的提前程度。 这两个指标越大,代表我们的存活率和存活能力越强。

公式三:\(\sum {score_i} \times enemy\) 用来评估蛇吃分数的能力,指标越大,代表蛇的吃分能力越强。

总结

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

4月1日 18.00

→ 📖 Q3.7(I) 请写下本部分的心得体会。

本次达到共舞的阶段,两人的身份在此时也会不断交替,灵感迸发。在此过程中,编程的效率确实比单人更加具有效率,个人的思绪总是会遇到郁结,当伙伴给提示后,能够保证编程效率的极大提高。 最终编程任务也是快速的完成了。不过,测试确实花了超过编程的时间,在多人对抗的情况下,不再是吃到果子就算成功,需要有多种考量来确定当前策略的性能优劣。许多意想不到的情形下,蛇蛇会陷入困境,这也是我们需要反思的地方。

结对项目总结

结对过程回顾和反思

→ 📖 Q4.1(P) 提供两人在讨论的结对图像资料。
image.png
→ 📖 Q4.2(P) 回顾结对的过程,反思有哪些可以提升和改进的地方。
  • 我们在完成第三次作业时选择了碎片化时间进行编码,导致效率有所降低;
  • 我们对ts语言了解不深,很多ts语言特性了解不够深入。因此我们在编码过程中基本沿用C语言的编程习惯,代码可读性有待加强。
  • 编码时忍不住玩手机,导致浪费了一些时间。
→ 📖 Q4.3(I) 锐评一下你的搭档!并请至少列出三个优点和一个缺点。

我的搭档是一个动手能力极强的程序员,在编程过程中有时可以快速完成独立完成任务而不需要领航员。它十分注重效率,时常敦促我完成任务。在本次任务中,它对测试十分上心,具有较为全面的测试考量,我对他十分认可。
优点:

  • 充满激情,对编程充满热情,对测试也十分上心。
  • 善于沟通,能够有效地提升团队合作能力。
  • 学习能力强,表达能力佳,能够快速学习新知识(webAssembly是他快速学习后教会我的)。
  • 主动承担任务,对于任务计时和划分工作量十分负责。
  • 良好的时间管理,pairComplier的工作时间分布其安排的很合理,我认为这让我的工作更有条理

缺点:

  • 有时过度追求效率导致自己的程序健壮性不强,导致代码质量不高,最终反而造成效率下降。(他似乎没有意识到)
  • 情绪有时很激动,对于无法改变的事情抱怨过多(对于他认为不合理的事情),我觉得有时会造成士气低沉,毕竟这件事怎么都得做。

对结对编程的理解

→ 📖 Q4.4(I) 说明结对编程的优缺点、你对结对编程的理解。

优点为在两人合作时可以产生思想碰撞,对于问题的思考更加全面,因而解决算法问题可以快速直抵关键。第二点就是可以边编写边审查,降低了bug的出现。
缺点则是需要花费更多的时间,因为需要两人共同完成,因此效率会有所降低。另外,在编程过程中,需要注意代码的可读性,否则容易出现代码混乱。两人存在沟通的成本(在磨合后此成本会降低)

结对编程是以短期效率换取长期质量与团队增益的工程实践,其价值体现在知识沉淀、风险防控及团队协同能力的提升。
但它本质是协作模式,而非万能解药:结对编程并非替代独立工作的“银弹”,而是特定场景下的协作增强工具。需根据任务复杂度、团队成熟度灵活选用,例如:

  • 攻坚场景:复杂模块设计时,双人协作可减少设计缺陷。

  • 教学场景:导师通过实时指导帮助新人理解代码规范与系统架构。

  • 知识平权:跨领域合作(如前后端联调)时快速对齐技术细节。

代码实现提交

→ 📖 Q4.5(P) 请提供你们完成代码实现的代码仓库链接。
结对作业:影蛇舞 ——github仓库
posted @ 2025-04-06 08:53  八月萑苇  阅读(30)  评论(0)    收藏  举报