[P]结对项目:影蛇舞

结对项目:博客问题清单

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

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

引入

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

2025/3/25 14:45。

调查

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

I. 没有听说过;

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

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

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

I,之前完全没有听说过。

总结

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

2025/3/25 16:18,阅读完guide,并一步步安装好rustc、rustup、cargo、wasm-pack等等工具链,完成仓库中模板rust文件的构建。

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

结对过程

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

2025/3/25 17:00。

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

了解Rust基本语法,阅读指导书相关需求,双方探讨是否对题目要求存在歧义(通过excel等工具模拟贪吃蛇一次移动,确认我们需要做的是给出较优的移动方向),达成编程共识,讨论具体实现方式,查询资料,了解贪吃蛇碰撞检测(主要是与自身身体碰撞检测)规则,随后对Rust函数设计与循环相关语法进行了解,开始正式结对编程流程。

在我们编写greedy_snake_move这一核心函数时,先遇到的问题是,在防超界、防碰撞后找到可行移动策略后,如何寻找最优移动策略的。经过共同商讨,我们决定以移动策略是否能使小蛇靠近食物,作为判定最优策略的依据。

构建rust项目过程中,我们遇到了语法错误:bool类型和i32类型无法直接相加,我们通过i32::from()方式解决。

自行测试和提交测试过程中,我们发现自己的函数存在逻辑问题,即当小蛇受限制无法靠近食物时,会因为不存在”最优解“而错误输出,我们采用default默认值的方法,先找到一个可行解保底,再去探寻最优解。最后顺利通过了自行测试和提交测试。

测试

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

设计测试,主要考虑边界问题和自身碰撞情况,在编写测试样例时,设计了头坐标位于方格四个顶角之一的位置,测试是否会出现超界现象,此外还设计目标果子位于头部不同方位(左上,左下,右上,右下),测试是否能做出正确的决断,在上述测试的基础上,通过改变初始身体位置坐标,测试若向预期方向移动会自身碰撞,是否能正确避开。
对于如何评估测试的有效性,我们是这样认为的,若测试程序可以覆盖全部代码分支,且样例运行结果合理,在移动方案合理的基础上,这样的测试设计是较为有效的。
比如在lib.rs的测试模块中,我们编造了五组数据,分别为正常情况、测试超界情况、测试首身碰撞情况、环形情况能否找到最优策略、环形情况能否避免首身碰撞。其中,环形的首尾衔接情况是比较特殊的情形,我们特意测试了这种特殊情况下能否找到移动的可行策略和最优策略。

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

单元测试能够保证软件的每一个函数/模块运行正确。比如在我们这次小的函数设计中,通过单元测试(断言),我们能确保该函数的在测试输入样例下的输出正确,为之后的章节更复杂的功能、更宏大的模块正确性提供了保障。单元测试也有助于我们精准定位错误发生的位置、及时修改。

总结

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

2025-03-25-20:19
(项目在18:35-19:50期间暂停)

”实际耗时“栏目见上。

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

在第一次结对编程过程中,我们双方互相讨论、形成了一个更好的逻辑,但我也发现双方思路不一致可能带来的困境。积极沟通、接纳别人不同的思路,能有助于我们提高结对效率,也能补足自身的逻辑、编程欠缺。

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

结对过程

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

2025-03-29-9:50

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

2.首先,结对搭档阅读指导书,通过模拟游戏熟悉本次任务可能需要解决的问题,确保理解上不存在差异,随后认为了解迷宫问题算法对本次作业有帮助,所以对该算法进行了回顾,并且讨论该算法应用到本次任务中需要注意哪些问题、做哪些调整(例如起终点不是固定的,可能存在不可达情况等),在做完上述准备工作后,开始搭建算法框架,尝试实现。
开发过程中出现的主要问题是数据类型使用错误,特别是i32usize的使用场景,出现报错,通过查询网络资料,我们得知wasm_bindgen不能直接处理固定大小的二维数组等限制,修改了相关代码,解决了问题。
其次,我们发现在考虑可行路径时,忽视了身体对于蛇的阻挡作用,于是对相关部分进行修改,我们认为,在合理移动的情况下,蛇头不能向第二节身体的方向移动,所以对移动方向进一步限制,解决了该问题。

代码可复用性与需求变更

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

针对该任务,T1任务代码的可复用性并不高,在T1任务中,需要给出可移动的方向,我们主要是通过检测每个移动方向是否出现碰撞,是从排除非法的各种情况实现,而在该任务中,我们尝试找出一条可行的路径验证是否“可达”,我们是从考虑合法的情况入手,如果符合要求,才进行下一步移动。

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

可以采用模块化设计的思想,比如T2编程中我们把bfs寻找路径的功能,从greedy_snake_move_barriers函数中拆解出来,单独封装成bfs_find_path函数,这样代码可以更灵活地适应需求变更和迭代。

我们还采用了可配置参数,比如文件开头定义的const N: usize = 8; const DIRECTIONS: [(i32, i32, i32); 4] = [(0, 1, 0), (0, -1, 2), (-1, 0, 1), (1, 0, 3)];,如果迷宫大小和行进方向有改变,只需要改变此常量参数即可。

