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

项目 内容
这个作业属于哪个课程 2026春季软件工程
这个作业的要求在哪里 结对项目:花见小路
我在这个课程的目标是 学习到软件工程中的各种最佳实践,然后实际运用到学习和未来的工作中
这个作业在哪个具体方面帮助我实现目标 学习结对编程相关知识并通过实践感受结对编程利弊

结对项目:博客问题清单

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

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

Chapter.0 wasm从安装到入门

引入

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

2026.4.3 14:00

调查

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

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

I. 没有听说过;✅️

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

I. 不了解玩法和规则;✅️

总结

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

2026.4.3 14:36

Chapter.1 七色之缨

结对过程

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

2026.4.3 14:38

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

  1. 浏览任务要求,参照 附录A:基于 PSP 2.1 修改的 PSP 表格,估计任务预计耗时;
Personal Software Process Stages 个人软件开发流程 预估耗时(分钟) 实际耗时(分钟)
PLANNING
- Estimate - 估计这个任务需要多少时间 15 2
DEVELOPMENT
- Analysis & Design Spec - 需求分析 & 生成设计规格(确定要实现什么) 60 5
- Technical Background - 了解技术背景(包括学习新技术) 60 4
- Coding Standard - 代码规范 15 1
- Design - 具体设计(确定怎么实现) 90 6
- Coding - 具体编码 300 8
- Code Review - 代码复审 45 3
- Test Design - 测试设计(确定怎么测,比如要测试哪些情景、设计哪些种类的测试用例) 30 3
- Test Implement - 测试实现(设计/生成具体的测试用例、编码实现测试) 30 2
REPORTING
- Quality Report - 质量报告(评估设计、实现、测试的有效性) 20 1
- Size Measurement - 计算工作量 15 0
- Postmortem & Process Improvement Plan - 事后总结和过程改进计划(总结过程中的问题和改进点) 25 0
TOTAL 705 35
  1. 完成编程任务期间,依次做了什么(例如查阅了哪些资料、如何设计判定逻辑、如何设计测试样例、遇到了什么问题、如何解决)。

先读题并整理胜负判定顺序,再把规则拆成计分、计数、档位比较几个部分实现。编码后先用题目样例测,再补边界测试。中间主要问题是第三轮平局细分容易写乱,最后靠拆辅助函数和补测试校正。

设计

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

我们设计了4个辅助函数:

函数 职责 设计理由
getOwnedScore 计算指定方拥有的倾心标记总分 将"按角色分值累加"的逻辑独立封装,避免主函数中出现重复计算代码
getOwnedCount 计算指定方拥有的倾心标记数量 独立封装计数逻辑,与计分逻辑解耦
cmpTier 比较某一分数档位内双方的归属情况 处理第三小轮中同档位多角色(D/E、A/B/C)的平局细分逻辑
cmpHighestTier 按优先级顺序比较最高档位 封装档位优先级顺序(G > F > D/E > A/B/C),主函数只需调用一次

这样的设计满足单一职责原则,即每个函数只做一件事儿;能够消除重复,计分/计数逻辑在"立即胜利条件"和"第三小轮判定"中都需要,提取后避免代码重复;规则映射直观,cmpHighestTier 中的 if 顺序直接对应题目优先级(G>F>D/E>A/B/C),可读性强;主函数流程清晰,hanamikoji_judge 按"立即胜利条件 → 轮次判断 → 第三小轮细分"的顺序展开,分支结构扁平。

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

我觉得关键是先把规则顺序写清楚,再按顺序实现。像这题就先判 >=11,再判 >=4枚,最后才处理第三轮细分,不能混着写。代码里把计分、计数、档位比较拆开,也更不容易漏情况。最后再用边界测试兜住。

测试

→ 📖 Q1.5(P) 请说明你们设计了哪些测试用例,这些测试分别覆盖了哪一类规则或边界情况。

我们一共设计了6个测试样例:

