《花见小路》与结对编程
| 项目 | 内容 |
|---|---|
| 这个作业属于哪个课程 | 2026年春季软件工程 (北京航空航天大学 - 计算机学院) |
| 这个作业的要求在哪里 | [P] 结对项目:花见小路 |
| 我在这个课程的目标是 | 学习软工 |
| 这个作业在哪个具体方面帮助我实现目标 | 学习结对 |
→ 📖 Q0.0(P) 列举仓库包含 AIGC 的部分,以及使用的工具、模型和使用范围。
我们提交的代码里包含 AIGC 的部分,主要用在自动生成 GitHub 提交信息,代码开发环境配置,仓库文档维护,以及 T3 阶段的博弈策略分析和方案讨论。具体使用方式见仓库的环境配置部分。
Chapter.0 wasm从安装到入门
引入
→ 📖 Q0.1(P) 请记录下目前的时间。
2026.3.28 10:00
调查
→ 📖 Q0.2(I) 对 Wasm 和花见小路的熟悉程度?
- Wasm:仅限于听说过相关名词;
- 花见小路:不了解玩法和规则;
总结
→ 📖 Q0.3(P) 请记录下目前的时间。
2026.3.28 12:00
Chapter.1 七色之缨
结对过程
→ 📖 Q1.1(P) 请记录下目前的时间。
2026.3.28 16:00
→ 📖 Q1.2(P) 请在完成任务的同时记录,并在完成任务后整理完善:
- 浏览任务要求,参照 附录A:基于 PSP 2.1 修改的 PSP 表格,估计任务预计耗时;
- 完成编程任务期间,依次做了什么(例如查阅了哪些资料、如何设计判定逻辑、如何设计测试样例、遇到了什么问题、如何解决)。
| Personal Software Process Stages | 个人软件开发流程 | 预估耗时(分钟) |
|---|---|---|
| PLANNING | 计划 | |
| - Estimate | - 估计这个任务需要多少时间 | 10 |
| DEVELOPMENT | 开发 | |
| - Analysis & Design Spec | - 需求分析 & 生成设计规格(确定要实现什么) | 10 |
| - Technical Background | - 了解技术背景(包括学习新技术) | 15 |
| - Coding Standard | - 代码规范 | 5 |
| - Design | - 具体设计(确定怎么实现) | 15 |
| - Coding | - 具体编码 | 60 |
| - Code Review | - 代码复审 | 20 |
| - Test Design | - 测试设计(确定怎么测,比如要测试哪些情景、设计哪些种类的测试用例) | 5 |
| - Test Implement | - 测试实现(设计/生成具体的测试用例、编码实现测试) | 15 |
| REPORTING | 报告 | |
| - Quality Report | - 质量报告(评估设计、实现、测试的有效性) | 10 |
| - Size Measurement | - 计算工作量 | 5 |
| - Postmortem & Process Improvement Plan | - 事后总结和过程改进计划(总结过程中的问题和改进点) | 10 |
| TOTAL | 合计 | 180 |
- 通读任务要求和评分标准后,我们在 Go 和 Rust 两种实现方案之间做过比较。二者各有优缺点,但考虑到 Rust 语法本身会增加实现复杂度、拖慢作业进度,最后还是决定用 Go。
- 在 https://learnxinyminutes.com/zh-cn/go/ 学习 Go 语法。
- 实现判定主函数时采用“先判立即胜利,再判轮次,最后判第三轮细则”的固定顺序,减少漏判和分支顺序错误。
- 对于测试样例,除了任务要求的 6 种情况,我们还设计了
TestBoardSummary()来验证中间变量Summary的正确性。
设计
→ 📖 Q1.3(P) 请说明你们为这个判定模块设计了哪些中间量或辅助函数;如果没有额外设计,也请说明为什么认为直接实现已经足够清晰。
我们为这个判定模块设计了若干中间量和辅助函数。
这里最重要的中间量是 Summary,它把原始棋盘状态归纳成双方各自的 Score、Markers 和 BestTier。
辅助函数方面,我们先用 Board.summary() 和 addGeisha() 完成从棋盘到统计结果的转换,再用 resolveImmediateWin() 和 resolveFinalRound() 分别处理立即胜利条件与第三轮最终判定。对于第三轮平分时的比较,我们还额外抽象了 Tier 枚举,避免把 G、F、DE、ABC 的优先级直接写成难维护的分支。
这些中间量和辅助函数让代码结构和题目规则基本是一一对应的,读起来更清楚,测试也更方便。
→ 📖 Q1.4(I) 请说明在这样一个规则判定类模块中,如何避免“漏判”“错判”或分支顺序错误等问题。
我们采用优先级递减的短路分层结构,高优先级规则先判、命中即返回,确保后续分支不会干扰已确定的结果;对于对称比较(如双方得分、标记数),严格成对书写互斥条件(A > B 与 A < B 相邻排列),使比较逻辑与书写顺序解耦;每条判定链末尾必须设置兜底默认返回值(如 Draw 或 Continue),穷尽所有状态空间不留 fall-through 空隙;同时将阈值等魔法数字提取为语义化常量以减少笔误风险,并辅以覆盖边界值和平局场景的单元测试来验证各分支的完备性与正确性。
测试
→ 📖 Q1.5(P) 请说明你们设计了哪些测试用例,这些测试分别覆盖了哪一类规则或边界情况。
-
TestBoardSummary
验证中间量Summary的正确性。同时检查我方与对手的Score、Markers、BestTier三个统计值是否按预期汇总,降低主判定函数因统计错误导致漏判/错判的风险。 -
TestScoreReach11
覆盖规则:一方分值达到 11 分立即获胜。
覆盖边界:使用“恰好等于 11 分”的边界值(A+F+G=11),验证“达到或超过 11 分”中的达到条件。 -
TestMarkersReach4
覆盖规则:一方获得至少 4 枚倾心标记获胜。
覆盖边界:使用“恰好 4 枚标记”的边界值,且对手未达 11 分。 -
TestContinueRound3
覆盖规则:前两小轮结束时若未满足胜利条件,返回继续(0)。
覆盖边界:将round设为第 2 轮,并构造双方都不满足立即胜利的条件,验证不会误判为胜负。 -
TestRound3ScoreHigherWins
覆盖规则:第三小轮结束时,若总分不同,由总分高者获胜。
覆盖边界:round设为第 3 轮,且双方分差较小,验证第三轮按总分比较生效。 -
TestRound3SameScoreCompareTier
覆盖规则:第三小轮结束时总分相同,按最高档位倾心标记判定胜负。
覆盖边界:构造双方同分(6 : 6),我方最高档位为 F、对方为 D/E,验证档位比较顺序正确。 -
TestRound3Draw
覆盖规则:第三小轮结束时若总分和最高档位都无法区分,判平局(2)。
覆盖边界:构造双方同分(5 : 5)且最高档位同为 D/E,验证是否判为平局。
→ 📖 Q1.6(I) 请说明你对“先写测试再实现”与“先实现再补测试”两种方式的理解。
两种方式都有适用场景。规则明确、接口稳定时,先写测试再实现更合适,因为它能先把输入输出和边界条件固定下来,也更容易早点暴露设计问题。需求还在摸索、需要先快速验证数据结构或流程时,先实现再补测试会更顺手;但这样也更容易被已有实现“带着走”,边界条件可能漏掉。结合这次 T1,判定规则本身比较明确,所以更适合先把关键测试列出来,再逐步把实现补齐。
总结
→ 📖 Q1.7(P) 请记录下目前的时间,并根据实际情况填写 附录A:基于 PSP 2.1 修改的 PSP 表格 的“实际耗时”栏目。
2026.3.29 21:30
| Personal Software Process Stages | 个人软件开发流程 | 预估耗时(分钟) | 实际耗时(分钟) |
|---|---|---|---|
| PLANNING | 计划 | ||
| - Estimate | - 估计这个任务需要多少时间 | 10 | 10 |
| DEVELOPMENT | 开发 | ||
| - Analysis & Design Spec | - 需求分析 & 生成设计规格(确定要实现什么) | 10 | 15 |
| - Technical Background | - 了解技术背景(包括学习新技术) | 15 | 8 |
| - Coding Standard | - 代码规范 | 5 | 3 |
| - Design | - 具体设计(确定怎么实现) | 15 | 5 |
| - Coding | - 具体编码 | 60 | 49 |
| - Code Review | - 代码复审 | 20 | 22 |
| - Test Design | - 测试设计(确定怎么测,比如要测试哪些情景、设计哪些种类的测试用例) | 5 | 7 |
| - Test Implement | - 测试实现(设计/生成具体的测试用例、编码实现测试) | 15 | 10 |
| REPORTING | 报告 | ||
| - Quality Report | - 质量报告(评估设计、实现、测试的有效性) | 10 | 10 |
| - Size Measurement | - 计算工作量 | 5 | 3 |
| - Postmortem & Process Improvement Plan | - 事后总结和过程改进计划(总结过程中的问题和改进点) | 10 | 5 |
| TOTAL | 合计 | 180 | 147 |
→ 📖 Q1.8(I) 请写下本部分的心得体会。
用 Go 写真的挺舒服的
Chapter.2 不祥之影
准备
→ 📖 Q2.1(P) 请记录下目前的时间。
2026.3.30 19:14
→ 📖 Q2.2(P) 请在完成任务的同时记录,并在完成任务后整理完善:
- 浏览任务要求,参照 附录A:基于 PSP 2.1 修改的 PSP 表格,估计任务预计耗时;
- 完成编程任务期间,依次做了什么(比如查阅了什么资料,随后如何进行了开发,遇到了什么问题,又通过什么方式解决);
| Personal Software Process Stages | 个人软件开发流程 | 预估耗时(分钟) |
|---|---|---|
| PLANNING | 计划 | |
| - Estimate | - 估计这个任务需要多少时间 | 10 |
| DEVELOPMENT | 开发 | |
| - Analysis & Design Spec | - 需求分析 & 生成设计规格(确定要实现什么) | 20 |
| - Technical Background | - 了解技术背景(包括学习新技术) | 0 |
| - Coding Standard | - 代码规范 | 0 |
| - Design | - 具体设计(确定怎么实现) | 10 |
| - Coding | - 具体编码 | 120 |
| - Code Review | - 代码复审 | 30 |
| - Test Design | - 测试设计(确定怎么测,比如要测试哪些情景、设计哪些种类的测试用例) | 0 |
| - Test Implement | - 测试实现(设计/生成具体的测试用例、编码实现测试) | 0 |
| REPORTING | 报告 | |
| - Quality Report | - 质量报告(评估设计、实现、测试的有效性) | 10 |
| - Size Measurement | - 计算工作量 | 5 |
| - Postmortem & Process Improvement Plan | - 事后总结和过程改进计划(总结过程中的问题和改进点) | 10 |
| TOTAL | 合计 | 215 |
- 将规则拆成可组合的数据结构:
ActionKind、Player、Geisha、CardCounts、CardSet、ActionContent,把“动作解析”和“状态回放”实现了解耦。 - 在实现 T2 时,“赠予/竞争的响应匹配”是 T2 里最容易出错的一段,它同时涉及了文本表示、牌的多重集合语义、以及后续状态回放的一致性。以竞争为例,它除了“选中的内容”之外还带有“组别”语义:规则规定前两张是左组、后两张是右组,所以
parseCompeteAction()先按位置分组,再把response也转成CardCounts,通过resolveGroupSelection()比较计数而不是比较字符顺序,这就解决了 AB 与 BA 文本不同但语义相同的问题,也能正确处理 DD 这类重复牌组。
代码可复用性与需求变更
→ 📖 Q2.3(P) 请说明针对该任务,你们对 🧑💻 T1 中已实现的代码进行了哪些复用和修改。
复用主要集中在三块。第一块是基础建模:Owner、Board、Geisha 以及按 A-G 建模的 score() / cardCount() 这些定义都直接延续了 T1。第二块是输入校验的写法:先把原始输入转成内部结构,再统一做长度和值域检查。第三块是代码组织方式:T1 是先把 board 汇总后判胜负,T2 则是先把 history 解析成结构化动作,再回放到当前场面上。
在这个基础上,T2 新增了 CardCounts、CardSet、History、Action、ActionContent 等数据结构,把四种动作的解析和结算分别建模出来;同时把 T1 的“直接判定胜负”替换成了“根据完整一轮记录回放双方区域并更新 board”的业务逻辑。
→ 📖 Q2.4(I) 请说明在编码实现时,可以采取哪些设计思想、考虑哪些设计冗余,来提高既存代码适应需求变更的能力。
提高既存代码适应需求变更能力的关键,是把“稳定的概念”和“易变的规则”拆开。像 Geisha、Board、CardCounts 这类基础数据结构尽量保持稳定;四种动作各自的解析、耗牌和结算则放到独立实现里,由 ActionContent 统一抽象。这样以后即使输入格式或回放规则变化,也优先改某一类动作的解析或 apply(),而不是把所有逻辑揉在一个大函数里。
另外,像 CardSet 同时表示已知牌和未知牌,这种带一点前瞻性的冗余也有价值:T2 里虽然基本用不到 X,但数据结构先留好,后续支持不完整信息时就不需要推倒重来。
头脑风暴环节
→ 📖 Q2.5(P) 头脑风暴环节:我们终于快要开始让程序玩游戏了!请尝试分析:T2 中不带 X 的操作记录比起实际对局多出了多少信息?如果加上 X,也就是失去了这部分信息的话,如何处理对小轮结束后状态的估计?
- T2 不带
X的完整历史,多出来的主要是双方1/2动作里原本对对手不可见的牌面,也就是密约暗置和取舍弃牌的具体内容。等于这一小轮里已经用掉的牌都被公开了。 - 如果把这些位置改成
X,就不再是确定性回放,而是带隐藏信息的约束推断。此时只能根据已知的history、起始board、整副牌的数量上限,以及各动作消耗的张数,列出所有满足这些约束的未知牌分配方案。 - 对每个可行方案,都可以像 T2 一样回放一遍,得到一种可能的小轮结束状态;这时输出不再是唯一状态,而更像这些状态的分布,或者其中概率最大的状态和相应的期望估计。
- 如果可行方案太多,就不能全枚举,只能改用随机采样:采满足约束的隐藏牌分配,再统计各类结束状态出现的频率。
总结
→ 📖 Q2.6(P) 请记录下目前的时间,并根据实际情况填写 附录 A:基于 PSP 2.1 修改的 PSP 表格 的“实际耗时”栏目。
2026.3.31 23:30
| Personal Software Process Stages | 个人软件开发流程 | 预估耗时(分钟) | 实际耗时(分钟) |
|---|---|---|---|
| PLANNING | 计划 | ||
| - Estimate | - 估计这个任务需要多少时间 | 10 | 8 |
| DEVELOPMENT | 开发 | ||
| - Analysis & Design Spec | - 需求分析 & 生成设计规格(确定要实现什么) | 20 | 15 |
| - Technical Background | - 了解技术背景(包括学习新技术) | 0 | 0 |
| - Coding Standard | - 代码规范 | 0 | 0 |
| - Design | - 具体设计(确定怎么实现) | 10 | 5 |
| - Coding | - 具体编码 | 120 | 159 |
| - Code Review | - 代码复审 | 30 | 82 |
| - Test Design | - 测试设计(确定怎么测,比如要测试哪些情景、设计哪些种类的测试用例) | 0 | 0 |
| - Test Implement | - 测试实现(设计/生成具体的测试用例、编码实现测试) | 0 | 0 |
| REPORTING | 报告 | ||
| - Quality Report | - 质量报告(评估设计、实现、测试的有效性) | 10 | 10 |
| - Size Measurement | - 计算工作量 | 5 | 3 |
| - Postmortem & Process Improvement Plan | - 事后总结和过程改进计划(总结过程中的问题和改进点) | 10 | 5 |
| TOTAL | 合计 | 215 | 287 |
→ 📖 Q2.7(I) 请写下本部分的心得体会。
队友作为主驾先完成了一版,我觉得代码架构和风格上还可以再挑刺,然后抢过方向盘开始重构……
Chapter.3 道途之荆
准备
→ 📖 Q3.1(P) 请记录下目前的时间。
2026.4.9 15:03
→ 📖 Q3.2(P) 请在完成任务的同时记录,并在完成任务后整理完善:
- 浏览任务要求,参照 附录A:基于 PSP 2.1 修改的 PSP 表格,估计任务预计耗时;
- 完成编程任务期间,依次做了什么(比如查阅了什么资料,随后如何进行了开发,遇到了什么问题,又通过什么方式解决);
| Personal Software Process Stages | 个人软件开发流程 | 预估耗时(分钟) |
|---|---|---|
| PLANNING | 计划 | |
| - Estimate | - 估计这个任务需要多少时间 | 5 |
| DEVELOPMENT | 开发 | |
| - Analysis & Design Spec | - 需求分析 & 生成设计规格(确定要实现什么) | 10 |
| - Technical Background | - 了解技术背景(包括学习新技术) | 0 |
| - Coding Standard | - 代码规范 | 0 |
| - Design | - 具体设计(确定怎么实现) | 10 |
| - Coding | - 具体编码 | 240 |
| - Code Review | - 代码复审 | 30 |
| - Test Design | - 测试设计(确定怎么测,比如要测试哪些情景、设计哪些种类的测试用例) | 5 |
| - Test Implement | - 测试实现(设计/生成具体的测试用例、编码实现测试) | 10 |
| REPORTING | 报告 | |
| - Quality Report | - 质量报告(评估设计、实现、测试的有效性) | 10 |
| - Size Measurement | - 计算工作量 | 5 |
| - Postmortem & Process Improvement Plan | - 事后总结和过程改进计划(总结过程中的问题和改进点) | 10 |
| TOTAL | 合计 | 335 |
我们在 T3 遇到的主要问题是:输入只给了当前小轮的 history、cards 和 board,没有直接告诉我们现在是第几轮,而第三轮和前两轮的决胜规则是不一样的,所以很难在行动函数里直接做整局胜负模拟。
后来我们不再把“先判断轮次”当成前提,而是先保证当前状态推断正确、下一步动作合法。具体做法是先解析不完整历史,再回放两种先手假设,用行动使用记录和手牌数量去推断当前阶段。只有一种回放结果能和当前视角、自身手牌同时对上,后面的合法动作生成和选择就都基于这个状态来做。这样模块不需要直接依赖轮次,第三轮与前两轮的最终胜负结算仍交给外部对局程序按完整规则处理,我们这里只处理眼前这一步。
策略方面,一开始确实想直接用蒙特卡洛解决,但实现下来发现效率太低;最后只保留了一轮内的蒙特卡洛推演,在决策质量和时间之间做平衡。
头脑风暴环节
→ 📖 Q3.3(P) 头脑风暴环节:假设提供更充裕的时间和资源,这个游戏中你能找到的最优策略有可能是什么形式的?进行调研并总结分析。你还可以在任务结束后试着实现(不计分)。
我们查找了不完全信息博弈里常见的几种方法,主要是 CFR、CFR+、Deep CFR 和 NFSP。这些方法大体都在做同一件事:让策略逐步接近纳什均衡,并在对局过程中根据新信息修正当前决策。
如果把它们放到 T3 里看,在资源和时间都很充裕的情况下,最优策略大概会是一张覆盖全部信息集的策略映射。预计算阶段先把三轮完整规则建成博弈树,通过大量自博弈把每个信息集下的行动分布算出来;决策阶段再结合当前 history、手牌和 board 做后验更新,把不可能的对手手牌情况排除,然后在当前局面附近做一次小范围重新计算,再决定这一手怎么出。这种做法更稳,对手水平越高,优势也越容易体现出来,因为它不容易因为某一局的局部波动偏离整体最优太多。
按对局阶段看,这个策略在不同阶段的重心也会变化。前段更重视信息价值和行动顺序管理,中段更重视高分艺伎归属和对手可选动作,末段更重视阈值判断。还有一个看起来有点反直觉、但经常有效的点是,有些局面下主动放掉眼前一小口收益,能换来后两手更大的主动权,这在长期双循环测试里通常更有效。
需求建模和算法设计
→ 📖 Q3.4(P) 请说明针对该任务,你们采取了哪些策略来优化决策。具体而言,怎么选择行动类型?选牌如何更优?如何编程实现。
先处理响应对方动作的情况:
- 如果当前是在响应赠予,我们把可选的每一张都当成候选,分别做后续模拟,返回估值最高的
-X。 - 如果当前是在响应竞争,我们把两组都当成候选,同样各自做后续模拟,返回估值更高的那组。
再处理我方主动出牌的情况:
我们先从本轮还没用过的 1/2/3/4 动作里,枚举出所有合法出牌组合。然后对候选动作做蒙特卡洛估值:先把当前已知牌固定住,再把未知牌随机分配到对手手牌、对手密约暗牌、未知弃牌、暗置移除位和剩余牌堆。对于根节点候选较多的情况,我们会先对全部候选做少量预采样,再保留估值更好的部分候选继续深挖,把更多时间集中在更有希望的动作上。在 rollout 阶段,我们不再每一步都完整枚举所有合法行动后再随机挑选,而是直接随机生成一个合法行动,以降低单次模拟成本;同时,当剩余动作已经很少时,不再继续随机,而是直接把这一小轮精确搜索到结算。最后根据结算后的 board 打分,并比较各候选动作的平均得分。
我们的评分是:
base = 5000 * (我方总分 - 对手总分) + 200 * (我方标记数 - 对手标记数) + 档位偏置
其中档位偏置会额外看 G/F/DE/ABC 的归属。
如果结算后我方触发立即胜利条件,就在 base 上加一个大额奖励;如果结算后对手触发立即胜利,就在 base 上加一个大额惩罚。
最终选择规则是:平均分最高的动作优先;如果分数打平,就按动作编码字典序选最小,保证输出稳定。另外我们有决策时间预算,时间快不够时就停止继续采样,直接返回当前最优动作。
代码可复用性与需求变更
→ 📖 Q3.5(P) 请说明针对该任务,你们对 🧑💻 T2 中已实现的代码进行了哪些复用和修改。
艺伎、标记归属、牌计数这些定义基本一脉相承,Geisha、Owner、CardCounts、CardSet 在 const.go 和 struct.go 里都继续沿用,解析动作的写法也延续了 T2 的思路,splitActionBody、parseCardSet、parseGeisha、赠予/竞争的响应合法性判断也都迁移到了 T3 中。
T2 的目标是根据完整一轮历史还原结算状态,而 T3 的目标是当前轮次给出下一步行动,所以目标从结算变成了状态推断、合法动作生成和出牌策略。因此,我们在 T3 新增了 state.go 来推断当前是谁行动、是否处在响应阶段、以及历史到底对应哪种先后手,同时新增了 move.go 枚举所有合法出牌。
另外,输入从 T2 的固定 8 条完整记录,变成 T3 的任意长度历史记录和当前手牌,所以 parse.go 允许最后一条动作尚未响应,也允许出现 X 并保留未知信息。
→ 📖 Q3.6(I) 请说明在编码实现时,可以采取哪些设计思想、考虑哪些设计冗余,来提高既存代码适应需求变更的能力。
我在 T3 里做了一次相反方向的权衡:T2 用 ActionContent 把四类动作拆成不同实现,扩展性更好;但 T3 只有固定的 4 种动作,而且状态推断更依赖统一访问字段,所以把这些字段收回到 Action 中,再用 Kind + switch 处理。
我的理解是,提高适应变更能力不等于一味增加抽象,而是要把可能变化的地方单独隔离:如果动作种类还可能继续扩展,就保留接口;如果规则集合已经比较稳定,就可以适当压平模型,减少样板代码。另外,像 Board、CardCounts、CardSet 这类底层数据结构保持稳定,也能让解析、状态推断和策略层各自调整时不至于连锁改动。
软件度量
→ 📖 Q3.7(P) 请说明你们如何量度所实现的程序模块的有效性,例如:“如何说明我们的程序模块决策能力很强?”,尝试提出一些可能的定量分析方式或测试方式。
衡量这个模块,我们主要看两件事:在评测约束下会不会出问题,以及长期对局里能不能稳定赢。
第一部分是工程稳定性,因为 T3 有时限和异常判负。我们会记录每一步决策耗时的均值、P95、P99,外加超时率、非法动作率、异常退出率。一个策略就算理论上不错,但只要超时率高或者偶发非法动作,实战成绩就会被直接拉垮。
第二部分是对局结果。我们按课程的双循环思路自己先做小联赛,用固定随机种子批量生成三轮牌堆,让每个对手都打先手和后手两组,统计总胜率、净胜场、平局率,同时拆开看先手胜率和后手胜率,避免被先后手差异误导。为了说明决策能力强不是偶然,我们会拿随机合法策略、简单贪心策略、以及上一版策略当基线来比较胜率,并且每组至少跑几百到上千局,再给一个 95% 置信区间;如果区间下界仍明显高于基线,才算胜率有所提升。
所以这里说的有效性,就是结果和稳定性同时达标,也就是在时限内保持接近 0 的超时与异常,同时胜率仍明显领先基线。
另外我们还会补一组针对性的场景测试,比如只抽取“需要响应赠予/竞争”“最后一两手就可能分胜负”“信息不完整(含 X)”这些局面单独回放,统计关键决策正确率。这样不仅能看出它总体赢不赢,也能看出它到底强在什么地方、弱在什么地方,后续优化也更有方向。
总结
→ 📖 Q3.8(P) 请记录下目前的时间,并根据实际情况填写 附录A:基于 PSP 2.1 修改的 PSP 表格 的“实际耗时”栏目。
2026.4.11 21:00
| Personal Software Process Stages | 个人软件开发流程 | 预估耗时(分钟) | 实际耗时(分钟) |
|---|---|---|---|
| PLANNING | 计划 | ||
| - Estimate | - 估计这个任务需要多少时间 | 5 | 3 |
| DEVELOPMENT | 开发 | ||
| - Analysis & Design Spec | - 需求分析 & 生成设计规格(确定要实现什么) | 10 | 8 |
| - Technical Background | - 了解技术背景(包括学习新技术) | 0 | 0 |
| - Coding Standard | - 代码规范 | 0 | 0 |
| - Design | - 具体设计(确定怎么实现) | 10 | 15 |
| - Coding | - 具体编码 | 240 | 367 |
| - Code Review | - 代码复审 | 30 | 22 |
| - Test Design | - 测试设计(确定怎么测,比如要测试哪些情景、设计哪些种类的测试用例) | 5 | 2 |
| - Test Implement | - 测试实现(设计/生成具体的测试用例、编码实现测试) | 10 | 11 |
| REPORTING | 报告 | ||
| - Quality Report | - 质量报告(评估设计、实现、测试的有效性) | 10 | 16 |
| - Size Measurement | - 计算工作量 | 5 | 3 |
| - Postmortem & Process Improvement Plan | - 事后总结和过程改进计划(总结过程中的问题和改进点) | 10 | 5 |
| TOTAL | 合计 | 335 | 452 |
→ 📖 Q3.9(I) 请写下本部分的心得体会。
T3给的信息实在是太少了,让决策视角只能局限于一个小轮之中;不过再给多点信息蒙特卡洛也要处理不过来了(
结对项目总结
结对过程回顾和反思
→ 📖 Q4.1(P) 提供两人在讨论的结对图像资料。

→ 📖 Q4.2(P) 回顾结对的过程,反思有哪些可以提升和改进的地方。
这次结对里,分工和节奏都还算清楚:一人主写代码,另一人同步做测试、规则核对和样例推演,遇到关键问题再一起复盘。这样在 T1、T2 阶段效率很高,但也暴露出一个问题:前期我们把“写得动”放在了“先定义统一策略框架”前面,等到 T3 又想把框架代码补完整,于是花了不少时间搭框架。
→ 📖 Q4.3(I) 锐评一下你的搭档!并请至少列出三个优点和一个缺点。
-
行动力超高!说什么时候写完就什么时候写完!
-
非常宽容!能接纳我的拖延症的毛病!而且不 Push!
- 惭愧死我了
-
很有学习和适应的能力,我说要用 Go 写,她没学过但也能接受,零基础照着 T1 写的 T2 代码却是很清晰的!
- 这么来看是很勇敢而且很有探索精神的!
-
博客的神!热门阅读目前第一还是她的 I.2!
- 这方面帮我扫了不少的尾……
-
游戏规则这块她理得也比我清楚!这极大加快了我们上手的速度!
-
地理位置优势!工位在一块就有利于结对编程!
-
会讲广东话!我不会讲……
-
多列几个优点能不能少列一个缺点……
对结对编程的理解
→ 📖 Q4.4(I) 说明结对编程的优缺点、你对结对编程的理解。
优点特别是在一块做 Code Review 的时候,效率和正确性能够高很多;缺点就是实际执行力不强,而且耗费 PD。
AI 时代也可以多试试人与 AI 的结对编程,甚至 AI 与 AI 的结对编程。传统结对编程的问题之一就是人力成本高,但有 AI 参与之后,这部分压力会小一些;而结对编程在复核、补漏和推进上的优势,反而更容易发挥出来。
代码实现提交
→ 📖 Q4.5(P) 请提供你们完成代码实现的代码仓库链接。
https://github.com/Rosalind-savona/BUAA-2026-SE-PairProgramming-public
浙公网安备 33010602011771号