[P] 结对项目:播棋・the・Rock
结对项目:博客问题清单
Chapter.1 缠结的字节码(Bytecode Complex)
引入
→ 📖 Q1.1§ 请记录下目前的时间。
2024/3/26 14:00
→ 📖 Q1.2§ 根据之前学习的专业课和各类开发经验,回答:为什么原生应用相较 Web app 更有快的印象?这样的“速度”又是如何达成的?
- Web app 的所有操作需要先由浏览器内核处理,再由操作系统运行,而原生应用是直接调用系统 API,所以原生应用更快(增加一层浏览器内核进行抽象将会带来的开销)
- 某些特殊硬件提供的接口浏览器内核无法调用
- Web app 原有的开发语言本身性能上可能不如原生的开发语言
→ 📖 Q1.3§ “要让 Web 生态、或者说一种雄心勃勃的软件运行环境的未来,受益于既有的‘原生’软件开发模式、技术栈和工具链,我们还缺少什么?”——你们的答案是?
我们需要一个中间代码表示形式,将 Web 代码编译为这种中间代码,然后在不同的平台上,利用原生的工具链将这种中间代码编译为原生代码。这样可以在不同的平台上运行相同的代码,而不需要重新编写代码。
结对过程
→ 📖 Q1.4(I) 作为本项目的调查:请如实标注在开始项目之前对 Wasm 的熟悉程度分级,可以的话请细化具体的情况。
I. 没有听说过; ✔️
II. 仅限于听说过相关名词;
III. 听说过,且有一定了解;
IV. 听说过,且使用 Wasm 实际进行过开发(即便是玩具项目的开发)。
→ 📖 Q1.5§ 请在完成任务的同时记录,并在完成任务后整理完善:
- 查阅了 mdn WebAssembly,根据其中的 C/C++ 指引安装了相关环境。
- 遇到了 js 和 c-wasm 难以对接的问题,查阅了 wasm 相关接口文档,特别是 WebAssembly.Memory 部分,构建了一个提供内存数据传递的胶水代码。
编程语言选择
自选的编程语言
→ 📖 Q1.6.X.1§ 选择该编程语言的原因是?
C 语言较为底层,速度快,GCC 优化好,并且也比较熟悉。
→ 📖 Q1.6.X.2§ 为了完成相关编程任务,进行了哪些操作、使用了怎样的工具链?简要描述相关工具做了什么。
- 下载并安装 Emscripten 环境
- 使用 Emscripten 编译器 emcc 将 C 代码编译为 WebAssembly 字节码并生成对应的 js 文件(和 html)
- 编写胶水代码将 js 和 wasm 代码结合起来
总结
→ 📖 Q1.7§ 请记录下目前的时间。
2024/3/26 18:40
→ 📖 Q1.8(I) 请写下本部分的心得体会。
首次尝试为 wasm 设置必要的编译器 Emscripten 时非常艰难,因为官方文档并未为 Windows 系统文档提供详细说明,网上也缺乏相关论坛帖子。尽管我们对 WebAssembly 仍然了解不深,但是我相信,开发 WebAssembly 将会为网络开发人员带来许多新颖的可能性。
Chapter.2 石子翻滚,晨光降临你身(Rock’n Roll, Morning Light Falls on You)
结对过程
→ 📖 Q2.1§ 请记录下目前的时间。
2024/3/30 14:00
→ 📖 Q2.2§ 请在完成任务的同时记录,并在完成任务后整理完善:
Personal Software Process Stages | 个人软件开发流程 | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
PLANNING | 计划 | ||
- Estimate | - 估计这个任务需要多少时间 | 5 | |
DEVELOPMENT | 开发 | ||
- Analysis & Design Spec | - 需求分析 & 生成设计规格(确定要实现什么) | 15 | |
- Technical Background | - 了解技术背景(包括学习新技术) | 45 | |
- Coding Standard | - 代码规范 | 15 | |
- Design | - 具体设计(确定怎么实现) | 60 | |
- Coding | - 具体编码 | 60 | |
- Code Review | - 代码复审 | 30 | |
- Test Design | - 测试设计(确定怎么测,比如要测试哪些情景、设计哪些种类的测试用例) | 60 | |
- Test Implement | - 测试实现(设计/生成具体的测试用例、编码实现测试) | 60 | |
REPORTING | 报告 | ||
- Quality Report | - 质量报告(评估设计、实现、测试的有效性) | 30 | |
- Size Measurement | - 计算工作量 | 5 | |
- Postmortem & Process Improvement Plan | - 事后总结和过程改进计划(总结过程中的问题和改进点) | 15 | |
TOTAL | 合计 | 400 |
- 查阅了播棋玩法
- 通过模拟的方法实现 T2
- 列出所有可能的逻辑
- 播种
- 分配
- 不是对方计分洞
- 放入
- 是对方计分洞
- 跳过
- 不是对方计分洞
- 观察最后一颗
- 是我方计分洞
- 继续分配
- 不是我方计分洞
- 是己方无棋子的棋洞且对方棋洞有棋子
- 都放入己方计分洞
- 其他情况
- 轮到对方播种
- 是己方无棋子的棋洞且对方棋洞有棋子
- 是我方计分洞
- 任一方无棋子
- 对方的所有棋子放到对方计分洞中
- 算双方净胜棋数
- 根据列出的逻辑实现代码
- 列出所有可能的逻辑
- 在测试部分遇到了测试不全面的问题
- 采用了评测机的方法,进行了大量、随机的数据测试
- 根据运行逻辑制造了一些评测机可能无法覆盖的数据
测试
→ 📖 Q2.3§ 请说明针对该任务,你们设计和实现测试的方法及过程,包括但不限于:出于对需求的哪些考虑设计了哪些测试用例、如何评估所设计测试的有效性 等等。
我们对于测试采用了两种方案:
- 评测机构造大量的数据
- 手动针对特殊情况添加测试
其中在评测机部分,我们的设计是:
设计了三种测试:
- 正常结束的测试数据
- 正常未结束的测试数据
- 不正常结束的随机测试数据
通过 getHole()方法采用栈的方法,避免大量非法数据
int getHole(int player, int num[][7])
{
int stack[6], top = 0;
for (int i = 0; i < 6; ++i)
{
if (num[player][i] > 0)
{
stack[top++] = i;
}
}
int p = rand() % top;
return stack[p];
}
在手动构造测试数据部分,我们的设计是:
我们首先考虑一步下可能产生的情况,分别对一步的开始、中间和结束部分进行了讨论。
- 开始
- 有棋子
- 无棋子
- 已结束
- 中间
- 经过对方计分洞
- 经过我方计分洞
- 不经过计分洞
- 结束
- 最后是我方计分洞
- 最后不是我方计分洞
- 我方为空
- 对方为空
- 对方不为空
- 我方不为空
- 我方为空
→ 📖 Q2.4(I) 请说明单元测试对软件开发的作用。
单元测试(Unit Testing)使代码更模块化,这帮助我们在某个问题变成大问题之前将其捕获,从而使代码更整洁、更易于维护。
总结
→ 📖 Q2.5§ 请记录下目前的时间,并根据实际情况填写 附录 A:基于 PSP 2.1 修改的 PSP 表格 的“实际耗时”栏目。
2024/4/2 17:00
Personal Software Process Stages | 个人软件开发流程 | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
PLANNING | 计划 | ||
- Estimate | - 估计这个任务需要多少时间 | 5 | 5 |
DEVELOPMENT | 开发 | ||
- Analysis & Design Spec | - 需求分析 & 生成设计规格(确定要实现什么) | 15 | 15 |
- Technical Background | - 了解技术背景(包括学习新技术) | 45 | 45 |
- Coding Standard | - 代码规范 | 15 | 15 |
- Design | - 具体设计(确定怎么实现) | 60 | 30 |
- Coding | - 具体编码 | 60 | 120 |
- Code Review | - 代码复审 | 30 | 20 |
- Test Design | - 测试设计(确定怎么测,比如要测试哪些情景、设计哪些种类的测试用例) | 60 | 90 |
- Test Implement | - 测试实现(设计/生成具体的测试用例、编码实现测试) | 60 | 60 |
REPORTING | 报告 | ||
- Quality Report | - 质量报告(评估设计、实现、测试的有效性) | 30 | 15 |
- Size Measurement | - 计算工作量 | 5 | 5 |
- Postmortem & Process Improvement Plan | - 事后总结和过程改进计划(总结过程中的问题和改进点) | 15 | 15 |
TOTAL | 合计 | 400 | 435 |
→ 📖 Q2.6(I) 请写下本部分的心得体会。
写复杂程序时,最好将每个任务单独分开。 特别是当您有一个特殊情况大部分是“驱动力”的任务时。 在我的案例中,我们将玩家的移动单独放在一个实体中,无论多长时间都不会受到影响。 这是我在程序中编写游戏规则的第一次尝试,因此我学到了如何将规则转化成代码限制。
Chapter.3 十二进制的黄昏(Dusk of the Duodecimal System)
结对过程
→ 📖 Q3.1§ 请记录下目前的时间。
2024/4/2 18:00
→ 📖 Q3.2§ 请在完成任务的同时记录,并在完成任务后整理完善:
Personal Software Process Stages | 个人软件开发流程 | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
PLANNING | 计划 | ||
- Estimate | - 估计这个任务需要多少时间 | 5 | |
DEVELOPMENT | 开发 | ||
- Analysis & Design Spec | - 需求分析 & 生成设计规格(确定要实现什么) | 15 | |
- Technical Background | - 了解技术背景(包括学习新技术) | 45 | |
- Coding Standard | - 代码规范 | 30 | |
- Design | - 具体设计(确定怎么实现) | 30 | |
- Coding | - 具体编码 | 120 | |
- Code Review | - 代码复审 | 120 | |
- Test Design | - 测试设计(确定怎么测,比如要测试哪些情景、设计哪些种类的测试用例) | 45 | |
- Test Implement | - 测试实现(设计/生成具体的测试用例、编码实现测试) | 45 | |
REPORTING | 报告 | ||
- Quality Report | - 质量报告(评估设计、实现、测试的有效性) | 30 | |
- Size Measurement | - 计算工作量 | 15 | |
- Postmortem & Process Improvement Plan | - 事后总结和过程改进计划(总结过程中的问题和改进点) | 15 | |
TOTAL | 合计 | 485 |
- 查阅了播棋的相关资料,并且上手对弈
- 查阅了博弈论的相关资料
- min-max
- alpha-beta 剪枝
- 查阅了播棋的优秀策略
- bilibili
- 个人博客
- 开发
- 编写播棋的基本框架
- 编写 min-max 算法
- 在理解 min-max 算法方面出现了一些偏差,通过查阅资料和讨论解决
- 基于 min-max 的搜索策略时间复杂度较高,设计了一个评估函数在深度较深时直接返回结果
- 编写基于策略的决策
- 基于策略的启发式方法是否合理难以进行定量分析,算法特点,难以解决
代码可复用性与需求变更
→ 📖 Q3.3§ 请说明针对该任务,你们对 🧑💻 T2
中已实现的代码进行了哪些复用和修改。
T3-1 和 T2 的运行逻辑是一致的。我们在 T2 完全记录了模拟过程,所以我们 T3-1 和 T2 的最大区别在于输出逻辑。
主要在 T3-1 对 T2 的运行逻辑部分采用了复用。T3-1 架构基本上跟 T2 完全一致。
区别主要在于开始的 Flag 部分和返回值部分。我们取消了非法数据依靠 Flag 进行判断,修改了 return 结果,其他基本跟 T2 完全一致。
→ 📖 Q3.4(I) 请说明在编码实现时,可以采取哪些设计思想、考虑哪些设计冗余,来提高既存代码适应需求变更的能力。
设计思想:
- 模块化
- KISS (Keep it Simple and Stupid):使用简单而直接的数据结构和算法来实现
设计冗余:
- 记录文档
- 代码注释
需求建模和算法设计
→ 📖 Q3.5§ 请说明你们如何建模这一需求。
按照博弈论的思路,我们将对局的局面抽象为树上的节点,
每一次选择都是寻找一个儿子节点进行游走。
我们假定每个操作者都是理性且聪明的,
故我们将选择令对手的最优策略最差的方案作为当前节点的最优策略。
→ 📖 Q3.6§ 请说明针对该任务,你们采取了哪些策略来取得更大的净胜棋数,如何编程实现这些策略。
- 实现了一个基于 min-max 的搜索策略,并且在深度较深时直接返回己方棋盘和对方棋盘上的棋子数之差,作为评估函数来解决搜索空间过大的问题。
- 实现了基于棋手策略的启发式方法,最后发现效果并不好,因为策略本身需要全局的灵活性,在不同的指标上是需要妥协的,而硬编码很难实现这样的功能。
软件度量
→ 📖 Q3.7§ 请说明你们如何量度所实现的程序模块的有效性,例如:“如何说明我们的程序模块对弈能力很强?”,尝试提出一些可能的定量分析方式。
- 分别实现了两种方案,然后进行对拍和对弈
- 和其他小组进行对弈
- 获得测试结果(正确性,时间,最终得分)
- trace 程序每个部分的运行
总结
→ 📖 Q3.8§ 请记录下目前的时间,并根据实际情况填写 附录 A:基于 PSP 2.1 修改的 PSP 表格 的“实际耗时”栏目。
Personal Software Process Stages | 个人软件开发流程 | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
PLANNING | 计划 | ||
- Estimate | - 估计这个任务需要多少时间 | 5 | 5 |
DEVELOPMENT | 开发 | ||
- Analysis & Design Spec | - 需求分析 & 生成设计规格(确定要实现什么) | 15 | 15 |
- Technical Background | - 了解技术背景(包括学习新技术) | 45 | 60 |
- Coding Standard | - 代码规范 | 30 | 15 |
- Design | - 具体设计(确定怎么实现) | 30 | 45 |
- Coding | - 具体编码 | 120 | 120 |
- Code Review | - 代码复审 | 120 | 90 |
- Test Design | - 测试设计(确定怎么测,比如要测试哪些情景、设计哪些种类的测试用例) | 45 | 15 |
- Test Implement | - 测试实现(设计/生成具体的测试用例、编码实现测试) | 45 | 30 |
REPORTING | 报告 | ||
- Quality Report | - 质量报告(评估设计、实现、测试的有效性) | 30 | 30 |
- Size Measurement | - 计算工作量 | 15 | 5 |
- Postmortem & Process Improvement Plan | - 事后总结和过程改进计划(总结过程中的问题和改进点) | 15 | 10 |
TOTAL | 合计 | 485 | 440 |
→ 📖 Q3.9(I) 请写下本部分的心得体会。
利用有限功能设计“聪明”的软件需要相当的“聪明”手段。
写本部分的代码时,最大问题是 – 如何在没有超过时间内获得更多的胜利?我们研究了不同解决方案,例如minmax算法和深度优先搜索DFS,但是考虑之后发现选择其中一个,不足以全面地解决问题。因此,决定将两者各自的优点结合起来。
结对项目总结
结对过程回顾和反思
→ 📖 Q4.1§ 提供两人在讨论的结对图像资料。
→ 📖 Q4.2§ 回顾结对的过程,反思有哪些可以提升和改进的地方。
- 在结对过程中,两人在担任领航员的过程中总是会走神从而跟不上进度,作为代码手也常常出现说一套做一套从而产生思维偏差的问题。
- 需要加深对于结对编程的理解,明确领航员和代码手的职责和工作重心,并且根据情况进行调整
- 在结对的形式上,需要提前安排好工作的地点和方式
→ 📖 Q4.3(I) 锐评一下你的搭档!并请至少列出三个优点和一个缺点。
优点
- 需要时认真,需要时轻松
- 对所学领域有很好的了解
- 注重细节而代码整齐
缺点
- 太完美了,缺少缺点
对结对编程的理解
→ 📖 Q4.4(I) 说明结对编程的优缺点、你对结对编程的理解。
优点:人之间使用逻辑沟通,也可以互相监督,从而提高工作效率
缺点:由于结队是彼此依赖的,一个人的问题会影响整个结队