[P]结对项目:影舞蛇
结对项目:博客问题清单
请将本文件在代码仓库外复制一份,一边阅读和完成结对项目、一边填写入代码仓库外的版本,或采取简记、语音备忘等方式记载较复杂问题的要点之后再补充。请不要将本文档内的作答提交到代码仓库。
Chapter.0 Belua multorum es capitums.(你是多首的怪物。)
引入
→ 📖 Q0.1(P) 请记录下目前的时间。
2025-3-25 20:08
调查
→ 📖 Q0.2(I) 作为本项目的调查:请如实标注在开始项目之前对 Wasm 的熟悉程度分级,可以的话请细化具体的情况。
I. 没有听说过;
II. 仅限于听说过相关名词;
III. 听说过,且有一定了解;
IV. 听说过,且使用 Wasm 实际进行过开发(即便是玩具项目的开发)。
II,只大致了解过似乎是一种中间代码
总结
→ 📖 Q0.3(P) 请记录下目前的时间。
2025-3-25 20:25
Chapter.1 不畏迷茫,只管前进。(迷子でもいい、前へ進め。)
结对过程
→ 📖 Q1.1(P) 请记录下目前的时间。
2025-3-26 13:30
→ 📖 Q1.2(P) 请在完成任务的同时记录,并在完成任务后整理完善:
- 浏览任务要求,参照 附录A:基于 PSP 2.1 修改的 PSP 表格,估计任务预计耗时;
| Personal Software Process Stages | 个人软件开发流程 | 预估耗时(分钟) | 实际耗时(分钟) |
|---|---|---|---|
| PLANNING | 计划 | ||
| - Estimate | - 估计这个任务需要多少时间 | 5 | 10 |
| DEVELOPMENT | 开发 | ||
| - Analysis & Design Spec | - 需求分析 & 生成设计规格(确定要实现什么) | 5 | 5 |
| - Technical Background | - 了解技术背景(包括学习新技术) | 10 | 15 |
| - Coding Standard | - 代码规范 | 5 | 5 |
| - Design | - 具体设计(确定怎么实现) | 5 | 8 |
| - Coding | - 具体编码 | 10 | 14 |
| - Code Review | - 代码复审 | 10 | 6 |
| - Test Design | - 测试设计(确定怎么测,比如要测试哪些情景、设计哪些种类的测试用例) | 15 | 25 |
| - Test Implement | - 测试实现(设计/生成具体的测试用例、编码实现测试) | 20 | 28 |
| REPORTING | 报告 | ||
| - Quality Report | - 质量报告(评估设计、实现、测试的有效性) | 10 | 8 |
| - Size Measurement | - 计算工作量 | 5 | 5 |
| - Postmortem & Process Improvement Plan | - 事后总结和过程改进计划(总结过程中的问题和改进点) | 10 | 8 |
| TOTAL | 合计 | 110 | 137 |
- 完成编程任务期间,依次做了什么(比如查阅了什么资料,随后如何进行了开发,遇到了什么问题,又通过什么方式解决);
- 查阅资料:第一部分已经查阅了背景资料,这一部分主要集中在代码相关语法的查找上
- 开发过程:根据指导书内容构建方法,再引入必要属性,最后实现具体函数过程
- 问题:第一章逻辑上比较简单,大多为对assemblyScript不了解导致的语法细节方面出错,解决时需要一个一个上网查找资料
测试
→ 📖 Q1.3(P) 请说明针对该任务,你们设计和实现测试的方法及过程,包括但不限于:出于对需求的哪些考虑设计了哪些测试用例、如何评估所设计测试的有效性 等等。
-
测试方法:不断循环主函数,每次循环过后进行判断,因为本次作业事实上没有撞墙或者撞自身的可能,因而出现这两种情况时直接报错,如果吃到果子则直接判断正确并退出循环,最后将轮次加一并进入下一次循环。
-
测试用例:考虑以下几种情况
- 能一步吃到果子
- 身体为正方形,需要向左绕开自己并吃到果子,比如snake为[3, 1, 3, 2, 2, 2, 2, 1],果子为(1,1)
- 身体为正方形,需要向右绕开自己并吃到果子,比如snake为[1, 1, 1, 2, 2, 2, 2, 1],果子为(8,8)
- 身体为一条直线
- 身体为L型
对于果子
- 果子在顶点
- 果子在中央
因而在构造时枚举每种情况即可
-
评估有效性:在测试时列出每一步行动的轨迹,后续检查是否出现问题
→ 📖 Q1.4(I) 请说明单元测试对软件开发的作用。
提前发现bug,提高当前模块可靠性:开发过程中,及早发现错误,减少后续调试成本,同时预防代码改动时引入新的 Bug,可以确保每个模块都是稳定的,这样在后续测试比如回归测试时,能确保新代码不会破坏旧功能。
总结
→ 📖 Q1.5(P) 请记录下目前的时间,并根据实际情况填写 附录A:基于 PSP 2.1 修改的 PSP 表格 的“实际耗时”栏目。
2025-3-26 15:55
→ 📖 Q1.6(I) 请写下本部分的心得体会。
花的大部分时间都用在了代码的编写和测试上,后续的改动也比较多。之后的编程应该在动手之前进一步沟通规划,防止编写时经常出现意见相背而重构次数也过多。
Chapter.2 即使迷茫,也要前行。(迷子でもいい、迷子でも進め。)
结对过程
→ 📖 Q2.1(P) 请记录下目前的时间。
2025-3-27 18:00
→ 📖 Q2.2(P) 请在完成任务的同时记录,并在完成任务后整理完善:
- 浏览任务要求,参照 附录A:基于 PSP 2.1 修改的 PSP 表格,估计任务预计耗时;
| Personal Software Process Stages | 个人软件开发流程 | 预估耗时(分钟) | 实际耗时(分钟) |
|---|---|---|---|
| PLANNING | 计划 | ||
| - Estimate | - 估计这个任务需要多少时间 | 10 | 20 |
| DEVELOPMENT | 开发 | ||
| - Analysis & Design Spec | - 需求分析 & 生成设计规格(确定要实现什么) | 5 | 8 |
| - Technical Background | - 了解技术背景(包括学习新技术) | 5 | 5 |
| - Coding Standard | - 代码规范 | 5 | 3 |
| - Design | - 具体设计(确定怎么实现) | 20 | 36 |
| - Coding | - 具体编码 | 60 | 85 |
| - Code Review | - 代码复审 | 30 | 25 |
| - Test Design | - 测试设计(确定怎么测,比如要测试哪些情景、设计哪些种类的测试用例) | 15 | 20 |
| - Test Implement | - 测试实现(设计/生成具体的测试用例、编码实现测试) | 30 | 35 |
| REPORTING | 报告 | ||
| - Quality Report | - 质量报告(评估设计、实现、测试的有效性) | 20 | 20 |
| - Size Measurement | - 计算工作量 | 10 | 8 |
| - Postmortem & Process Improvement Plan | - 事后总结和过程改进计划(总结过程中的问题和改进点) | 15 | 24 |
| TOTAL | 合计 | 225 | 289 |
- 完成编程任务期间,依次做了什么(比如查阅了什么资料,随后如何进行了开发,遇到了什么问题,又通过什么方式解决);
这次作业主要集中在算法层面,因此查阅了很多有关路径寻找算法的资料。
在开发过程中出现库函数不存在的情况,原因是assemblyScript有些语法和javaScript不一样,选择通过官网文档一一比对并修改部分函数的实现方式。
代码可复用性与需求变更
→ 📖 Q2.3(P) 请说明针对该任务,你们对 🧑💻 T1 中已实现的代码进行了哪些复用和修改。
由于此次需要提前规划路径以判断是否可达,所以基本框架有大幅变动。
但是部分判断逻辑大致可以沿用,主要在障碍判断方面
function is_safe(x: i32, y: i32, snake: Int32Array): bool {
if (x < 1 || x > 8 || y < 1 || y > 8) return false; // 碰墙
for (let i = 0; i < 6; i += 2) {
if (snake[i] == x && snake[i + 1] == y) return false; // 撞自己
}
//新增碰障碍
return true;
}
新增了对障碍物的判断,将蛇身和障碍物视为同一类,实质就是蛇头在运动,需要避开所有的障碍(身体,障碍物,墙壁)
→ 📖 Q2.4(I) 请说明在编码实现时,可以采取哪些设计思想、考虑哪些设计冗余,来提高既存代码适应需求变更的能力。
设计思想如下:
- 模块化设计:将不同功能拆分成独立的模块,例如此部分中路径搜索、蛇的运动逻辑判断、路径构建等待模块,这样的区分可以在修改某一部分功能时,不影响其他部分,提高代码的可维护性。
- 面向对象设计:用类和对象封装数据和行为,例如此部分在路径算法计算代价时,可以将每个节点封装成Node类快速以快速获得位置以及g,h值,通过继承和多态减少代码重复,使得代码更容易扩展。
- 单一职责原则:确保每个类或函数只负责一个方面的功能,例如 此部分中
Snake负责移动,reconstructPath只负责根据已有节点构建路径,需求变更时,只需要修改相关部分,而不会影响整个系统。
设计冗余:
- 预留扩展点:例如在
greedy_snake_move_barriers()里,可以支持未来新增不同寻路方法,只需将有关算法替换即可。 - 增加日志和调试信息:在游戏运行过程中记录调试信息,例如蛇的当前状态、 路径计算过程等,方便未来优化或修复 bug
头脑风暴环节
**→ 📖 Q2.5(P) **只吃一个食物可满足不了贪吃蛇的欲望,请一起思考并简述以下场景中贪吃蛇的策略:
在 🧑💻 T2 的基础上,场地里不再是只有 1 个果子,而是总共有 n 个果子 (1 < n < 10 ),果子随机分布在场地中且不会刷新,保证不与障碍物重叠,保证每个果子均可达,且至少存在一条成功吃掉所有果子的路线,其余条件保持不变,请你找出一条吃完所有果子的行动路径。
构建一个函数,
首先统计每个果子的曼哈顿距离,从小到大排列
再按每个果子曼哈顿距离小的优先,对出发点和终点进行A*算法,分两种情况:
- 如果找不到路径,跳过此果子遍历后续果子
- 找到路径,以此果子为出发点重新调用函数,即使用回溯方法
一旦路径上的点数量达到n个,调用终止,返回路径
总结
→ 📖 Q2.6(P) 请记录下目前的时间,并根据实际情况填写 附录A:基于 PSP 2.1 修改的 PSP 表格 的“实际耗时”栏目。
2025-3-27 22:30
→ 📖 Q2.7(I) 请写下本部分的心得体会。
通过学习对有障碍情况下的路径查找方法有了更深刻的了解,也使我深刻意识到开发前除框架以外算法选择的重要性,这两者也应该是相辅相成的。
另外一点就是设计时需要时刻审视自己代码实现的合理性和可扩展性,而结对编程中搭档的存在恰恰能更好考虑到这一点,如一些方法和类的封装,使得代码能够适应更多的变化(如果子生成规则改变等)。这些适时的变动能让我能够利用 参数化 和 模块化设计 来增强框架的适应能力。
Chapter.3 这就是我的前进、到我出场了!!!!!(It's MyGO!!!!!)
结对过程
→ 📖 Q3.1(P) 请记录下目前的时间。
2025-3-28 14:00
→ 📖 Q3.2(P) 请在完成任务的同时记录,并在完成任务后整理完善:
- 浏览任务要求,参照 附录A:基于 PSP 2.1 修改的 PSP 表格,估计任务预计耗时;
| Personal Software Process Stages | 个人软件开发流程 | 预估耗时(分钟) | 实际耗时(分钟) |
|---|---|---|---|
| PLANNING | 计划 | ||
| - Estimate | - 估计这个任务需要多少时间 | 10 | 6 |
| DEVELOPMENT | 开发 | ||
| - Analysis & Design Spec | - 需求分析 & 生成设计规格(确定要实现什么) | 20 | 30 |
| - Technical Background | - 了解技术背景(包括学习新技术) | 20 | 15 |
| - Coding Standard | - 代码规范 | 10 | 10 |
| - Design | - 具体设计(确定怎么实现) | 30 | 25 |
| - Coding | - 具体编码 | 120 | 105 |
| - Code Review | - 代码复审 | 20 | 35 |
| - Test Design | - 测试设计(确定怎么测,比如要测试哪些情景、设计哪些种类的测试用例) | 15 | 35 |
| - Test Implement | - 测试实现(设计/生成具体的测试用例、编码实现测试) | 10 | 15 |
| REPORTING | 报告 | ||
| - Quality Report | - 质量报告(评估设计、实现、测试的有效性) | 20 | 15 |
| - Size Measurement | - 计算工作量 | 15 | 12 |
| - Postmortem & Process Improvement Plan | - 事后总结和过程改进计划(总结过程中的问题和改进点) | 10 | 8 |
| TOTAL | 合计 | 300 | 311 |
- 完成编程任务期间,依次做了什么(比如查阅了什么资料,随后如何进行了开发,遇到了什么问题,又通过什么方式解决);
在网络中大量搜索相关贪吃蛇竞争实例算法,在开发时对于一些细节算法或者实现方案的选择两个人有小分歧。
解决方法当然是大致实现以后根据实际情况调整,当然最重要的是多交流和沟通,能省不少麻烦🎉
需求建模和算法设计
→ 📖 Q3.3(P) 请说明你们如何建模这一需求。
数据建模
- 障碍
将所有能产生碰撞的点视为障碍,包括墙壁、其他蛇和自己的前三节身体,以及周围有三个不包括自己的其他障碍的格子(这个格子可以是果子,即吃完就会趋势的果子)
- 目标
对每个果子统计并暂时由其到达代价所取代,体现为到达需要的距离和吃其他果子需要的距离,将所有蛇对所有果子的代价放在一起对比以确认目标
- 状态
根据自身蛇的形状确定所处状态,便于下一步做出调整,主要为三种:
L字形:身体呈现L字弯折,根据弯折点、朝向、镜面折叠可以有多种情况。
Z字形:身体呈现z字弯折,与L字形类似。
正方形:头尾相接,是最安全的形状。
一字型:身体呈一条线
因而目标建模主要如下:
- 存活优先
全力避免装到障碍,优先保证自身存活。
- 果子尽量吃👋
在保证安全的基础上吃果子。
→ 📖 Q3.4(P) 请说明针对该任务,你们采取了哪些策略来优化决策。具体而言,怎么避免死亡?怎么吃到更多果子?如何编程实现。
对于避免死亡
- 龟龟战略:回合数不足或者果子难以吃到时进入正方形玄龟阵,也即快速进入立体防御。具体来说实现了一个防御函数,专门根据各状态转为正方形:
function defensiveMove(
n: i32,
snake: Int32Array,
snakeNum: i32,
otherSnakes: Int32Array
): i32 {
if (uniquex.size == 2 && uniquey.size == 2 && Math.abs(headx - tailx) + Math.abs(heady - taily) == 1) { //正方形
…………………… //维持正方形
} else if (uniquex.size >= 2 && uniquey.size >= 2) { //L型或z型
……………………
} else { //一字型
……………………
}
}
- 安全格优先:在与果子相冲突的情况下优先走安全格
对于吃到更多果子
- 边缘处理:考虑到传统算法控制的蛇在边界时比较危险(容易被别的AI蛇绞杀),因此在计算路径时给边界上的点赋予更高的代价,让蛇优先选择位于中间的格子作为路径
if (selfMove && (neighbor.x - 1 <= (width == 5 ? 1 : 2) || width - neighbor.x <= (width == 5 ? 1 : 2)
|| neighbor.y - 1 <= (width == 5 ? 1 : 2) || width - neighbor.y <= (width == 5 ? 1 : 2))) {
//min为相距边界最小值
g = current.g + 1 + 0.25 * Math.pow(2, (width == 5 ? 1 : 2) - min); // 更高选择代价
} else {
g = current.g + 1;
}
- 保证果子最先吃到:筛选能最早吃到的果子,尽量保证自身得分。
软件度量
→ 📖 Q3.5(P) 请说明你们如何量度所实现的程序模块的有效性,例如:“如何说明我们的程序模块对弈能力很强?”尝试提出一些可能的定量分析方式。
主要在多蛇对抗中体现,通过多轮测试,考虑以下方面:
-
平均得分:在多次对局中统计最终得分的平均值,较高的平均得分表明具备较强的生存和果子获取能力,较低则可能说明得分策略考虑不足等。
-
得分分布:观察不同对局中得分的方差,较低的方差表示策略稳定,较高的方差可能意味着策略偶尔会失败,可能说明在博弈过程中对生存考虑不足或得分策略存在缺陷。
-
多种类对局表项:观察在其他条件不变的同时,同一网格中随蛇数量增加时得分表现。这样的分析有助于考虑程序在一些极限情况的博弈能力。
总结
→ 📖 Q3.6(P) 请记录下目前的时间,并根据实际情况填写 附录A:基于 PSP 2.1 修改的 PSP 表格 的“实际耗时”栏目。
2025-4-1 20:00
→ 📖 Q3.7(I) 请写下本部分的心得体会。
用按部就班的路径搜索算法还是太低效了,可惜发现深度强化学习的思路时两人的主要框架已经打好了,迫不得已没法人工深度学习深度学习(悲)。总的来说这次作业让我们重新认识了路径搜索方面的有关算法和实现,不管怎么样也算重新巩固了基础吧(
结对项目总结
结对过程回顾和反思
→ 📖 Q4.1(P) 提供两人在讨论的结对图像资料。
→ 📖 Q4.2(P) 回顾结对的过程,反思有哪些可以提升和改进的地方。
- 细节实现、debug能力等有待提高(好像是个人问题)
- 交流方式存在问题,虽说是领航员和驾驶员模式,但是很多时间两人都是无言状态,比如领航员等着驾驶员写完一个方法或功能
对于改进点,可以在编码前事先将功能划分成更具体的块,而不是较为笼统交给驾驶员完成
→ 📖 Q4.3(I) 锐评一下你的搭档!并请至少列出三个优点和一个缺点。
优
- 大局观好,框架概念强
- 代码审查认真可靠
- 在很多方面创新思维强
缺
- 相关资料查找能力较弱
对结对编程的理解
→ 📖 Q4.4(I) 说明结对编程的优缺点、你对结对编程的理解。
优:两人并行构建项目,有利于bug和架构相关问题的及时发现,并且在接触新的技术层面时,两人一起研究探讨往往能提高并发度,大大提高项目的实现效率和可扩展性
缺:一方面是小项目实际效果不好,看短时间的完成度可能还不如单独开发,反而是要求复杂、技术涉及多的项目可能效果更好,另一方面是两人难免有差异,沟通不及时极有可能影响工作进度,甚至出现后期大重构的情况。
我的理解就是一人当领航员、一人作驾驶员,边审查边编码,构思与实现并行完成的编程方式,“旁观者”和“当局者”共存。
代码实现提交
→ 📖 Q4.5(P) 请提供你们完成代码实现的代码仓库链接。
https://github.com/manhuo/software-project
附录
附录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 | 合计 |
浙公网安备 33010602011771号