我们实现的设计冗余是在单元测试中,设置food_num参数,匹配可能未来会有多个果子规则,也能更好地测试我们当前的代码。以及,不管是问题解决函数中、还是测试函数中,我们的错误处理机制是彼此独立的,不同的错误用不同的if语句判断,并返回相应的错误参数编码(-1、-2等等),如果未来加入新的规则,我们可以快速修改而不影响原规则判定。

头脑风暴环节

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

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

对于多个果子的问题,bfs依旧可以找到可行路径,但需要改变:

  • 吃到果子时不能立即返回,而是需要等所有果子都吃完后再返回。

  • visit数组维数需要增加,原本是相同位置的格子只能到达一次,现在应改成相同位置+相同果子状态的位置只能到达一次,即需要新增一维表示已经吃掉的果子集合。同时,bfs的队列也需要增加维数,原本的(x, y, first_move, snake_body)需要增加已经吃掉的果子集合。

总结

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

2025-04-01-10:40
(项目的编程阶段在2025-03-29-9:50到12:18,项目的测试阶段在2025-04-01-10:00到10:40)

补充:2025-04-01-19:52,发现一个小bug在之前的测试中未测到,大概花了10分钟修复。今天是愚人节qaq程序大人不要跟我开玩笑了。

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

在本次结对任务中,我进一步认识到了结对的优势。一开始面对这个问题,我提出用dfs搜索蛇的可行路径,但队友觉得bfs能更简洁、更直接地解决该问题,进行深入探讨后,我们达成一致:用bfs算法。最终结果也证明队友的思路是正确的。结对能让我接触到不同的编程思想,更高效地形成解决问题的思路。

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

结对过程

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

2025/4/5 10:40

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

2.首先一起阅读了指导书关于Chapter3的内容,对于存活策略,我们先讨论了是得分重要还是活得久重要,形成了一个根据场上剩余蛇的数量调整策略的思想,但我们发现仅靠蛇的数目难以评估场上状况且最终需要以分数作为获胜依据,所以该策略的可使用性并不高,后续我们根据可选的方向数量有限且较少,认为可以给每个方向进行赋分(例如存在碰撞障碍物减100分,靠近果子则加分等),最终选取得分最高的方向进行返回,确定使用该方案后我们进行了较为详细的赋分讨论,得出了初步的较为完善的方案,开始进行代码的编写。开发过程中遇到的主要过程是对于输入参数的格式没有特别清楚,导致对数据的处理出现问题,产生报错,但通过查找相关说明,修改成了合理的方式。对于具体参数的确定上我们存在一些纠结,采取了不同参数的蛇进行对弈,选取了在30轮左右的比赛中表现较好的。

需求建模和算法设计

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

对于蛇蛇大作战这一问题,我们首先明确了各实体及其行为。比如蛇的属性包括坐标、存活状态,其行为是移动决策。果子的属性是坐标,其行为是被吃掉后每回合重置。场地的属性是大小和边界。接着,我们建模了游戏规则,包括碰撞规则(边界碰撞、自身碰撞、其他蛇碰撞),得分规则(吃果子),决策规则(上下左右移动方向)。最后,我们把实体的属性转换为编程中具体的状态,并用合适的数据结构存储,行为则会导致状态的转移更新。自此,我们建模完成,并在该模型基础上思考我们的算法。

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

我们对蛇头可能行进的四个方向进行打分,最终选取了得分最高的方向作为我们选取的方向,具体来说:
对于踏入边界的方向-100=>避免死亡
对于会和自身/其他蛇碰撞的方向-100=>避免死亡
对于其他蛇可能行进的方向,我们根据其他蛇可选择的方向数(排除掉一定发生碰撞的方向后剩余的方向总数)进行适当减分,例如,如果该方向是其他蛇唯一可选的行进方向,则该方向-100,若其他蛇有更多可选择的行进方向,则减掉的分数会适当减小=>避免死亡
如果移动后两条蛇蛇头的距离过近,进行适当减分,避免后续移动可能发生的碰撞=>避免死亡
如果往该方向走会靠近某个果子,我们以果子为单位进行加分=>吃到更多果子
如果该方向附近有很近的果子,对该方向根据距离远近进行加分,防止出现抛弃了近处的少数果子,而往远处较多果子的方向移动=>吃到更多果子

编程实现:对于四个方向,计算朝该方向移动后新蛇头的位置,初始化分数为0分,随后通过简单的if函数检测是否发生绝对碰撞,加减分数,对于是否靠近果子,我们是通过比较移动前后相对于果子的距离实现的。

软件度量

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

