[P] 结对项目:花见小路

结对项目:博客问题清单

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

→ 📖 Q0.0(P) 【你可以在结对结束后补充】如果你的代码仓库包含 AIGC 的部分,列举使用的工具、模型和使用范围。若未使用则填写:本组提交的全部代码不包含AI补全或生成的部分。

使用了vscode的copilot模型,在chapter3部分中辅助完成具体算法的实现。

Chapter.0 wasm从安装到入门

引入

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

2026年3月28日13点整

调查

→ 📖 Q0.2(I) 【你可以在结对结束后另行补充。】作为本项目的调查:

请如实标注在开始项目之前对 Wasm 的熟悉程度分级,可以的话请细化具体的情况。(分别回答两人各自的情况)

I. 没有听说过;

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

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

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

I. 没有听说过;

请如实标注在开始项目之前对桌游花见小路的熟悉程度分级,可以的话请细化具体的情况。(分别回答两人各自的情况)

I. 不了解玩法和规则;

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

I. 不了解玩法和规则;

总结

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

2026年3月28日14点整

Chapter.1 七色之缨

结对过程

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

2026年3月29日21点整

→ 📖 Q1.2(P) 请在完成任务的同时记录,并在完成任务后整理完善:

  1. 浏览任务要求,参照 附录A:基于 PSP 2.1 修改的 PSP 表格,估计任务预计耗时;
  2. 完成编程任务期间,依次做了什么(例如查阅了哪些资料、如何设计判定逻辑、如何设计测试样例、遇到了什么问题、如何解决)。
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
  1. 依次进行了AS语言的快速上手,了解桌游规则并且先设计好了测试用例再进行代码编写,没有遇到问题。

设计

→ 📖 Q1.3(P) 请说明你们为这个判定模块设计了哪些中间量或辅助函数;如果没有额外设计,也请说明为什么认为直接实现已经足够清晰。

两个玩家分别设置了sum,cnt,maxTier,记录倾心标记总分值,倾心标记数量和最高分倾心标记,方便后面判断,让函数的逻辑更加清晰。

没有设置辅助函数,judge的过程只是简单的分支判断,目前的复杂程度没有必要抽象出一个单独的辅助函数,目前的实现方式已经足够清晰,代码可读性也够了。

→ 📖 Q1.4(I) 请说明在这样一个规则判定类模块中,如何避免“漏判”“错判”或分支顺序错误等问题。

  1. 先画一个流程图,对于每一个分支都做一个测试用例。
  2. 使用覆盖率测试工具,确保高覆盖率。
  3. 当编码总是无法通过测试点时,需考虑是否出现错判。

测试

→ 📖 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) 请在完成任务的同时记录,并在完成任务后整理完善:

  1. 浏览任务要求,参照 附录A:基于 PSP 2.1 修改的 PSP 表格,估计任务预计耗时;
  2. 完成编程任务期间,依次做了什么(比如查阅了什么资料,随后如何进行了开发,遇到了什么问题,又通过什么方式解决);
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
  1. 仔细阅读了规则部分,随后针对具体实现简单交流后就开展了编码工作。由于规则较为复杂,中间经历了一些反复,但是最后还是成功编辑。

代码可复用性与需求变更

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

由于游戏部分和最终结果判定上逻辑和变量的耦合度较低。虽然在如board的合法性上的判断有重叠,但是我们还是选择了重新设计新代码的方式,没有对🧑‍💻 T1 中已实现的代码进行复用和修改。

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

  1. 常量化与配置化:像 CARD_POINTS / CARD_TIER 这类数据抽成常量或配置,规则变更只需改数据而非逻辑。
  2. 纯函数优先:尽量让每一个函数无副作用,同时功能上也尽量最小化,便于后续复用和修正。

头脑风暴环节

→ 📖 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) 请写下本部分的心得体会。

这部分题意较为明确,编码方向单一。在结对编程中,很多小bug被第一时间找出来,同时一些架构设计也比独立编程更好。

Chapter.3 道途之荆

准备

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

2026年4月1日19点整

→ 📖 Q3.2(P) 请在完成任务的同时记录,并在完成任务后整理完善:

  1. 浏览任务要求,参照 附录A:基于 PSP 2.1 修改的 PSP 表格,估计任务预计耗时;
  2. 完成编程任务期间,依次做了什么(比如查阅了什么资料,随后如何进行了开发,遇到了什么问题,又通过什么方式解决);
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) 请写下本部分的心得体会。

本部分涉及对算法的思考,结对编程的重点并没有在“编程“本身,更多是在探讨如何决策。最终我们讨论出一个基于纳什均衡的思想而非单一地进行贪心策略。

结对项目总结

结对过程回顾和反思

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

2f080839e97c1c818d65b759356457b7

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

  1. 长时间做一人编码易导致注意力下降。可以尝试每30分钟转换一下身份的方式。
  2. 有不少时间花费在命名和代码细节上。可以尝试在开始编码前先统一命名规范和缩紧等细节,或是只规定函数参数的命名规范即可,非不要不关注其中的细枝末节。
  3. 反馈不够及时具体,尽量不说“也行”,“还可以”这类话,最好都能说明一下支持或者不支持的理由。

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

优点:善于沟通,风趣,思路清晰
缺点:细节把握不足

对结对编程的理解

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

优点:结对编程过程相对没有独立编程那么枯燥,同时也更容易及时发现代码中的细节问题。

缺点:对于整体效果来说,结对编程需要适应两个人的编码习惯,会降低效率。同时,事实上如果两个人分开工作能做的任务会更多(

我认为结对更适合把复杂或关键的逻辑的把控。但是在如今AI时代下,一个人可以同时控制多个AI聊天窗口,让AI辅助编写测试用例和检查代码已经是常规操作。这种情况下,结对编程似乎无法起到传统模式下的效果了

代码实现提交

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

https://github.com/aStringCat/BUAASE2026-PairProgramming-Fork

posted @ 2026-04-08 11:23  LightALm  阅读(36)  评论(0)    收藏  举报