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

项目 内容
这个作业属于哪个课程 https://edu.cnblogs.com/campus/buaa/BUAA_SE_2026_LR?page=2
这个作业的要求在哪里 https://edu.cnblogs.com/campus/buaa/BUAA_SE_2026_LR/homework/15648
我在这个课程的目标是 学会团队协作
这个作业在哪个具体方面帮助我实现目标 体验结对编程,培养团队协作能力

结对项目:博客问题清单

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

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

工具:Cursor
模型:composer
使用范围:1. 编写项目gitignore;2. 自动化构建依赖环境;3. 启发T3策略优化思路;4. 协助整理文档内容。最终提交的内容均经过人员审核。

Chapter.0 wasm从安装到入门

引入

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

2026-4-10 8:23

调查

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

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

I. 没有听说过;

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

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

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

Wasm: 结对开始前整体在 II~III 之间。知道 Wasm 能进浏览器、别的语言可以编译成它,也和网页性能有关,但真正自己配工具链、写模块、和 JS 对接,是这次项目里才完整走了一遍。

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

I. 不了解玩法和规则;

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

花见小路:I。之前没玩过实体桌游,规则是这次读 README、看视频、边做 T1/T2 边熟悉的,算从零入门。

总结

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

2026-4-10 8:57

Chapter.1 七色之缨

结对过程

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

2026-04-10 09:02

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

  1. 浏览任务要求,参照 附录A:基于 PSP 2.1 修改的 PSP 表格,估计任务预计耗时;
Personal Software Process Stages 个人软件开发流程 预估耗时(分钟) 实际耗时(分钟)
PLANNING 计划
- Estimate - 估计这个任务需要多少时间 5 5
DEVELOPMENT 开发
- Analysis & Design Spec - 需求分析 & 生成设计规格(确定要实现什么) 8 10
- Technical Background - 了解技术背景(包括学习新技术) 7 6
- Coding Standard - 代码规范 2 2
- Design - 具体设计(确定怎么实现) 8 6
- Coding - 具体编码 15 13
- Code Review - 代码复审 3 2
- Test Design - 测试设计(确定怎么测,比如要测试哪些情景、设计哪些种类的测试用例) 5 4
- Test Implement - 测试实现(设计/生成具体的测试用例、编码实现测试) 6 5
REPORTING 报告
- Quality Report - 质量报告(评估设计、实现、测试的有效性) 2 3
- Size Measurement - 计算工作量 1 1
- Postmortem & Process Improvement Plan - 事后总结和过程改进计划(总结过程中的问题和改进点) 2 2
TOTAL 合计 64 59
  1. 完成编程任务期间,依次做了什么(例如查阅了哪些资料、如何设计判定逻辑、如何设计测试样例、遇到了什么问题、如何解决)。
  1. 首先仔细阅读指导书的胜负判定规则,并且看了给出的B站小视频,明确核心判定条件,梳理出规则的优先级和执行逻辑。
  2. 基于梳理好的规则,按优先级分步设计函数核心逻辑,保证逻辑清晰无歧义。
  3. 根据规则,按场景分类设计测试用例,覆盖所有规则范围,并且检测编写的代码能够顺利通过该测试以及课题组给出的测试。

设计

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

  1. 辅助函数
    • tokenValue(index: i32): i32:根据倾心标记索引返回对应分值(A/B/C=2、D/E=3、F=4、G=5)。
    • tierPriority(index: i32): i32:返回同分比较时的优先级(G=3、F=2、D/E=1、A/B/C=0)。
  2. 中间量
    • myScore/oppScore:统计双方总分值。
    • myCnt/oppCnt:统计双方拥有的倾心标记数量。
    • myBestTier/oppBestTier:记录双方最高优先级倾心标记档位。

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

先把题目里写清楚的胜利条件按判断的先后顺序排好,和 README 保持一致,再在纸上或注释里画一条线性的判断流程,避免写着写着漏掉某一种情况。实现时把算总分、数枚数、第三轮同分比档位这几块拆成小段函数或步骤,每段只干一件事,这样不容易把条件写反。测试上按指导书列的那几类场景各做一两个用例,尤其是第三轮的平局、同分不同档,跑一遍就能发现分支顺序有没有写错。

测试

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

