[P] 结对项目:花见小路
结对项目:博客问题清单
请将本文件在代码仓库外复制一份,一边阅读和完成结对项目、一边填写入代码仓库外的版本,或采取简记、语音备忘等方式记载较复杂问题的要点之后再补充。请不要将本文档内的作答提交到代码仓库。
→ 📖 Q0.0(P) 【你可以在结对结束后补充】如果你的代码仓库包含 AIGC 的部分,列举使用的工具、模型和使用范围。若未使用则填写:本组提交的全部代码不包含AI补全或生成的部分。
使用了vscode的copilot模型,在chapter3部分中辅助完成具体算法的实现。
Chapter.0 wasm从安装到入门
引入
→ 📖 Q0.1(P) 请记录下目前的时间。
2026年3月28日13点整
调查
→ 📖 Q0.2(I) 【你可以在结对结束后另行补充。】作为本项目的调查:
请如实标注在开始项目之前对 Wasm 的熟悉程度分级,可以的话请细化具体的情况。(分别回答两人各自的情况)
1
I. 没有听说过;
II. 仅限于听说过相关名词;
III. 听说过,且有一定了解;
IV. 听说过,且使用 Wasm 实际进行过开发(即便是玩具项目的开发)。
请如实标注在开始项目之前对桌游花见小路的熟悉程度分级,可以的话请细化具体的情况。(分别回答两人各自的情况)
1
I. 不了解玩法和规则;
II. 听说过,且有一定了解;
总结
→ 📖 Q0.3(P) 请记录下目前的时间。
2026年3月28日14点整
Chapter.1 七色之缨
结对过程
→ 📖 Q1.1(P) 请记录下目前的时间。
2026年3月29日21点整
→ 📖 Q1.2(P) 请在完成任务的同时记录,并在完成任务后整理完善:
- 浏览任务要求,参照 附录A:基于 PSP 2.1 修改的 PSP 表格,估计任务预计耗时;
- 完成编程任务期间,依次做了什么(例如查阅了哪些资料、如何设计判定逻辑、如何设计测试样例、遇到了什么问题、如何解决)。
| Personal Software Process Stages | 个人软件开发流程 | 预估耗时(分钟) | 实际耗时(分钟) |
|---|---|---|---|
| PLANNING | 计划 | 5 | 2 |
| - Estimate | - 估计这个任务需要多少时间 | 5 | 2 |
| DEVELOPMENT | 开发 | 45 | 40 |
| - Analysis & Design Spec | - 需求分析 & 生成设计规格(确定要实现什么) | 5 | 5 |
| - Technical Background | - 了解技术背景(包括学习新技术) | 5 | 2 |
| - Coding Standard | - 代码规范 | 5 | 3 |
| - Design | - 具体设计(确定怎么实现) | 5 | 5 |
| - Coding | - 具体编码 | 10 | 15 |
| - Code Review | - 代码复审 | 5 | 3 |
| - Test Design | - 测试设计(确定怎么测,比如要测试哪些情景、设计哪些种类的测试用例) | 5 | 2 |
| - Test Implement | - 测试实现(设计/生成具体的测试用例、编码实现测试) | 5 | 5 |
| REPORTING | 报告 | 15 | 8 |
| - Quality Report | - 质量报告(评估设计、实现、测试的有效性) | 5 | 4 |
| - Size Measurement | - 计算工作量 | 5 | 2 |
| - Postmortem & Process Improvement Plan | - 事后总结和过程改进计划(总结过程中的问题和改进点) | 5 | 2 |
| TOTAL | 合计 | 65 | 50 |
- 依次进行了AS语言的快速上手,了解桌游规则并且先设计好了测试用例再进行代码编写,没有遇到问题。
设计
→ 📖 Q1.3(P) 请说明你们为这个判定模块设计了哪些中间量或辅助函数;如果没有额外设计,也请说明为什么认为直接实现已经足够清晰。
两个玩家分别设置了sum,cnt,maxTier,记录倾心标记总分值,倾心标记数量和最高分倾心标记,方便后面判断,让函数的逻辑更加清晰。
没有设置辅助函数,judge的过程只是简单的分支判断,目前的复杂程度没有必要抽象出一个单独的辅助函数,目前的实现方式已经足够清晰,代码可读性也够了。
→ 📖 Q1.4(I) 请说明在这样一个规则判定类模块中,如何避免“漏判”“错判”或分支顺序错误等问题。
仔细考虑每一个分支,并且考虑覆盖所有测试点
测试
→ 📖 Q1.5(P) 请说明你们设计了哪些测试用例,这些测试分别覆盖了哪一类规则或边界情况。
我们设计了如下的9个样例
// 一方分值达到 11 分而获胜
it("hanamikoji_judge", () => {
assert.equal(hanamikoji_judge([0, 0, 0, 0, -1, -1, -1], 1), -1);
});
// 一方获得至少 4 枚倾心标记而获胜
it("hanamikoji_judge", () => {
assert.equal(hanamikoji_judge([1, 1, 1, 1, 0, 0, 0], 2), 1);
});
// 前两小轮结束时尚未满足胜利条件,应返回 0
it("hanamikoji_judge", () => {
assert.equal(hanamikoji_judge([1, 1, 0, -1, -1, 0, 0], 1), 0);
});
// 第三小轮结束时,总分不同,由总分高者获胜
it("hanamikoji_judge", () => {
assert.equal(hanamikoji_judge([1, 1, 1, -1, -1, 0, 0], 3), -1);
});
// 第三小轮结束时,总分相同,由最高档位倾心标记判定胜负
it("hanamikoji_judge", () => {
assert.equal(hanamikoji_judge([1, 0, 0, -1, -1, 1, 0], 3), 1);
});
// 第三小轮结束时平局,应返回 2
it("hanamikoji_judge", () => {
assert.equal(hanamikoji_judge([1, -1, 0, 1, -1, 0, 0], 3), 2);
});
// 出现异常board输入
it("hanamikoji_judge", () => {
try {
hanamikoji_judge([0, 0, 0, 1, 1, 0], 1);
assert.fail("应抛出错误");
} catch (e) {
assert.ok(e instanceof Error);
assert.match(e.message, /Board must have 7 elements/);
}
});
// 出现异常round输入
it("hanamikoji_judge", () => {
try {
hanamikoji_judge([0, 0, 0, 1, 1, 0, 0], -1);
assert.fail("应抛出错误");
} catch (e) {
assert.ok(e instanceof Error);
assert.match(e.message, /Round must be between 1 and 3/);
}
});
it("hanamikoji_judge", () => {
try {
hanamikoji_judge([2, 2, 2, 3, 3, 4, 5], 1);
assert.fail("应抛出错误");
} catch (e) {
assert.ok(e instanceof Error);
assert.match(e.message, /Board elements must be -1, 0, or 1/);
}
});
→ 📖 Q1.6(I) 请说明你对“先写测试再实现”与“先实现再补测试”两种方式的理解。
先写测试再实现能够在一开始就能考虑所有易错遗漏的地方,而先实现再补测试是传统开发模式,让思考更加丝滑
总结
→ 📖 Q1.7(P) 请记录下目前的时间,并根据实际情况填写 附录A:基于 PSP 2.1 修改的 PSP 表格 的“实际耗时”栏目。
2026年3月29日21点50分
→ 📖 Q1.8(I) 请写下本部分的心得体会。
较简单,了解了怎样进行测试点的覆盖
Chapter.2 不祥之影
准备
→ 📖 Q2.1(P) 请记录下目前的时间。
2026年3月29日22点整
→ 📖 Q2.2(P) 请在完成任务的同时记录,并在完成任务后整理完善:
- 浏览任务要求,参照 附录A:基于 PSP 2.1 修改的 PSP 表格,估计任务预计耗时;
- 完成编程任务期间,依次做了什么(比如查阅了什么资料,随后如何进行了开发,遇到了什么问题,又通过什么方式解决);
| Personal Software Process Stages | 个人软件开发流程 | 预估耗时(分钟) | 实际耗时(分钟) |
|---|---|---|---|
| PLANNING | 计划 | 5 | 2 |
| - Estimate | - 估计这个任务需要多少时间 | 5 | 2 |
| DEVELOPMENT | 开发 | 50 | 55 |
| - Analysis & Design Spec | - 需求分析 & 生成设计规格(确定要实现什么) | 5 | 5 |
| - Technical Background | - 了解技术背景(包括学习新技术) | 5 | 5 |
| - Coding Standard | - 代码规范 | 5 | 5 |
| - Design | - 具体设计(确定怎么实现) | 5 | 5 |
| - Coding | - 具体编码 | 15 | 15 |
| - Code Review | - 代码复审 | 5 | 5 |
| - Test Design | - 测试设计(确定怎么测,比如要测试哪些情景、设计哪些种类的测试用例) | 5 | 5 |
| - Test Implement | - 测试实现(设计/生成具体的测试用例、编码实现测试) | 5 | 10 |
| REPORTING | 报告 | 15 | 13 |
| - Quality Report | - 质量报告(评估设计、实现、测试的有效性) | 5 | 3 |
| - Size Measurement | - 计算工作量 | 5 | 5 |
| - Postmortem & Process Improvement Plan | - 事后总结和过程改进计划(总结过程中的问题和改进点) | 5 | 5 |
| TOTAL | 合计 | 65 | 70 |
- 仔细阅读了规则部分,随后针对具体实现简单交流后就开展了编码工作。由于规则较为复杂,中间经历了一些反复,但是最后还是成功编辑。
代码可复用性与需求变更
→ 📖 Q2.3(P) 请说明针对该任务,你们对 🧑💻 T1 中已实现的代码进行了哪些复用和修改。
由于游戏部分和最终结果判定上逻辑和变量的耦合度较低。虽然在如board的合法性上的判断有重叠,但是我们还是选择了重新设计新代码的方式,没有对🧑💻 T1 中已实现的代码进行复用和修改。
→ 📖 Q2.4(I) 请说明在编码实现时,可以采取哪些设计思想、考虑哪些设计冗余,来提高既存代码适应需求变更的能力。
考虑将常量数据剥离,同时将每个函数的功能最小化
头脑风暴环节
→ 📖 Q2.5(P) 头脑风暴环节:
我们终于快要开始让程序玩游戏了!请尝试分析:T2 中不带 X 的操作记录比起实际对局多出了多少信息?如果加上 X,也就是失去了这部分信息的话,如何处理对小轮结束后状态的估计?
如果不含X,实际上会把真实对局中对当时不可见,但是每小轮结束后公开的信息提前给了我们。对于单个玩家来说,额外信息主要是对手的暗置1张(行动1)+暗弃2张(行动2),一共3张牌的身份。如果加上X,每个小轮结束后的状态不再是存一个具体的场面,而是存所有可能的场面(可以依据已知规则进行过滤)。
总结
→ 📖 Q2.6(P) 请记录下目前的时间,并根据实际情况填写 附录 A:基于 PSP 2.1 修改的 PSP 表格 的“实际耗时”栏目。
2026年3月29日23点整
→ 📖 Q2.7(I) 请写下本部分的心得体会。
这部分架构进行了重新设计,将各个函数功能函数最小化,让整个结构十分清晰
Chapter.3 道途之荆
准备
→ 📖 Q3.1(P) 请记录下目前的时间。
2026年4月1日19点整
→ 📖 Q3.2(P) 请在完成任务的同时记录,并在完成任务后整理完善:
- 浏览任务要求,参照 附录A:基于 PSP 2.1 修改的 PSP 表格,估计任务预计耗时;
- 完成编程任务期间,依次做了什么(比如查阅了什么资料,随后如何进行了开发,遇到了什么问题,又通过什么方式解决);
| Personal Software Process Stages | 个人软件开发流程 | 预估耗时(分钟) | 实际耗时(分钟) |
|---|---|---|---|
| PLANNING | 计划 | 10 | 10 |
| - Estimate | - 估计这个任务需要多少时间 | 10 | 10 |
| DEVELOPMENT | 开发 | 140 | 140 |
| - Analysis & Design Spec | - 需求分析 & 生成设计规格(确定要实现什么) | 10 | 10 |
| - Technical Background | - 了解技术背景(包括学习新技术) | 10 | 15 |
| - Coding Standard | - 代码规范 | 10 | 15 |
| - Design | - 具体设计(确定怎么实现) | 20 | 10 |
| - Coding | - 具体编码 | 30 | 35 |
| - Code Review | - 代码复审 | 30 | 25 |
| - Test Design | - 测试设计(确定怎么测,比如要测试哪些情景、设计哪些种类的测试用例) | 20 | 20 |
| - Test Implement | - 测试实现(设计/生成具体的测试用例、编码实现测试) | 10 | 10 |
| REPORTING | 报告 | 30 | 30 |
| - Quality Report | - 质量报告(评估设计、实现、测试的有效性) | 15 | 20 |
| - Size Measurement | - 计算工作量 | 10 | 5 |
| - Postmortem & Process Improvement Plan | - 事后总结和过程改进计划(总结过程中的问题和改进点) | 5 | 5 |
| TOTAL | 合计 | 180 | 180 |
2.仔细阅读了规则部分,查阅的资料主要在于如何找到最优决策。整体上,这一轮任务的收获是:相比单纯追求策略复杂度,更关键的是先保证协议正确与编译稳定,再在此基础上逐步优化决策质量。
头脑风暴环节
→ 📖 Q3.3(P) 头脑风暴环节:
假设提供更充裕的时间和资源,这个游戏中你能找到的最优策略有可能是什么形式的?进行调研并总结分析。你还可以在任务结束后试着实现(不计分)。
如果“时间和资源非常充裕”,最优策略的形式大概率不是一套固定规则,而是一个概率分布。因为游戏规则是不完全信息+对抗+顺序行动,所以纯贪心一定不是最优解。最优往往需要不可预测性与诱导对手误判。
需求建模和算法设计
→ 📖 Q3.4(P) 请说明针对该任务,你们采取了哪些策略来优化决策。具体而言,怎么选择行动类型?选牌如何更优?如何编程实现。
针对本任务,我们的决策优化思路不是固定出牌,而是围绕局势评估、行动调度和选牌质量三方面进行设计。
首先,在每次决策前我们会先做局势分析:结合当前倾心标记分布、双方得分差距与关键牌控制情况,判断当前阶段更适合稳健拿分还是主动争夺。这样可以避免仅根据手牌大小做局部贪心,使决策更贴近整局目标。
其次,在行动类型选择上,我们采用“可用行动集合 + 优先级”的方法。由于每种行动在小轮内只能使用一次,我们先识别当前可选动作,再根据局势压力进行排序:在安全局面下偏向稳定收益,在落后或关键回合时提高进攻性。这样做的核心理由是把有限行动资源用在最有边际价值的时点,而不是平均分配或随机使用。
再次,在同一行动内部,我们对选牌进行了针对性优化,实现了独立的选牌函数:
evaluateSecret(密约)
对每张牌计算价值分,基础分由cardScore给出,再结合局势做惩罚/修正,选综合价值最高牌。evaluateDiscard(弃牌)
扫描手牌找最低价值两张,尽量把低收益资源转化为“弃牌成本”。evaluateGift(赠予)
构造“高+中+低”组合,并根据对手需求牌调整出牌结构,目标是让对手在三选一中难以拿到最有利结果。evaluateCompetition(竞争)
先按牌值对手牌索引排序,再分成两组,在终局可切换为更激进分组,提高关键回合收益。
代码可复用性与需求变更
→ 📖 Q3.5(P) 请说明针对该任务,你们对 🧑💻 T2 中已实现的代码进行了哪些复用和修改。
在本任务中,我们对 T2 阶段的实现的计分算法予以保留复用,用于预测计算分数。
复用部分主要体现在三类基础能力上:其一,牌面表示与计分体系;其二,历史记录与动作字符串的解析思路;其三,基础的安全兜底机制。这些内容在 T3 中继续沿用,保证了与引擎协议的一致性和实现稳定性。
→ 📖 Q3.6(I) 请说明在编码实现时,可以采取哪些设计思想、考虑哪些设计冗余,来提高既存代码适应需求变更的能力。
可以考虑从整体出发,再逐步增加具体的细节,如在每种情况下你的出牌策略
软件度量
→ 📖 Q3.7(P) 请说明你们如何量度所实现的程序模块的有效性,例如:“如何说明我们的程序模块决策能力很强?”,尝试提出一些可能的定量分析方式或测试方式。
我们将程序模块的有效性量度为三类指标:正确性、稳定性、对抗强度。
第一,正确性指标用于说明“程序是否可靠可用”。主要包括:行动是否合法、程序是否会异常退出。这类指标是底线,如果这方面出错,胜率结论不具参考价值。
第二,稳定性指标用于说明“性能是否可复现”。可以在不同随机种子、不同先后手条件下重复大量对局,统计胜率均值和方差等数据;同时记录单局决策耗时分布。若同策略在不同实验批次结果波动小,说明实现稳定、泛化较好。
第三,对抗强度指标用于说明“决策能力是否强”。核心做法是对照评测。
总结
→ 📖 Q3.8(P) 请记录下目前的时间,并根据实际情况填写 附录A:基于 PSP 2.1 修改的 PSP 表格 的“实际耗时”栏目。
2026年4月1日22点10分
→ 📖 Q3.9(I) 请写下本部分的心得体会。
这部分是自己思考,利用vibe coding编写代码完成,感受是对于博弈的策略,如果说需要大量考虑细枝末节,需要大量编码,反而不如剪枝过后的代码清晰明了,虽然复杂度更高,但可读性更差
结对项目总结
结对过程回顾和反思
→ 📖 Q4.1(P) 提供两人在讨论的结对图像资料。

→ 📖 Q4.2(P) 回顾结对的过程,反思有哪些可以提升和改进的地方。
- 长时间做一人编码易导致注意力下降。可以尝试每30分钟转换一下身份的方式。
- 有不少时间花费在命名和代码细节上。可以尝试在开始编码前先统一命名规范和缩紧等细节,或是只规定函数参数的命名规范即可,非不要不关注其中的细枝末节。
- 反馈不够及时具体,尽量不说“也行”,“还可以”这类话,最好都能说明一下支持或者不支持的理由。
→ 📖 Q4.3(I) 锐评一下你的搭档!并请至少列出三个优点和一个缺点。
优点:自驱力强,热爱思考,有合作意识
缺点:pua我
对结对编程的理解
→ 📖 Q4.4(I) 说明结对编程的优缺点、你对结对编程的理解。
优点:能更全面的思考
缺点:仍然是单人的工作量,另外一人只能提供补充,并不能起到决定性作用
代码实现提交
→ 📖 Q4.5(P) 请提供你们完成代码实现的代码仓库链接。
https://github.com/aStringCat/BUAASE2026-PairProgramming-Fork

浙公网安备 33010602011771号