首先比较直观的衡量方式是胜率、平均得分、存活率。我们通过和别的组的蛇蛇进行1v1或4蛇大乱斗,观察我们组的胜率(获胜次数/总对弈次数)、平均得分(总得分/总对弈次数)、存活率(存货次数/总对弈次数),以此为依据考察模块的对弈能力,修改我们的赋分数值,在吃到果子和存活下来这两个目标中找到更合适的临界点数值。
其次我们也进行了鲁棒性测试,在不同的初始条件和随机种子下,测试我们的模块性能是否稳定。具体也是体现在胜率、平均得分、存活率等上是否有较大变化,定量的可以通过标准差和方差来衡量。
最后,我们考虑到决策时间也是对弈能力较为重要的一环,因此计算了每回合平均决策时间(总决策时间/总回合数),较短的决策时间表明模块效率较高,能够在短时间内做出合理的决策。

总结

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

2025/4/5 22:15
具体说明:我们结对时间分为三段,2025/4/5 10:40-12:50,2025/4/5 15:35-17:40,2025/4/5 8:45-22:15

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

在这个问题中,蛇蛇获胜的主要两个目标是:吃到更多果子和存活下来。在做决策时这两个目标可能会产生冲突,那么如何权衡就是提高程序性能的关键。我和队友仔细商讨,最后决定采用打分制来给每个决策(上下左右移动)打分,通过调整参数权重来改变吃到果子和存活下来这两个目标对决策的影响大小。并通过不断测试(自我测试、和别的组的蛇蛇测试)找到最优数值。

在这个过程中,我充分认识到结对编程的优势:两个人深入讨论、优势互补。尤其是在面对这类较为复杂的问题时,讨论能让我们更全面地思考问题,做出更优质的决策。

结对项目总结

结对过程回顾和反思

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

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

在结对过程中,我们认为在代码实现前先形成统一清晰的思路是很重要的。在Chapter2中我们没有完全想清楚算法思路,就匆忙开始编程,导致后面测试环节频繁出现逻辑上的问题,大大降低了结对效率。因此我们认识到先讨论,形成优质的、清晰的思路,再编程会事半功倍,这也是结对编程的优势所在。

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

优点:考虑问题特别全面,经常会提出我未曾设想过的细节问题,很好地帮我规避了编程中可能会踩的“坑”;非常沉稳,由于我是那种咋咋呼呼、拿到问题稍加思索就想开始编程的人,我的搭子会在这个时候拦住我,我们先经过深入讨论,理清编程思路后再上手写代码;很幽默很有趣,我们在生活中也成为了很好的朋友(原来是完全不认识的O.O)。

缺点:我们结对的时候经常忘我地沉浸在代码的世界里,而错过了饭点。我亲爱的搭子,要好好爱惜身体,多注意休息!

对结对编程的理解

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

优点:

  • 两个人深入讨论、优势互补。尤其是在面对较为复杂的问题时,讨论能让我们更全面地思考问题,做出更优质的决策。多角度地思考往往能够让我们更快地找到问题的根源,同时避免我们陷入“思维定势”而陷入僵局。
  • 我们结对时,一般是一个人编写代码,另一个人在旁边监督,审查语法是否有问题、逻辑是否正确、代码风格是否规范等,这大大提升了我们的代码质量和可读性。
  • 遇到bug和难题时,两个人能互相鼓励支持,不会因为逃避问题而拖延时间,提高了编程效率。

缺点:

  • 一开始由于我们彼此不太熟悉,沟通起来较费时。因为“脑回路”不在同一条线上,我们一开始对对方的想法思路不太理解,前期耗费了很多时间沟通。

总的来说我觉得结对编程是利大于弊的,它不是简单地让两个人一起写代码,而是一种有组织的、需要良好沟通和协调的开发方式。它结合两个人的智慧和技能,优势互补,能大大提高软件开发的质量和效率,但也需要我们发挥沟通能力和团队精神,采取正确的方式结对。

结对编程也是我动态学习过程,在这次结对里,我从对方身上学习到了很多新的知识和技能,也不断调整自己的思维方式和编程习惯。

软件开发中会遇到各种各样的问题,结对编程提供了一种合作的手段来应对这些复杂的情况,是今后软件开发过程中我可以考虑的、行之有效的合作模式。

代码实现提交

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

仓库链接

附录

附录A:基于 PSP 2.1 修改的 PSP 表格

Personal Software Process Stages 个人软件开发流程 预估耗时(分钟) 实际耗时(分钟)
PLANNING 计划
- Estimate - 估计这个任务需要多少时间
DEVELOPMENT 开发
- Analysis & Design Spec - 需求分析 & 生成设计规格(确定要实现什么)
- Technical Background - 了解技术背景(包括学习新技术)
- Coding Standard - 代码规范
- Design - 具体设计(确定怎么实现)
- Coding - 具体编码
- Code Review - 代码复审
- Test Design - 测试设计(确定怎么测,比如要测试哪些情景、设计哪些种类的测试用例)
- Test Implement - 测试实现(设计/生成具体的测试用例、编码实现测试)
REPORTING 报告
- Quality Report - 质量报告(评估设计、实现、测试的有效性)
- Size Measurement - 计算工作量
- Postmortem & Process Improvement Plan - 事后总结和过程改进计划(总结过程中的问题和改进点)
TOTAL 合计
posted @ 2025-04-06 10:54  六拾一61  阅读(24)  评论(0)    收藏  举报