用例 名称 覆盖规则/边界情况
1 score threshold wins immediately 立即胜利条件①:一方总分≥11分(己方A+B+C+G=2+2+2+5=11,第1小轮立即获胜)
2 four markers win immediately 立即胜利条件②:一方获得≥4枚标记且对方未达11分(对方4枚A/B/C/D,第2小轮)
3 round two continues when no win condition is met 继续游戏:第1/2小轮未满足任何胜利条件时返回0(双方各2枚,均未达4枚或11分)
4 round three compares total score first 第三小轮判定①:总分比较(己方A+E=2+3=5,对方F=4,己方总分高获胜)
5 round three breaks score tie by highest tier 第三小轮判定②:总分相同,比较最高档位(己方有F=4分档,对方最高D/E=3分档,己方胜)
6 round three returns draw when highest non-empty tier is shared 第三小轮判定③:平局情况(双方各2枚,总分相同,最高非空档位D/E中双方都有,返回2)

完整性对应如下:

规则类别 覆盖状态
立即胜利条件①(≥11分) ✅ 用例1
立即胜利条件②(≥4枚且对方<11) ✅ 用例2
第1/2小轮继续游戏 ✅ 用例3
第三小轮总分比较 ✅ 用例4
第三小轮最高档位比较 ✅ 用例5
第三小轮平局 ✅ 用例6

随后又补充12个测试样例:

用例 名称 覆盖规则/边界情况
1 over 11 points wins 超过11分获胜(12分场景,验证≥11分条件)
2 exactly 4 markers with 9 points 恰好4枚且总分<11获胜(A+B+C+D=9分,验证4枚条件独立于11分条件)
3 5 markers wins 超过4枚获胜(对方5枚,验证数量条件不严格等于4)
4 opponent 11 points 对方11分获胜(验证-1返回值,双方胜负对称性)
5 all neutral round 1 全中立初始状态第1小轮继续(边界:零和状态,游戏未开始)
6 all neutral round 3 draw 全中立第3小轮平局(边界:零和状态持续到终局)
7 round 3 score diff 第3小轮总分不同(基础:总分优先判定胜负)
8 round 3 A/B/C tier draw 第3小轮A/B/C档位平局(边界:同档位内无法区分,最终平局)
9 0 vs 3 markers round 2 己方0枚对方3枚第2小轮继续(边界:极端不均衡但未达胜利条件)
10 all 7 markers 单方全拿7枚(极端:满分21分,验证立即胜利条件触发)
11 round 3 F tier wins 第3小轮F档位决胜(档位优先级:F > D/E,总分相同时高档位胜)
12 3 markers round 1 3枚标记第1小轮继续(边界:接近4枚但未达条件,轮次继续)

完整性如下:

规则维度 覆盖情况
立即胜利条件(≥11分) 用例1、4、10
立即胜利条件(≥4枚且对方<11) 用例2、3、12
轮次继续(round 1/2未达标) 用例5、9、12
第3小轮总分比较 用例7
第3小轮档位比较 用例11
第3小轮平局 用例6、8
边界值(恰好/超过/不足) 用例1、2、3、12
极端状态(全拿/全空) 用例5、6、10
双方对称性(1/-1返回值) 用例3、4

→ 📖 Q1.6(I) 请说明你对“先写测试再实现”与“先实现再补测试”两种方式的理解。

先写测试更适合这种规则明确的题,能先把判定标准卡死,写的时候不容易跑偏。先实现再补测试也有用,适合一开始还没完全想清楚的时候,先把主流程搭出来再查漏补缺。我们这次更像是先实现,再靠测试补边界。

总结

→ 📖 Q1.7(P) 请记录下目前的时间,并根据实际情况填写 附录A:基于 PSP 2.1 修改的 PSP 表格 的“实际耗时”栏目。

15:13

→ 📖 Q1.8(I) 请写下本部分的心得体会。

这一部分看起来简单,实际容易错在细节,尤其是第三轮的比较顺序。做完之后我感觉,把规则拆小、把测试补全,比一开始追求一口气写完更重要。