我们的测试覆盖了指导书中给出的测试范围:

  1. 游戏任意轮次可触发:

    1. 一方积分累计达到 11 分,直接判定获胜
    2. 一方集齐至少 4 枚倾心标记,且对方未达到 11 分,判定获胜
  2. 中间轮次,即第 1,2 轮:

    1. 第 1、2 小轮结束,未满足以上任何胜利条件,则无玩家获胜,返回 0,游戏继续进行
  3. 第 3 轮终局结算规则测试:

    1. 第 3 小轮结束,双方总积分不相等,总积分更高的玩家获胜
    2. 第 3 小轮结束,双方总积分相同,以高价值档位的倾心标记归属判定胜负
    3. 第 3 小轮结束,积分与高价值标记均完全持平,判定为全局平局

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

先写测试再实现,等于是先把什么算对这件事固定下来,写代码时心里更踏实,改规则时也能马上知道有没有把老用例弄坏,缺点是刚开始要花点时间想用例。

先实现再补测试往往写得更快,但容易漏边界,后面补测试时还可能要大改结构。

我们这次更偏向后一种,不过会把指导书要求的几种情况尽快写成自动化测试,尽量别拖到很后面。

总结

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

2026-04-10 10:02

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

这一章规则看起来长,拆成算分、数标记、第几轮这几块之后其实逻辑是顺的。把辅助函数写清楚以后,主函数就像填空。最大的收获是:判定类代码最怕顺序和边界搞混,用例覆盖到位比多写几行聪明代码更重要。

Chapter.2 不祥之影

准备

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

2026-04-10 10:20

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

  1. 浏览任务要求,参照 附录A:基于 PSP 2.1 修改的 PSP 表格,估计任务预计耗时;
Personal Software Process Stages 个人软件开发流程 预估耗时(分钟) 实际耗时(分钟)
PLANNING 计划
- Estimate - 估计这个任务需要多少时间 5 5
DEVELOPMENT 开发
- Analysis & Design Spec - 需求分析 & 生成设计规格(确定要实现什么) 15 18
- Technical Background - 了解技术背景(包括学习新技术) 10 11
- Coding Standard - 代码规范 3 3
- Design - 具体设计(确定怎么实现) 20 28
- Coding - 具体编码 45 43
- Code Review - 代码复审 5 7
- Test Design - 测试设计(确定怎么测,比如要测试哪些情景、设计哪些种类的测试用例) 15 8
- Test Implement - 测试实现(设计/生成具体的测试用例、编码实现测试) 20 13
REPORTING 报告
- Quality Report - 质量报告(评估设计、实现、测试的有效性) 3 5
- Size Measurement - 计算工作量 1 1
- Postmortem & Process Improvement Plan - 事后总结和过程改进计划(总结过程中的问题和改进点) 2 3
TOTAL 合计 144 154
  1. 完成编程任务期间,依次做了什么(比如查阅了什么资料,随后如何进行了开发,遇到了什么问题,又通过什么方式解决);
  1. 首先阅读 T2 的指导书,明确本题需求,确定输入输出含义及主函数名称。
  2. 实现代码编写:首先厘清主函数架构,根据各行动内容依次完成各类型行动函数编写,并且设计了字符串分割等辅助函数,最后完成主函数的填充。
  3. 根据指导书完成测试代码编写,首先确保每个行动相关的代码逻辑正确,然后是总体逻辑正确;最后进行课题组提供的测试并成功通过。

代码可复用性与需求变更

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

T2 未对 T1 的代码进行复用。

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

解析 history 和行动类型尽量拆成小函数,输入输出含义单一,以后规则微调时只改局部。牌面、行动类型用常量或表驱动,少写魔法数字。可以适当多留一层从字符串到中间结构的转换,看起来多写一点,但以后如果记录格式变了,不用整文件搜着改。测试里留几条典型 history,改代码跑一遍,心里会稳很多。

头脑风暴环节

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

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

不带 X 的操作记录多出的信息:对手玩家原本在游戏进行中不会公开的牌,也就是对手进行“密约”时选择的牌以及进行“舍弃”时扔掉的牌。因此玩家可以根据这些牌来调整自己的出牌策略,考虑自己应该抢夺或者放弃哪些角色的标记。

