[P] 结对项目:影蛇舞

结对项目:博客问题清单

项目 内容
这个作业属于哪个课程 2025年春季软件工程(罗杰、任健)
这个作业的要求在哪里 [P] 结对项目:影蛇舞
我在这个课程的目标是 在 PSP 和 TSP 中磨炼自身
这个作业在哪个具体方面帮助我实现目标 通过合作和头脑风暴培养分析问题、解决问题的能力

请将本文件在代码仓库外复制一份,一边阅读和完成结对项目、一边填写入代码仓库外的版本,或采取简记、语音备忘等方式记载较复杂问题的要点之后再补充。请不要将本文档内的作答提交到代码仓库。

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

引入

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

3月26日11:58

调查

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

I. 没有听说过;

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

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

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

I. 完全没有听说过;

总结

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

3月26日12:14

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

结对过程

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

3月26日12:14

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

过程:

参考AssemblyScript官方文档, 学习如何使用其构建项目,理解测试程序代码,然后再根据题意编写主函数和测试代码。

测试

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

要考虑基础方向测试、边界测试、蛇头坐标和食物坐标连线有身体的测试、角落只能朝向蛇尾的测试。

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

从小处开始,杜绝非预期的结果,从而减少debug的时间和精力,提高编码总体效率。

总结

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

3月26日14:17

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

对AS语言的语法一开始很懵逼,边学边用,最后才安稳落地。

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

结对过程

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

3月26日14:30

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

过程:

  1. 详细阅读新增规则,发现新增不可达检测,在源代码基础上写个功能函数即可。
  2. 想兼容之前的测试报错:不能传入null。解决后,为了兼容,之前的某些测试断定结果需要更改为不可达(-1)。
  3. 补充了有障碍测试和不可达测试后,还是没通过最终测试,思考发现是测试写得不好,只测试了单步情况,未考虑全局,比如T1的优先级决策会导致走进死路,需要路径规划。
  4. 最后改用BFS算法完成了此任务。

代码可复用性与需求变更

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

在函数开头增加了可达性预测,然后复用了根据食物位置进行的优先级决策,由于增加了障碍物位置参数,修改了判断方向可行性的函数,最后复用了安全方向的备用决策。但是发现有个地方是错误的,就是判断方向可行性的函数使用了T1的贪心策略,本题需要使用BFS算法。

→ 📖 Q2.4(I) 请说明在编码实现时,可以采取哪些设计思想、考虑哪些设计冗余,来提高既存代码适应需求变更的能力。

设计思想:

  • 模块化:将独立功能拆分为独立函数,比如本题需要用BFS算法计算合理的下一步,那搜索时会遇到三种阻碍:边界、身体、障碍物,判断三者的碰撞可以独立为三个函数。
  • 兼容性:由于T2比T1多了障碍物参数,但为了复用T1的测试,可以将函数中障碍物参数的输入写成 barriers: Int32Array | null = null。

设计冗余:

  • 备用决策:就是保留T1的安全方向备用决策,虽然本题实际不需要,当计算出不可达时就算通过测试,但实际上,但计算此果子不可达时,蛇也要做出决策,此时计算出安全方向是有必要的,比如动态障碍物情况时,可能下一回合果子就可达了。

头脑风暴环节

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

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

​ 在多食物场景中,可以将问题转化为旅行商问题(TSP)的变种,通过计算蛇头和各食物之间的最短路径来规划最优的进食顺序。首先,使用BFS建立所有食物点之间的最短路径网络,考虑蛇身和障碍物的阻挡。对于少量食物,可以采用动态规划精确求解最优访问顺序。每次吃到食物后动态更新剩余路径,确保高效性和适应性。

总结

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

3月26日17:18

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

先想清楚再编码!当时可能头晕了,以为很简单,然后就走弯路了。

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

结对过程

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

3月27日20:00

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

过程:

  1. 基于最小可用原则,写一个不会碰撞边界、自己和当前敌人的贪心蛇。然后自我对战,发现很容易在争抢同一个果子同归于尽。
  2. 于是考虑一个防止和其他蛇碰撞的避险蛇,将每个蛇的三个方向都设置为威胁区域,并使用A*启发式算法,穷举自己的四个方向,计算每个方向的得分,取得分最高的方向为下一步的方向。(发现计算不对,于是针对计算威胁的函数写了个测试。)具体而言,先选择一个自己比别人更快吃到的目标果子,设置与目标果子越近得分越高,撞到边界、自己或别人的威胁区域会扣10000分。然后和贪心蛇对战,发现1v1情况下贪心蛇得分更高,因为避险蛇变相保护了贪心蛇。在4蛇模式中,得分情况居然挺复杂的。1条避险蛇和3条贪心蛇时,避险蛇总得分最高,而对角线的贪心蛇比避险蛇差一点,其他两个贪心蛇就差多些。1和2为避险蛇、3和4为贪心蛇时,两个避险蛇比2个贪心蛇高一些,而1和3为避险蛇、2和4为贪心蛇时(即对角的蛇相同),两个贪心蛇非常容易相撞,比前面的情况低很多分。3条避险蛇和1条贪心蛇时,贪心蛇存活率高些,而与贪心蛇对角的避险蛇死亡率比其他避险蛇高,得分也低一些。
  3. 由于1v1避险蛇比贪心蛇弱,考虑针对贪心蛇的攻击蛇。详细思考后,未来两步的必杀走法人类可以轻易看出来,但不知道如何转换成代码,遂放弃,考虑加强避险蛇。避险方面,加入其他策略,比如计算下一步与自己尾部的最短路径,超过12格说明此方向可能危险,扣1000分。贪心方面,在1v1中,如果分数高于对方,则敢于和对方争抢果子,即碰撞惩罚少扣2500分。最后测试与贪心蛇的1v1中,胜率高了一些。