Chapter.2 不祥之影

准备

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

2026-04-04 23:08

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

  1. 浏览任务要求,参照 附录A:基于 PSP 2.1 修改的 PSP 表格,估计任务预计耗时;
  2. 完成编程任务期间,依次做了什么(比如查阅了什么资料,随后如何进行了开发,遇到了什么问题,又通过什么方式解决);

预计耗时如下:

Personal Software Process Stages 个人软件开发流程 预估耗时(分钟) 实际耗时(分钟)
PLANNING 计划
- Estimate - 估计这个任务需要多少时间 5 3
DEVELOPMENT 开发
- Analysis & Design Spec - 需求分析 & 生成设计规格(确定要实现什么) 10 6
- Technical Background - 了解技术背景(包括学习新技术) 10 7
- Coding Standard - 代码规范 5 2
- Design - 具体设计(确定怎么实现) 10 8
- Coding - 具体编码 20 18
- Code Review - 代码复审 10 6
- Test Design - 测试设计(确定怎么测,比如要测试哪些情景、设计哪些种类的测试用例) 10 6
- Test Implement - 测试实现(设计/生成具体的测试用例、编码实现测试) 10 7
REPORTING 报告
- Quality Report - 质量报告(评估设计、实现、测试的有效性) 5 3
- Size Measurement - 计算工作量 1 1
- Postmortem & Process Improvement Plan - 事后总结和过程改进计划(总结过程中的问题和改进点) 2 1
TOTAL 合计 98 68

完成任务期间的过程记录如下:

  • 首先明确 calc_current_state(history, board) 的输入输出形式,同时理解四条规则
  • 实现时将问题拆成:字符串分词、单个行动解析、赠予/竞争的选择处理、场面牌计数更新、最后的 board 结算
  • 初版实现完成后,先通过仓库自带样例测试,然后编写更多更强的样例,包括:空历史、重复空格、全密约、全取舍、重复牌赠予、竞争组选取、顺序无关匹配、旧标记保留等边界情况。

代码可复用性与需求变更

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

相较于T1,T2增加了如下内容:

  1. 新增了对字符串记录格式的解析能力。T1 基本只处理数组;T2 必须处理空格分割、- 连接的响应记录、以及竞争中前后两组牌的拆分。
  2. 新增了对四类行动语义的建模。
  3. 测试方面也从 T1 的规则点样例测试,扩展为 T2 的状态恢复测试

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

这次 T2 我们尽量把容易变化的规则拆开写。比如 tokenize 只负责分词,applyDirectAction 只负责处理 1/2/3/4 四类行动,resolveBoard 只负责结算标记。这样以后如果记录格式、行动规则或结算方式变了,只需要改对应函数,不用整段重写。另外我们没有直接改原 board,而是先复制成 nextBoard 再结算,这样更方便排查问题,也方便以后同时保留旧状态和新状态。

头脑风暴环节

→ 📖 Q2.5(P) 头脑风暴环节:

我们终于快要开始让程序玩游戏了!请尝试分析:T2 中不带 X 的操作记录比起实际对局多出了多少信息?如果加上 X,也就是失去了这部分信息的话,如何处理对小轮结束后状态的估计?

  1. 对手通过密约和取舍隐藏掉的具体牌面信息。如果对手执行了 1X2XX,我们就只能知道对手消耗了几张牌,但无法知道具体是哪几张;但是在 T2小轮结束后这些信息会被公开,所以我们实际是上拿到了完整信息,可以据此恢复双方当前公开区和暗置区的牌数
  2. 所有需要保密的动作最终都能知道对应了哪些具体牌