加 X 后我们认为可以:

  • 利用公开的信息,包括但不限于自己的手牌、目前场上出现的牌组以及总牌数,剔除不可能状态,维护可行状态集合;
  • 在不知对方出牌策略的情况下,可以假设对手始终采取最优策略出牌。

总结

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

2026-04-10 12:55

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

T2 比 T1 长不少,主要难在把一整条 history 从头到尾推成最后的局面,字符串细节多,容易漏一种行动。两个人轮流写、互相读对方的分支,比一个人闷头写要快发现问题。做完这一章再回头看规则,会比刚开始清晰很多。

Chapter.3 道途之荆

准备

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

2026-04-10 14:40

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

  1. 浏览任务要求,参照 附录A:基于 PSP 2.1 修改的 PSP 表格,估计任务预计耗时;
Personal Software Process Stages 个人软件开发流程 预估耗时(分钟) 实际耗时(分钟)
PLANNING 计划
- Estimate - 估计这个任务需要多少时间 5 8
DEVELOPMENT 开发
- Analysis & Design Spec - 需求分析 & 生成设计规格(确定要实现什么) 20 17
- Technical Background - 了解技术背景(包括学习新技术) 15 18
- Coding Standard - 代码规范 5 5
- Design - 具体设计(确定怎么实现) 35 38
- Coding - 具体编码 100 108
- Code Review - 代码复审 10 14
- Test Design - 测试设计(确定怎么测,比如要测试哪些情景、设计哪些种类的测试用例) 20 18
- Test Implement - 测试实现(设计/生成具体的测试用例、编码实现测试) 30 27
REPORTING 报告
- Quality Report - 质量报告(评估设计、实现、测试的有效性) 5 5
- Size Measurement - 计算工作量 2 2
- Postmortem & Process Improvement Plan - 事后总结和过程改进计划(总结过程中的问题和改进点) 3 5
TOTAL 合计 245 265
  1. 完成编程任务期间,依次做了什么(比如查阅了什么资料,随后如何进行了开发,遇到了什么问题,又通过什么方式解决);
  1. 首先阅读 T3 的指导书,明确本题的任务需求,以及主函数入口。
  2. 代码实现
    1. 由于这道题需要根据历史信息及场上局势进行出牌,因此我们将任务拆分为了两个部分:分析场上整体局势部分以及出牌策略部分,因为可以在后续有新的策略思路时更好地进行修改;
    2. 因此我们首先采取了最简单的固定策略,目的是为了将焦点先锁定在分析场上局势并出牌的部分,并且完成该部分代码编写;
    3. 后续我们查阅了相关资料,以及利用AI进行启发,采取了加权贪心的出牌策略,进一步对我们的出牌策略部分进行了优化。
  3. 在两轮的代码编写过程中,我们自行编写了测试代码,同时借助课题组提供的测试代码进行测试,并成功通过。

头脑风暴环节

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

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

  1. 如果把游戏看成零和博弈,假设对手会采取对我方最不利的最优策略,我方在所有可能的行动中选择“对手反制后我方收益最大”的行动,可以采用极小极大搜索(再配合剪枝)在树上寻找较好的走法。

  2. 考虑到游戏过程中信息不完全的特性,可以考虑采用蒙特卡洛树搜索(MCTS),无需完整博弈树,通过“模拟-选择-扩展-回溯”迭代优化决策,通过大量模拟对局学习最优行动,适配对手策略的变化。

需求建模和算法设计

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

  1. 预处理:对于每种牌型进行赋值,每张牌的价值由牌本身分数乘以当前局面权重得到。当前局面权重经分析目前的场上局势得到,如果在该花色上我们处于落后或平局时,该花色的权重要高于领先时权重,这样能够鼓励争夺劣势或平局的花色。

  2. 选牌时:

    • 3(赠予):选择对手所处的三张牌中价值最高的一张牌。
    • 4(竞争):选择对手所处的四张牌中价值最高的一组牌。
  3. 行动时:排除所有已进行过的行动,枚举了所有合法的行动类型,并为每种可能的牌组合计算一个得分,最终选择得分最高的行动。

    • 1(密约):遍历手牌中每一张牌,选择单张价值最高的牌,估值sum
    • 2(取舍):枚举所有两两组合,计算两张牌的价值和,弃掉两张价值总和最低的牌,,估值sum-min(弃牌组合)
    • 3(赠予):展示三张牌,对手会选走价值最高的一张,剩下两张归自己。因此我们希望剩下的两张牌价值之和最大,枚举所有三张牌的组合,最大化 sum - max
    • 4(竞争):将四张牌分成两组,对手会选走价值总和较高的一组,自己得到较低的一组。因此我们希望较低的那一组价值尽可能高,枚举所有四张牌的组合,对于每种组合尝试所有三种可能的配对方式,计算 min(pair1, pair2),取最大值;然后选择使该值最大的配对方式。
  4. 编码实现:

    • 选牌:该部分代码位于choiceReply中,将以上的策略进行编码实现,并返回最合适的选择组合。
    • 行动:该部分核心代码集中在buildNormalAction(used, cards, board): string中,枚举所有未使用 + 手牌数合法的行动与牌型,按加权贪心选最优。