需求建模和算法设计

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

​ 在贪吃蛇的决策需求建模中,将其视为一个动态威胁环境下的路径规划问题,包含多个核心要素。首先是威胁建模。在这一部分,通过 buildThreat 函数构建威胁图,标记不同区域的危险种类。具体来说,敌方蛇头下一步可能的移动方向会被标记为2,敌方身体固定部分标记为1,而己方蛇身体除尾部外的部分被标记为3。威胁不同,相应的惩罚分数不同。

​ 在目标选择上,我们使用曼哈顿距离和BFS路径规划算法,筛选满足条件的果子。主要的选择标准是:选择距离己方蛇头更近的果子,同时确保敌方蛇头距离该果子更远。如果敌我距离相同,我们将通过比分来判断优先级。此外,我们优先选择靠近棋盘中心的果子,因为这样可以减少边缘碰撞的风险。

​ 路径安全评估则通过BFS计算蛇头到目标的最短路径,并避开所有威胁区域。在此过程中,还会评估移动后的安全空间(即通过 calSafeSpace 函数确保有足够的逃生路径)。同时,必须检查移动后的状态,确保蛇头可以回到尾部位置(通过 tailFlag 标志),以避免被困死在某个死角。

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

​ 首先通过威胁种类来对不同区域的危险程度进行评估。具体来说,敌方身体固定部分的威胁最高,扣除10000分;敌方蛇头下一步可能的位置次之,扣除4500分。此外,我们采用动态碰撞惩罚策略。在1v1模式下,如果己方分数领先,我们会降低碰撞惩罚,鼓励与对手争夺果子;反之则会增加碰撞惩罚,以采取保守避让的策略。另外,如果移动方向导致进入棋盘的角落,我们还会额外扣分,以避免过于冒险的行为。

​ 在贪心策略方面,目标优先级的选择基于敌我曼哈顿距离的比较,优先选择敌方难以接近的果子。路径评分则考虑了距离目标的远近以及安全空间的数量,距离目标越近得分越高,同时安全空间越大也能获得额外加分。这一策略旨在帮助蛇更有效地避开危险区域,同时接近目标。

​ 避险策略中,特别关注尾部的可达性。如果移动后,蛇头到尾部的最短路径超过12步,则认为存在被困的风险,因此会扣分。为了保证灵活性,在5x5小棋盘的情况下,若尾部不可达且安全空间较小,优先选择逃生方向。

​ 在实现细节上,我们使用BFS缓存来快速计算路径距离,从而避免重复搜索。通过位压缩技术存储食物的历史状态(foodHistory),使得判断果子是否被吃变得更加高效。此外,我们还对数组访问进行了边界检查和预计算(如unchecked操作),从而优化性能,提升系统的响应速度。

软件度量

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

​ 首先进行对抗性测试,目的是验证不同算法在实际对抗中的表现。在基准对比方面,我们将与纯贪心算法进行对比,进行1v1对战和4蛇混战,统计其胜率以及平均得分。通过这种方式,可以直观地评估算法在实际游戏中的竞争力。

​ 在场景覆盖上,我们将在不同棋盘大小(如5x5和8x8)以及不同初始位置下运行1000局游戏,计算胜率的方差。这能帮助我们评估算法在各种环境下的表现稳定性和适应性,确保其在不同情况下都能维持较高的胜率。

​ 为了更加全面地评估算法的效果,我们还关注几个关键指标。生存时间是指蛇在游戏中的平均存活回合数,得分效率则表示单位回合内吃到的果子数量。

​ 在极端情况测试中,我们会验证算法在特定情况下的表现。例如,若蛇身已经环绕,是否能够成功找到逃生路径,从而避免被困死。同时,在食物争夺的场景下,若敌我距离相同,我们会检查算法是否能够根据比分正确地调整策略,优先选择对己方更有利的果子。

​ 在定量分析方面,我们使用脚本统计不同策略组合下的得分分布。在4蛇模式下,每局比赛结束后将根据排名将其转换为得分(第1名得3分,第2名得2分,依此类推),然后计算每种策略的总分占比。

总结

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

4月6日16:50(注:实际分成三段时间:3月27日20:00到21:00、3月27日21:30到23:00、4月6日13:20到16:50)

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