如果重新把 X 加回来,那对于小轮结束后状态的估计就无法得到一个确定的结果,只能得到一个可能状态集合或概率分布。可以用当前已知信息维护一个约束集合,记录哪些牌已经公开、哪些牌已经被消耗但花色未知、哪些牌仍可能留在对手手中或暗置区。对于 1X2XX 这类动作,仅更新“对手少了 1 张或 2 张未知牌”,但花色未知,并利用后续又出现赠予、竞争、公开选牌等动作缩小这些未知牌的可能范围;例如某些花色的总数已经被用满,就可以排除它们继续出现在未知牌中的可能。若需要估计小轮结束后的状态,可以枚举所有满足约束的合法状态;如果状态空间较大,则可改用采样或启发式评估,对每种可能状态计算一个权重,再输出期望分布或最可能状态

总结

→ 📖 Q2.6(P) 请记录下目前的时间,并根据实际情况填写 附录 A:基于 PSP 2.1 修改的 PSP 表格 的“实际耗时”栏目。

2026-04-04 23:08

→ 📖 Q2.7(I) 请写下本部分的心得体会。

这一部分感觉最大的作用就是带我准确的理解游戏规则,理解之后写起来还是好写的

Chapter.3 道途之荆

准备

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

2026.04.06 23:00 → 04.07 00:30 ; 04.08 12:00 → 04.08 14:00

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

  1. 浏览任务要求,参照 附录A:基于 PSP 2.1 修改的 PSP 表格,估计任务预计耗时;
  2. 完成编程任务期间,依次做了什么(比如查阅了什么资料,随后如何进行了开发,遇到了什么问题,又通过什么方式解决);

头脑风暴环节

→ 📖 Q3.3(P) 头脑风暴环节:

假设提供更充裕的时间和资源,这个游戏中你能找到的最优策略有可能是什么形式的?进行调研并总结分析。你还可以在任务结束后试着实现(不计分)。

最优策略可能基于博弈论,如蒙特卡洛树搜索或强化学习,评估所有可能行动的胜率。花见小路类似的卡牌游戏,可以使用状态空间搜索模拟对局。实现可能需要构建树,计算每步的期望值,但由于时间有限,未实现。

需求建模和算法设计

→ 📖 Q3.4(P) 请说明针对该任务,你们采取了哪些策略来优化决策。具体而言,怎么选择行动类型?选牌如何更优?如何编程实现。

优先选择低编号行动,检查历史记录避免重复。选牌从手牌字符串前缀选取。编程实现:解析历史字符串提取已用行动,循环选择可用类型,验证手牌数量。

代码可复用性与需求变更

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

未复用T2代码,T3专注于决策函数,而T2是状态计算。

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

设计思想:模块化,将解析历史、选择行动分离。冗余:添加边界检查,如手牌不足时fallback。使用类型安全(Int8Array),便于扩展到更复杂策略。

软件度量

→ 📖 Q3.7(P) 请说明你们如何量度所实现的程序模块的有效性,例如:“如何说明我们的程序模块决策能力很强?”,尝试提出一些可能的定量分析方式或测试方式。

有效性通过测试框架验证:运行完整对局,检查无异常。定量:胜率统计(与随机对手比较)、决策时间(<2秒)、覆盖率(测试不同局面)。强决策:高胜率、低超时。

总结

→ 📖 Q3.8(P) 请记录下目前的时间,并根据实际情况填写 附录A:基于 PSP 2.1 修改的 PSP 表格 的“实际耗时”栏目。

04.08 14:04

→ 📖 Q3.9(I) 请写下本部分的心得体会。

与队友在沟通协作中实现了简单的决策策略,在过程中体会到沟通协作的重要性

结对项目总结

结对过程回顾和反思

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

0079c5e9920d972068cdb70b04bf7ccf

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

过程整体顺利,但可以增加更多测试和用例,提升策略复杂度。

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

优点:性格开朗沟通顺畅;代码能力强;编写测试样例严谨细致
缺点:有点忙,不太好约时间

对结对编程的理解

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

优点:在沟通中能够产生很多新的想法
缺点:协调成本高。很吃配合
整体上结对编程强调协作,合理搭配下往往能够提高代码质量。

代码实现提交

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

https://github.com/owpeter/BUAASE2026-PairProgramming.git

posted @ 2026-04-09 16:17  owpeter  阅读(2)  评论(0)    收藏  举报