[P] 结对项目: 花见小路
| 项目 | 内容 |
|---|---|
| 这个作业属于哪个课程 | 软件工程 |
| 这个作业的要求在哪里 | [P] 结对项目:花见小路 |
| 我在这个课程的目标是 | 掌握软件工程的核心理论,协作完成软件项目开发 |
| 这个作业在哪个具体方面帮助我实现目标 | 体验结对编程开发的具体流程,积累经验 |
→ 📖 Q0.0(P) 【你可以在结对结束后补充】如果你的代码仓库包含 AIGC 的部分,列举使用的工具、模型和使用范围。若未使用则填写:本组提交的全部代码不包含AI补全或生成的部分。
本组提交的全部代码不包含 AI 补全或生成的部分
Chapter.0 wasm从安装到入门
引入
→ 📖 Q0.1(P) 请记录下目前的时间。
4 月 2 日 14:10
调查
→ 📖 Q0.2(I) 【你可以在结对结束后另行补充。】作为本项目的调查:
请如实标注在开始项目之前对 Wasm 的熟悉程度分级,可以的话请细化具体的情况。(分别回答两人各自的情况)
I. 没有听说过;
II. 仅限于听说过相关名词;
III. 听说过,且有一定了解;
IV. 听说过,且使用 Wasm 实际进行过开发(即便是玩具项目的开发)。
I. 没有听说过
请如实标注在开始项目之前对桌游花见小路的熟悉程度分级,可以的话请细化具体的情况。(分别回答两人各自的情况)
I. 不了解玩法和规则;
II. 听说过,且有一定了解;
I. 不了解玩法和规则
总结
→ 📖 Q0.3(P) 请记录下目前的时间。
4 月 2 日 14:30
Chapter.1 七色之缨
结对过程
→ 📖 Q1.1(P) 请记录下目前的时间。
4 月 2 日 14:40
→ 📖 Q1.2(P) 请在完成任务的同时记录,并在完成任务后整理完善:
- 浏览任务要求,参照 附录A:基于 PSP 2.1 修改的 PSP 表格,估计任务预计耗时;
| Personal Software Process Stages | 个人软件开发流程 | 预估耗时(分钟) | 实际耗时(分钟) |
|---|---|---|---|
| PLANNING | 计划 | 5 | 5 |
| - Estimate | - 估计这个任务需要多少时间 | 5 | 5 |
| DEVELOPMENT | 开发 | 140 | 140 |
| - Analysis & Design Spec | - 需求分析 & 生成设计规格(确定要实现什么) | 20 | 10 |
| - Technical Background | - 了解技术背景(包括学习新技术) | 20 | 30 |
| - Coding Standard | - 代码规范 | 10 | 15 |
| - Design | - 具体设计(确定怎么实现) | 10 | 5 |
| - Coding | - 具体编码 | 30 | 25 |
| - Code Review | - 代码复审 | 30 | 30 |
| - Test Design | - 测试设计(确定怎么测,比如要测试哪些情景、设计哪些种类的测试用例) | 10 | 15 |
| - Test Implement | - 测试实现(设计/生成具体的测试用例、编码实现测试) | 10 | 10 |
| REPORTING | 报告 | 30 | 25 |
| - Quality Report | - 质量报告(评估设计、实现、测试的有效性) | 10 | 10 |
| - Size Measurement | - 计算工作量 | 5 | 5 |
| - Postmortem & Process Improvement Plan | - 事后总结和过程改进计划(总结过程中的问题和改进点) | 15 | 10 |
| TOTAL | 合计 | 175 | 170 |
- 完成编程任务期间,依次做了什么(例如查阅了哪些资料、如何设计判定逻辑、如何设计测试样例、遇到了什么问题、如何解决)。
- 查阅了 WebAssembly 的基础教程,学习了 as 的语法
- 仔细阅读胜负判定规则,明确立即胜利条件、前两轮继续、第三轮总分比较、最高分比较及平局的顺序。规划主函数和三个辅助函数,逐一实现函数
- 针对每一种规则分支:总分胜、标记数胜、继续、总分高胜、最高分胜、平局,构造测试用例,确保覆盖每一种情况
- 编写过程中遇到的问题:忘记在变量声明和返回值前添加
i8类型标注,导致编译报错,后续逐项补全
设计
→ 📖 Q1.3(P) 请说明你们为这个判定模块设计了哪些中间量或辅助函数;如果没有额外设计,也请说明为什么认为直接实现已经足够清晰。
我们设计了三个辅助函数
calculate_score用于统计两方当前获得的得分count_marks用于统计倾心标记的个数max_mark用于双方所拥有的最高分值的倾心标记的分值
→ 📖 Q1.4(I) 请说明在这样一个规则判定类模块中,如何避免“漏判”“错判”或分支顺序错误等问题。
严格按照规则中的顺序编写代码,先检查总分→再统计标记数→ 然后判断轮数是否小于 3→最后处理第三轮的情况。处理每一个分支时不在主函数中写,而是用辅助函数,保证主函数的逻辑清晰性。
测试
→ 📖 Q1.5(P) 请说明你们设计了哪些测试用例,这些测试分别覆盖了哪一类规则或边界情况。
-
一方分值达到 11 分而获胜
-
我方胜,返回 1
board: [1, 0, 1, -1, -1, 1, 1], round: 2
-
对方胜,返回 -1
board: [1, 0, 1, 0, -1, -1, -1], round: 3
-
-
一方获得至少 4 枚倾心标记而获胜
-
我方胜,返回 1
board: [0, 1, 1, 1, 1, 0, -1], round: 3
-
对方胜,返回 -1
board: [-1, -1, -1, -1, 0, 0, 1], round: 1
-
-
前两小轮结束时尚未满足胜利条件,应返回 0
board: [1, 1, 0, 0, 0, -1, 0], round: 1
-
第三小轮结束时,总分不同,由总分高者获胜
-
我方胜,返回 1
board: [-1, -1, 0, 0, 0, 1, 1], round: 3
-
对方胜,返回 -1
board: [1, 0, 1, -1, -1, 0, 0], round: 3
-
-
第三小轮结束时,总分相同,由最高档位倾心标记判定胜负
-
我方胜,返回 1
board: [-1, -1, 0, 0, 0, 1, 0], round: 3
-
对方胜,返回 -1
board: [-1, 0, 0, 1, 1, -1, 0], round: 3
-
-
第三小轮结束时平局,应返回 2
board: [1, -1, 0, 1, -1, 0, 0], round: 3
→ 📖 Q1.6(I) 请说明你对“先写测试再实现”与“先实现再补测试”两种方式的理解。
先写测试再实现, 要求开发者在写代码前熟悉规则, 明确边界条件, 也对后续的代码实现有帮助. 对于花见小路这种结果状态比较少的桌游, 编写测试样例的难度不大, 所以很适合先写测试.
先实现再补测试, 更符合直觉, 先让代码跑起来. 写代码的时候也能发现一些细节, 有利于构造测试样例.
总结
→ 📖 Q1.7(P) 请记录下目前的时间,并根据实际情况填写 附录A:基于 PSP 2.1 修改的 PSP 表格 的“实际耗时”栏目。
4 月 2 日 17:30
→ 📖 Q1.8(I) 请写下本部分的心得体会。
学到了新的编程语言; 通过自己构造的样例发现了代码逻辑上的 bug, 充分的测试很重要; 结对编程也很有趣.
Chapter.2 不祥之影
准备
→ 📖 Q2.1(P) 请记录下目前的时间。
4 月 2 日 19:00
→ 📖 Q2.2(P) 请在完成任务的同时记录,并在完成任务后整理完善:
- 浏览任务要求,参照 附录A:基于 PSP 2.1 修改的 PSP 表格,估计任务预计耗时;
| Personal Software Process Stages | 个人软件开发流程 | 预估耗时(分钟) | 实际耗时(分钟) |
|---|---|---|---|
| PLANNING | 计划 | 5 | 5 |
| - Estimate | - 估计这个任务需要多少时间 | 5 | 5 |
| DEVELOPMENT | 开发 | 140 | 125 |
| - Analysis & Design Spec | - 需求分析 & 生成设计规格(确定要实现什么) | 10 | 10 |
| - Technical Background | - 了解技术背景(包括学习新技术) | 10 | 0 |
| - Coding Standard | - 代码规范 | 10 | 5 |
| - Design | - 具体设计(确定怎么实现) | 20 | 20 |
| - Coding | - 具体编码 | 60 | 60 |
| - Code Review | - 代码复审 | 30 | 30 |
| - Test Design | - 测试设计(确定怎么测,比如要测试哪些情景、设计哪些种类的测试用例) | 5 | 0 |
| - Test Implement | - 测试实现(设计/生成具体的测试用例、编码实现测试) | 0 | 0 |
| REPORTING | 报告 | 30 | 25 |
| - Quality Report | - 质量报告(评估设计、实现、测试的有效性) | 10 | 10 |
| - Size Measurement | - 计算工作量 | 5 | 5 |
| - Postmortem & Process Improvement Plan | - 事后总结和过程改进计划(总结过程中的问题和改进点) | 15 | 10 |
| TOTAL | 合计 | 175 | 150 |
- 完成编程任务期间,依次做了什么(比如查阅了什么资料,随后如何进行了开发,遇到了什么问题,又通过什么方式解决);
- T2 思路比较直接,我们根据题意,模拟两人出卡过程,将每个行动设计成一个函数单独计算得分,最后统计得分。
- 遇到了一个小 bug:AS 中的
substr(start, length)第二个参数是长度,不是结束下标。
代码可复用性与需求变更
→ 📖 Q2.3(P) 请说明针对该任务,你们对 🧑💻 T1 中已实现的代码进行了哪些复用和修改。
我们没有对 T1 的代码进行复用或修改。
→ 📖 Q2.4(I) 请说明在编码实现时,可以采取哪些设计思想、考虑哪些设计冗余,来提高既存代码适应需求变更的能力。
- 为每个行动类型写函数, 输入行动, 输出行动后的效果;
- 每个函数只做一件事, 便于复用
头脑风暴环节
→ 📖 Q2.5(P) 头脑风暴环节:
我们终于快要开始让程序玩游戏了!请尝试分析:T2 中不带 X 的操作记录比起实际对局多出了多少信息?如果加上 X,也就是失去了这部分信息的话,如何处理对小轮结束后状态的估计?
多出了对方玩家密约和取舍的牌面。
当历史记录包含X时,我们无法唯一确定双方场面上每种牌的张数,只能得到一个可能性集合。对于每个X,可能是任意未被公开的牌,我们可以通过回溯或枚举所有可能的实际牌型组合。
总结
→ 📖 Q2.6(P) 请记录下目前的时间,并根据实际情况填写 附录 A:基于 PSP 2.1 修改的 PSP 表格 的“实际耗时”栏目。
4 月 2 日 21:30
→ 📖 Q2.7(I) 请写下本部分的心得体会。
T2 要根据出牌记录算出当轮的牌面, 需要对每个行动类型进行分析, 写完之后我对规则理解更深了, 有利于后续 T3 的策略设计. 和队友也配合得越来越默契.
Chapter.3 道途之荆
准备
→ 📖 Q3.1(P) 请记录下目前的时间。
4 月 8 日 14:00
→ 📖 Q3.2(P) 请在完成任务的同时记录,并在完成任务后整理完善:
- 浏览任务要求,参照 附录A:基于 PSP 2.1 修改的 PSP 表格,估计任务预计耗时;
| Personal Software Process Stages | 个人软件开发流程 | 预估耗时(分钟) | 实际耗时(分钟) |
|---|---|---|---|
| PLANNING | 计划 | 5 | 5 |
| - Estimate | - 估计这个任务需要多少时间 | 5 | 5 |
| DEVELOPMENT | 开发 | 330 | 330 |
| - Analysis & Design Spec | - 需求分析 & 生成设计规格(确定要实现什么) | 10 | 10 |
| - Technical Background | - 了解技术背景(包括学习新技术) | 10 | 10 |
| - Coding Standard | - 代码规范 | 10 | 10 |
| - Design | - 具体设计(确定怎么实现) | 120 | 120 |
| - Coding | - 具体编码 | 120 | 140 |
| - Code Review | - 代码复审 | 30 | 30 |
| - Test Design | - 测试设计(确定怎么测,比如要测试哪些情景、设计哪些种类的测试用例) | 0 | 0 |
| - Test Implement | - 测试实现(设计/生成具体的测试用例、编码实现测试) | 30 | 10 |
| REPORTING | 报告 | 30 | 25 |
| - Quality Report | - 质量报告(评估设计、实现、测试的有效性) | 10 | 10 |
| - Size Measurement | - 计算工作量 | 5 | 5 |
| - Postmortem & Process Improvement Plan | - 事后总结和过程改进计划(总结过程中的问题和改进点) | 15 | 10 |
| TOTAL | 合计 | 365 | 360 |
- 完成编程任务期间,依次做了什么(比如查阅了什么资料,随后如何进行了开发,遇到了什么问题,又通过什么方式解决);
- 我们通过在游戏实战中找到可以获得胜利的策略,不断讨论和检验策略的正确性
- 得出很多条获得胜利的策略后,对每一个动作的需求进行总结
- 在编码中将每一个动作抽离成一个函数,实现每一个动作总结的获胜策略
头脑风暴环节
→ 📖 Q3.3(P) 头脑风暴环节:
假设提供更充裕的时间和资源,这个游戏中你能找到的最优策略有可能是什么形式的?进行调研并总结分析。你还可以在任务结束后试着实现(不计分)。
用蒙特卡洛树搜索的方式,结合对手手牌的概率来推演对局,估算对手可能持有的各类牌,通过随机模拟多场对局判断怎么走更优。我们还可以分析对手的打法习惯,根据他之前是送牌还是抢牌的选择,反向推测他手里大概有什么牌,以及他是偏保守还是偏激进的玩法。之后再根据这些推断,随时调整自己的行动,针对性克制对手,这样就能在接近最优博弈平衡的情况下,最大程度提高自己的获胜概率。
需求建模和算法设计
→ 📖 Q3.4(P) 请说明针对该任务,你们采取了哪些策略来优化决策。具体而言,怎么选择行动类型?选牌如何更优?如何编程实现。
赢的局面可以是: 2234, 2235, 245 , ... 其他局面不太容易达到. 我们主要追求 2234, 如果实在没有抽中 4, 那么争取拿到 5 分, 狗到下一局 (4 和 5 必须至少拿到 1 张才能不输).
密约 (隐藏 1 张): 如果手上有 4, 那么就藏 4; 如果没有 4, 那么藏 5
丢弃 (丢 2 张, 就不出现在牌局里了):
-
在已经有 2 张
4的情况下, 要扔且只扔 1 张4 -
当 ABC 已有 1 张时, 剩下那张可以丢
赠送 (选 3 张, 对手挑 1 张):
- 如果有 3 张 D / E, 就送这 3 张
- 选 3 张分值最接近的不同的牌
- 别人已经有的 1 张 + 2 张一样的牌
竞争 (选 4 张, 分成 2 组, 对手挑 1 组):
- 在没有特别好的密约 / 丢弃 / 赠送方案的时候, 才会进行竞争, 这往往是在后两手了, 此时可以模拟计算一下, 主要是看怎么分组
- 2 张不要的打牌 + 2 张小牌 / 比较平均的分组
编程实现
(1) 分析局势
-
根据历史记录计算已经打出的牌, 可能有隐藏的牌, 推测一下藏的啥
-
现在我能执行的行动
-
我需要争取的人物
(2) 考虑如何出牌
- 对每个当前可能执行的操作 (密约 / 丢弃 / ...), 算出此类操作最好的出牌方式, 同时粗略地给这个出牌估计一下分值
- 把上面得到的出牌方式按照分值排序, 选最好的那个, 如果分值相同, 按 3 \(\rightarrow\) 1 \(\rightarrow\) 2 \(\rightarrow\) 4 的顺序选
(3) 对手出牌的时候选什么牌
- 设计了
weight_of函数, 综合角色基础分、实时出牌差、是否接近获胜线等因素
代码可复用性与需求变更
→ 📖 Q3.5(P) 请说明针对该任务,你们对 🧑💻 T2 中已实现的代码进行了哪些复用和修改。
修改了行动操作 add_cards 的函数, 推测 X 牌
复用了 calc_current_state 函数, 来计算当前场上的状态
→ 📖 Q3.6(I) 请说明在编码实现时,可以采取哪些设计思想、考虑哪些设计冗余,来提高既存代码适应需求变更的能力。
- 将每个行动类型的出牌逻辑抽离成一个函数, 便于后续调整每个行动的策略
- 设计一个通用的牌型评估函数, 便于后续调整策略时快速评估不同出牌方案的优劣
软件度量
→ 📖 Q3.7(P) 请说明你们如何量度所实现的程序模块的有效性,例如:“如何说明我们的程序模块决策能力很强?”,尝试提出一些可能的定量分析方式或测试方式。
- 让程序自己跟自己打,分别用不同策略版本打 1000 局,看新版胜率是否有提高。
- 让程序跟随机生成的机器人打,胜率能到 70% 以上说明决策能力较强
- 设计几个经典局面,人工判断最优出法,看程序是否选对。
总结
→ 📖 Q3.8(P) 请记录下目前的时间,并根据实际情况填写 附录A:基于 PSP 2.1 修改的 PSP 表格 的“实际耗时”栏目。
4 月 8 日 20:00
→ 📖 Q3.9(I) 请写下本部分的心得体会。
写代码进行决策和我自己凭感觉进行决策很不一样, 想了一些策略, 但没想到很好的方式去编程实现. 所以我觉得想清楚计算机如何决策, 充分利用她算得快的特点去做一些遍历、评估可能更好.
设计很重要, 需要合理地评估工作量, 找一个可行的方案, 这需要两个人讨论.
结对项目总结
结对过程回顾和反思
→ 📖 Q4.1(P) 提供两人在讨论的结对图像资料。
→ 📖 Q4.2(P) 回顾结对的过程,反思有哪些可以提升和改进的地方。
- 分工可以更明确一点,比如一个人写代码的时候另一个人可以去构造测试用例 / 记录文档
- 写代码之前进行更详细的讨论,以便在写的时候两个人思路同步
→ 📖 Q4.3(I) 锐评一下你的搭档!并请至少列出三个优点和一个缺点。
优点: 查资料和阅读资料特别快; 情绪稳定, 遇到 bug 和其他问题的时候会很耐心地去解决; 性格好, 很好沟通
缺点: 太熟悉了, 容易闲聊
对结对编程的理解
→ 📖 Q4.4(I) 说明结对编程的优缺点、你对结对编程的理解。
优点:
- 思维互补, 显著提升代码质量, 减少逻辑漏洞
- 让写代码更有趣了
缺点:
- 需要两个人协商时间
- 单次工作时间太长, 比较累
结对编程由两个人共同完成同一段代码, 我们必须把想法讲给对方听, 这样会让思路更加清晰. 驾驶员负责代码的具体实现, 领航员负责审查代码. 我觉得这和 Vibe coding 很像, 我把想法告诉 AI, AI 负责生成代码, 我负责判断. 虽然形式不同, 但是“结对”的思想是一样的.
代码实现提交
→ 📖 Q4.5(P) 请提供你们完成代码实现的代码仓库链接。

浙公网安备 33010602011771号