代码可复用性与需求变更

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

复用:

  • splitBySpace
    • 用途:按空格切分历史行动字符串。
    • 复用场景:在 T3 中用于解析 history 参数,将其转换为行动数组以便后续处理。
  • sameMultiset2

    • 用途:判断两个双字符组合是否等价。
    • 复用场景:在 T3 中用于验证类型 4 行动中选组的合法性。
  • countLetters

    • 用途:统计字符串中 A-G 各字母出现的次数。
    • 复用场景:作为 T3 中分值计算的基础工具,用于统计玩家持有的倾心标记数量及分布。

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

把读 history、推断轮到谁、算分选牌分开,策略想换的时候只动打分或枚举那一块。分值、权重尽量集中在一两个函数里,不要散落在每个分支里写死数字。T2 里已经有的字符串工具能复用就复用,避免两处解析逻辑不一致。以后如果换更强的算法,只要保持入口 hanamikoji_action 的输入输出不变,内部可以整块替换。

软件度量

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

  1. 首先保证代码有效性:
    1. 执行课程组提供的测试,能跑通说明 Wasm 导出、接口和联调正常。
    2. 把自己编译的 wasm 复制多份互相对打,看对局结果是否出现波动,有没有被判超时。
  2. 其次看我们程序的决策能力:
    1. 与自己迭代前的代码进行比较,看看性能是不是更好;
    2. 和别的小组进行多轮次比较,并且交换先后手,查看胜率;
    3. 调整 buildNormalAction 里某一类行动的打分系数,多跑几局比较胜率变化,用于检验盘面权重等设计是否带来稳定收益。
  3. 时间:题目要求每步约 2 秒内;本地跑测试或 console.time 包一层 hanamikoji_action,确认不会卡死。

总结

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

2026-04-10 19:08

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

T3 要在不完整信息里做决策,我们先用简单可跑的打分把整条链路跑通,再慢慢调权重,比一上来追求完美的算法现实。和别的组对战会发现强弱差很多,也说明策略还有很大空间。注意别超时,这一点和写对同样重要。

结对项目总结

结对过程回顾和反思

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

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

整体结对的过程很顺利!提升改进的方面:

  1. 下次努力更早一点开始,但是时间确实有点难协调,挑战不再做 DDL 达人!
  2. 在开始结对前先进行相关内容的学习,尽量减少结对时一起现场学习的情况。
  3. 编码过程中,部分思考过程和讨论过程没有及时记录,应该及时记录开发过程中的关键决策、遇到的问题及对应的解决办法,便于后续总结与完善。

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

优点:

  • 思路清楚,讨论的时候能把问题拆开说
  • 写代码手快,愿意先搭架子再填细节
  • 测试和文档也会主动跟,不用一直催。

缺点:有时候赶进度会少写注释,后面回看要自己再想一遍当时为什么这样写。

对结对编程的理解

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

优点是能互相补位,一个人卡住了另一个人往往换个角度就通了,代码也容易在当场被看出低级错误。缺点是两个人时间要凑在一起,沟通成本比单干高,如果节奏不一致会有一点等或赶的感觉。我理解结对不是简单分工各写一半,而是一起盯着同一套问题和同一份代码,把讨论和实现绑在一起,这样质量会比各干各的更稳一点。

代码实现提交

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

https://github.com/Z-XUA/BUAASE2026-PairProgramming

posted @ 2026-04-11 19:30  Nice2cu22  阅读(11)  评论(0)    收藏  举报