​ 通过这次任务,我对贪吃蛇的决策算法和路径规划有了更深刻的理解。最开始的阶段,我通过简单的贪心算法进行初步尝试,但很快发现当多个蛇争抢同一个果子时,贪心算法很容易导致互相碰撞,因此需要进一步加入避险和路径规划的策略。最终通过结合A*算法和BFS路径规划,使得避险蛇能够有效规避威胁区域,同时选择更安全的路径前进,这让我体会到合理的算法设计对于避免死角和获取更多果子的关键作用。

​ 在整个编码过程中,尤其是在面对复杂的决策树和路径选择时,我深刻认识到如何平衡算法的效率与复杂度。通过不断调试和优化,我逐渐克服了几个瓶颈,比如如何精准计算威胁区域、如何结合曼哈顿距离判断目标优先级等问题。同时,测试覆盖也让我意识到不同的棋盘大小和初始位置可能带来完全不同的策略表现,因此我开始注重设计更全面的测试用例,确保算法在各种场景下都能保持稳定性。

​ 另外,在团队协作过程中,我们及时调整了角色分配和工作节奏,这让我认识到,灵活的团队合作和合理的时间管理能够显著提高工作效率。例如,定期的角色轮换帮助我们避免了因长时间单一任务而导致的疲劳,提高了代码编写的质量和速度。

结对项目总结

结对过程回顾和反思

→ 📖 Q4.1(P) 提供两人在讨论的结对图像资料。

→ 📖 Q4.2(P) 回顾结对的过程,反思有哪些可以提升和改进的地方。

​ 回顾结对的过程,我们发现了几个可以提升和改进的地方。首先,在需求理解方面,初期由于我们对“威胁区域动态更新”规则的理解存在偏差,导致避险算法出现了漏洞。这一问题主要是在设计阶段没有充分讨论清楚边界条件。因此,未来在设计初期,我们应该通过伪代码或流程图来明确和理清这些规则,确保对需求有一致的理解。

​ 其次,测试覆盖方面存在不足。我们没有针对8x8棋盘的边缘碰撞场景设计专项测试用例,结果在实际运行中发现蛇在棋盘角落频繁自杀,暴露出算法对角落的处理不够完善。为了避免类似问题的发生,后续我们需要建立更全面的测试用例,设计出棋盘大小和初始位置的组合测试矩阵,以确保各种情况都能得到充分验证。

​ 最后,关于角色切换的问题,长时间固定“驾驶员”和“领航员”的角色导致了工作效率下降,尤其在疲劳的情况下,进展较慢。为了解决这一问题,我们在中期做出了每30分钟轮换一次角色的调整,这样的改变显著提升了效率。因此,在未来的结对工作中,我们会更加注重角色的合理轮换,以保持工作的高效性和人员的精力充沛。

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

​ 在这次结对编程的过程中,我的搭档表现得非常出色。在项目中,我们互相配合,合作得很顺利。首先,搭档非常注重细节。在设计和实现过程中,他总是会仔细考虑到每个环节,确保没有遗漏,并且在代码审查时能够发现潜在的问题,及时提出解决方案。其次,搭档的沟通能力很强。无论是在讨论设计思路时,还是在遇到问题需要集思广益时,他都能够清晰、有效地表达自己的观点,同时也非常善于倾听并采纳合理的建议。这使得我们能高效地共同推进任务。此外,搭档对技术的掌握也非常扎实。在解决遇到的技术难题时,他能够快速分析并提供有效的解决方案,避免了很多不必要的时间浪费。

​ 不过,搭档有时会有些过于追求完美,尤其在设计阶段,可能会花费较长时间讨论和完善每个细节。这虽然有助于提升质量,但有时也会拖延进度,需要在效率和质量之间找到一个平衡点。

对结对编程的理解

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

​ 结对编程是一种两人合作的编程方式,通常分为“驾驶员”和“领航员”两个角色。驾驶员负责实际编写代码,而领航员则主要负责思考和提出方向性的建议。这种方式强调两个人的互动和合作,通过不断的讨论和交流来完成任务。

​ 结对编程有不少优点。首先,它能显著提升代码质量,因为两个人会实时审查彼此的工作,减少错误的发生。通过这种即时反馈,代码设计和实现会更加精细,问题也能得到更快速的解决。其次,这种方式促进了知识共享,尤其是在经验较丰富的开发者与较新手的合作中,后者能通过这种互动快速成长,提升整体团队的技术水平。此外,结对编程能够提高效率,虽然看似需要两个人共同编写代码,但通过协作,减少了调试和修复错误的时间。在我参与的项目中,我们通过角色轮换,成功避免了因疲劳带来的效率下降,反而提升了工作效率。

​ 然而,结对编程也存在一些缺点。首先,它需要两个人长期保持高强度的集中注意力,这可能会导致一定的疲劳,尤其是如果长时间没有角色轮换的话。此外,结对编程的资源消耗也比较大,尤其是在任务简单时,两个开发者共同处理可能会显得有些不划算。最后,结对编程要求两位开发者之间有良好的沟通和配合,如果性格不合或者沟通不畅,可能会影响整体的协作效率。

代码实现提交

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

https://github.com/YePeiLin/BUAASE2025-PairProgramming

posted @ 2025-04-06 21:38  捍卫银河中的美  阅读(19)  评论(1)    收藏  举报