[P] 结对项目:花见小路
[P] 结对项目:花见小路
| 项目 | 内容 |
|---|---|
| 这个作业属于哪个课程 | 2026春软件工程 |
| 这个作业的要求在哪里 | 个人第二次作业 |
| 我在这个课程的目标 | 帮助了解结对编程、敏捷开发全流程,同时提升两人协作能力,提升交流效率 |
| 这个作业在哪个具体方面帮助我实现目标 | 从项目设计到实现,从交流到合作 |
→ 📖 Q0.0(P) 【你可以在结对结束后补充】如果你的代码仓库包含 AIGC 的部分,列举使用的工具、模型和使用范围。若未使用则填写:本组提交的全部代码不包含AI补全或生成的部分。
本组提交的全部代码不包含AI补全或生成的部分
Chapter.0 wasm从安装到入门
引入
→ 📖 Q0.1(P) 请记录下目前的时间。
2026/4/2 16:43
调查
→ 📖 Q0.2(I) 【你可以在结对结束后另行补充。】作为本项目的调查:
请如实标注在开始项目之前对 Wasm 的熟悉程度分级,可以的话请细化具体的情况。(分别回答两人各自的情况)
I. 没有听说过;
请如实标注在开始项目之前对桌游花见小路的熟悉程度分级,可以的话请细化具体的情况。(分别回答两人各自的情况)
I. 不了解玩法和规则;
总结
→ 📖 Q0.3(P) 请记录下目前的时间。
2026/4/2 17:13
Chapter.1 七色之缨
结对过程
→ 📖 Q1.1(P) 请记录下目前的时间。
2026/4/2 17.14
→ 📖 Q1.2(P) 请在完成任务的同时记录,并在完成任务后整理完善:
- 浏览任务要求,参照 附录A:基于 PSP 2.1 修改的 PSP 表格,估计任务预计耗时;
- 完成编程任务期间,依次做了什么(例如查阅了哪些资料、如何设计判定逻辑、如何设计测试样例、遇到了什么问题、如何解决)。
| Personal Software Process Stages | 个人软件开发流程 | 预估耗时(分钟) | 实际耗时(分钟) |
|---|---|---|---|
| PLANNING | 计划 | ||
| - Estimate | - 估计这个任务需要多少时间 | 68 | 115 |
| DEVELOPMENT | 开发 | ||
| - Analysis & Design Spec | - 需求分析 & 生成设计规格(确定要实现什么) | 2 | 2 |
| - Technical Background | - 了解技术背景(包括学习新技术) | 5 | 45 |
| - Coding Standard | - 代码规范 | 5 | 5 |
| - Design | - 具体设计(确定怎么实现) | 10 | 5 |
| - Coding | - 具体编码 | 10 | 15 |
| - Code Review | - 代码复审 | 5 | 3 |
| - Test Design | - 测试设计(确定怎么测,比如要测试哪些情景、设计哪些种类的测试用例) | 5 | 5 |
| - Test Implement | - 测试实现(设计/生成具体的测试用例、编码实现测试) | 10 | 20 |
| REPORTING | 报告 | ||
| - Quality Report | - 质量报告(评估设计、实现、测试的有效性) | 5 | 5 |
| - Size Measurement | - 计算工作量 | 5 | 5 |
| - Postmortem & Process Improvement Plan | - 事后总结和过程改进计划(总结过程中的问题和改进点) | 5 | 5 |
- 通过视频网站了解花间小路规则,包括游戏规则、玩家操作、判断条件等。
- 通过阅读wasm官方文档、课程组提供的guide.md,并结合AI询问,了解wasm的基本概念和使用方法。
- 通过视频网站和rust官网学习rust的基本语法和概念。
- 交流并讨论设计相关的判定函数。
- 测试:先撰写一些边界情况测试,然后写python脚本随机生成测试用例。
设计
→ 📖 Q1.3(P) 请说明你们为这个判定模块设计了哪些中间量或辅助函数;如果没有额外设计,也请说明为什么认为直接实现已经足够清晰。
SCORE 全局变量,记录所有的分数。
judge_score_11 判定函数,用于判断玩家是否在当前轮中获得了 11 分。
judge_num_4 判定函数,用于判断玩家是否在当前轮中获得了 4 个艺妓的青睐。
judge_more_point 判定函数,用于在第三轮中,如果双方玩家不能通过judge_score_11和judge_num_4判断胜负,则通过比较分数高低来判断。
judge_dictionary 判定函数,用于在第三轮中,如果双方玩家不能通过judge_score_11,judge_num_4,- --
judge_dictionary 和判断胜负,则通过比较最高分倾心标记判断。
→ 📖 Q1.4(I) 请说明在这样一个规则判定类模块中,如何避免“漏判”“错判”或分支顺序错误等问题。
- 仿照决策树的结构,系统梳理所有情况,来保证无漏判情况
- 编写default分支,用于捕获未考虑情况,可以避免漏判
- 对于已明确的条件分支使用if或elif显示判断,不使其进入else分支
- 对于有顺序的分支情况可以编写小测试进行测试
- 对于漏判可以通过测试分支的覆盖率来检测
测试
→ 📖 Q1.5(P) 请说明你们设计了哪些测试用例,这些测试分别覆盖了哪一类规则或边界情况。
- 一方超过11分情况
- 一方获得11分另一方获得4个艺妓情况
- 一方获得4个艺妓但无11分情况
- 前两轮平局情况
- 第三轮超过11分情况
- 第三轮4个艺妓情况
- 第三轮均未超过11分且未获得4个艺妓
- 总分更高者赢情况
- 同分下得分字典序大者赢情况
- 平局情况
→ 📖 Q1.6(I) 请说明你对“先写测试再实现”与“先实现再补测试”两种方式的理解。
“先写测试再实现”主要针对于正确性至上且需求相对不变的情况,例如本题规则已经给明且不再会更改,可以优先编写尽量完整的测试,然后根据测试的逻辑再实现代码,正确性可以有所保障。
"先实现再补测试"追求写把功能代码写出来,让其可以跑通然后再测bug。适合需求可能相对变化,功能较多,要提前编写完整的测试比较困难的情况。这种方式可以确保开发效率,但是正确性、安全性等相对较差。
总结
→ 📖 Q1.7(P) 请记录下目前的时间,并根据实际情况填写 附录A:基于 PSP 2.1 修改的 PSP 表格 的“实际耗时”栏目。
2026/4/2 18:54
→ 📖 Q1.8(I) 请写下本部分的心得体会。
增加了对WebAssembly的理解,同时初步学习了Rust语言。体会到WebAssembly的良好的桥梁作用,同时体会到Rust切片机制下的安全制度的保证。
第一次作业的结对过程十分顺利,两个人进行讨论可以避免决策分支少考虑的情况,同时良好的分工加快开发效率,例如一人写代码另一人构想测试代码并行开发,效率很快。
Chapter.2 不祥之影
准备
→ 📖 Q2.1(P) 请记录下目前的时间。
2026/4/2 19:08
→ 📖 Q2.2(P) 请在完成任务的同时记录,并在完成任务后整理完善:
- 浏览任务要求,参照 附录A:基于 PSP 2.1 修改的 PSP 表格,估计任务预计耗时;
- 完成编程任务期间,依次做了什么(比如查阅了什么资料,随后如何进行了开发,遇到了什么问题,又通过什么方式解决);
| Personal Software Process Stages | 个人软件开发流程 | 预估耗时(分钟) | 实际耗时(分钟) |
|---|---|---|---|
| PLANNING | 计划 | ||
| - Estimate | - 估计这个任务需要多少时间 | 165 | 215 |
| DEVELOPMENT | 开发 | ||
| - Analysis & Design Spec | - 需求分析 & 生成设计规格(确定要实现什么) | 10 | 10 |
| - Technical Background | - 了解技术背景(包括学习新技术) | 10 | 20 |
| - Coding Standard | - 代码规范 | 10 | 10 |
| - Design | - 具体设计(确定怎么实现) | 10 | 20 |
| - Coding | - 具体编码 | 60 | 70 |
| - Code Review | - 代码复审 | 15 | 20 |
| - Test Design | - 测试设计(确定怎么测,比如要测试哪些情景、设计哪些种类的测试用例) | 15 | 10 |
| - Test Implement | - 测试实现(设计/生成具体的测试用例、编码实现测试) | 20 | 40 |
| REPORTING | 报告 | ||
| - Quality Report | - 质量报告(评估设计、实现、测试的有效性) | 5 | 5 |
| - Size Measurement | - 计算工作量 | 5 | 5 |
| - Postmortem & Process Improvement Plan | - 事后总结和过程改进计划(总结过程中的问题和改进点) | 5 | 5 |
- 依旧阅读指导书和rust文档
- 设计Player和Action结构体,用于存储玩家信息和操作记录。
- 为Player设计get_board(), add_card(), apply_action()方法,用于获取玩家当前状态、添加牌、应用操作。
- 编写strip_history()函数,用于处理输入
- 最后完成calc_current_state()函数
- 手工编写了三个测试用例后,通过python脚本随机生成测试用例。
代码可复用性与需求变更
→ 📖 Q2.3(P) 请说明针对该任务,你们对 🧑💻 T1 中已实现的代码进行了哪些复用和修改。
无T1复用代码。
→ 📖 Q2.4(I) 请说明在编码实现时,可以采取哪些设计思想、考虑哪些设计冗余,来提高既存代码适应需求变更的能力。
- 设计完备的Player结构体,将可能的属性和方法进行封装,在设计函数时可以传一整个结构体,避免硬编码固定的参数,提升迭代性。
- 通过设计枚举常量或全局常量,新增状态只需修改这些地方。
- 单一函数尽量只实现单一功能。
- 尽量避免修改已实现代码。
头脑风暴环节
→ 📖 Q2.5(P) 头脑风暴环节:
我们终于快要开始让程序玩游戏了!请尝试分析:T2 中不带 X 的操作记录比起实际对局多出了多少信息?如果加上 X,也就是失去了这部分信息的话,如何处理对小轮结束后状态的估计?
T2相当于上帝视角,相比正式游戏可以多了解对少操作1和操作2的牌;
如果失去此信息,可以通过枚举牌的组合、计算概率或者从博弈论角度(即假定对手是理性最优策略反向推断其未展示的牌)等方法来预估。
总结
→ 📖 Q2.6(P) 请记录下目前的时间,并根据实际情况填写 附录 A:基于 PSP 2.1 修改的 PSP 表格 的“实际耗时”栏目。
2026/4/3 19:54
→ 📖 Q2.7(I) 请写下本部分的心得体会。
本次作业依旧感受到良好的设计对功能的实现的重要性。在真正实现前,将任务拆分成处理输入,处理业务逻辑,完成输出三个子任务。对于每个部分分别设计辅助函数实现;同时涉及Player、Action等结构体作为子任务之间传递的对象,对子任务解耦处理,提升开发效率。
Chapter.3 道途之荆
准备
→ 📖 Q3.1(P) 请记录下目前的时间。
2026/4/5 15:54
→ 📖 Q3.2(P) 请在完成任务的同时记录,并在完成任务后整理完善:
- 浏览任务要求,参照 附录A:基于 PSP 2.1 修改的 PSP 表格,估计任务预计耗时;
- 完成编程任务期间,依次做了什么(比如查阅了什么资料,随后如何进行了开发,遇到了什么问题,又通过什么方式解决);
| Personal Software Process Stages | 个人软件开发流程 | 预估耗时(分钟) | 实际耗时(分钟) |
|---|---|---|---|
| PLANNING | 计划 | ||
| - Estimate | - 估计这个任务需要多少时间 | 375 | 615 |
| DEVELOPMENT | 开发 | ||
| - Analysis & Design Spec | - 需求分析 & 生成设计规格(确定要实现什么) | 20 | 20 |
| - Technical Background | - 了解技术背景(包括学习新技术) | 10 | 10 |
| - Coding Standard | - 代码规范 | 10 | 20 |
| - Design | - 具体设计(确定怎么实现) | 60 | 100 |
| - Coding | - 具体编码 | 220 | 400 |
| - Code Review | - 代码复审 | 20 | 30 |
| - Test Design | - 测试设计(确定怎么测,比如要测试哪些情景、设计哪些种类的测试用例) | 10 | 10 |
| - Test Implement | - 测试实现(设计/生成具体的测试用例、编码实现测试) | 10 | 10 |
| REPORTING | 报告 | ||
| - Quality Report | - 质量报告(评估设计、实现、测试的有效性) | 5 | 5 |
| - Size Measurement | - 计算工作量 | 5 | 5 |
| - Postmortem & Process Improvement Plan | - 事后总结和过程改进计划(总结过程中的问题和改进点) | 5 | 5 |
- 依旧阅读rust文档,学习rust的基本语法和概念。
- 设计中考虑复用T2中的Player和Action结构体。
- 通过进行多轮花间小路游戏分析策略,同时调研分析得到打分策略、蒙地卡罗模拟等方法,最后结合自身代码实力,选择贪心策略
- 先实现整体框架,定义Strategy trait,然后优先实现随机策略,在test.js中测试,确认框架正确性。
- 再实现贪心策略,在test.js中测试,确认正确性。同时与随机策略对比,分析贪心策略的优势与不足。
- 通过修改test.js进行随机发牌后多次测试。
- 与其他组同学进行对战,根据结果调整策略。
头脑风暴环节
→ 📖 Q3.3(P) 头脑风暴环节:
假设提供更充裕的时间和资源,这个游戏中你能找到的最优策略有可能是什么形式的?进行调研并总结分析。你还可以在任务结束后试着实现(不计分)。
1、引入对手信息建模,分析对手所需手牌。同时观察对手动作,通过贝叶斯更新其手牌的概率分布。从而可以预测对手想要的牌,可以添加诱饵策略。
2、进行长期规划,对后续抽牌和轮次分别建模。例如第一轮可以牺牲收益换取信息,越往后越注重得分。
3、对卡牌的重要性进行打分评估,从而决定牌的取舍。
4、通过CFR算法离线求解贝叶斯纳什均衡,得到可查表的最优混合策略。
需求建模和算法设计
→ 📖 Q3.4(P) 请说明针对该任务,你们采取了哪些策略来优化决策。具体而言,怎么选择行动类型?选牌如何更优?如何编程实现。
行动类型选择:优先级策略。
- 手牌有三张相同则执行赠与操作
- 手牌有两对则进行竞争操作
- 优先弃掉对方比自己多的牌,阻止对手得分
- 根据双方中牌的数量判断牌的重要性,然后选取密约
- 回退至随机策略
选牌策略:
- 密约时:提高高分牌的优先级,同时避免拿对手已经有优势的牌
- 回应赠与选牌时:优先选大牌,除非对手已经领先;其次抓可完成收集的牌,再抓对手少数牌,最后退回随机策略
- 回应竞争选牌时:优先选打牌,除非对手领先;其次选完成度更高的组合的牌,其次选数值更大的牌,最后随机
编程实现:
- 设计Player结构体:记录手牌、桌面牌、已做动作、未做动作
- 设计Action结构体,对action封装
- 定义Strategy trait,同时定义两个决策接口(give_advice和give_feedback)
辅助函数:
- have_triple():检测三连张牌(供赠与选择)
- have_double_double():检测两对(供竞争选择)
- have_discard():检测玩家手里可丢弃的牌
- is_critical():比较双方持有量判断手牌的关键性
- would_complete():判断拿了此牌是否可以直接收集成功
构建RandomStrategy,用随机策略作为保底
代码可复用性与需求变更
→ 📖 Q3.5(P) 请说明针对该任务,你们对 🧑💻 T2 中已实现的代码进行了哪些复用和修改。
复用了T2中的Player结构体和Action结构体。
→ 📖 Q3.6(I) 请说明在编码实现时,可以采取哪些设计思想、考虑哪些设计冗余,来提高既存代码适应需求变更的能力。
相比第二次作业增加了Strategy Trait,分别涉及give_advice和give_feedback两个结口,在实现随机策略和贪心策略后,可通过简单配置进行策略切换,达到即插即用的效果。
软件度量
→ 📖 Q3.7(P) 请说明你们如何量度所实现的程序模块的有效性,例如:“如何说明我们的程序模块决策能力很强?”,尝试提出一些可能的定量分析方式或测试方式。
通过修改给予的test.js代码,使其可以随机发牌,同时写脚本进行100次测评,观察胜率以及对局过程。(借用同学的胶水文件,或者与随机策略进行对比)
总结
→ 📖 Q3.8(P) 请记录下目前的时间,并根据实际情况填写 附录A:基于 PSP 2.1 修改的 PSP 表格 的“实际耗时”栏目。
2026/4/9 18.36
→ 📖 Q3.9(I) 请写下本部分的心得体会。
最大的收获,是完整地为这次博弈游戏编写了策略代码(真的不太擅长这类游戏……)。在这个过程中我认识到,写博弈策略不能一直纠结哪个方案更好,否则会迟迟无法下手,严重拖慢开发效率。这有点像“先实现再测试”的思路,先把基础策略功能写出来,后续再根据对战结果不断优化补充。哪怕一开始会输很多,也总比没有代码强。
结对项目总结
结对过程回顾和反思
→ 📖 Q4.1(P) 提供两人在讨论的结对图像资料。

→ 📖 Q4.2(P) 回顾结对的过程,反思有哪些可以提升和改进的地方。
1、部分函数命名不够直观,导致调用辅助函数时需要在代码中反复查找才能理解其用途
2、在动手编码之前,对整体架构和模块划分的设计讨论不够充分。
3、结对过程中的技术讨论有时表述不够精准,导致双方对同一问题的理解出现偏差。
→ 📖 Q4.3(I) 锐评一下你的搭档!并请至少列出三个优点和一个缺点。
优点:积极沟通交流,策略游戏经验丰富,测试与设计考虑周全。
缺点:在长时间代码编写后,精力可能有一点点下降
对结对编程的理解
→ 📖 Q4.4(I) 说明结对编程的优缺点、你对结对编程的理解。
- 优点:
- 经过交流和讨论,可以得到良好的设计,避免需求的遗漏。
- 在面对困难时,可以共同克服。
- 代码编写的时候,互相纠错,吸收相互的编码习惯上的优点。
- 缺点:
- 在一些小代码量的编写上,可能会不如单人开发效率。
- 理解:结对编程可以实时审查设计、代码实现、测试等各阶段的不足或错误,并即刻提出修改和完善。虽然可能会在一定程度上降低开发速度,但能显著提高代码的正确性,减少事后定位和修复 Bug 的时间成本。同时,结对编程是一种平等的交流方式,两人站在同一层级上共同完成任务。
代码实现提交
→ 📖 Q4.5(P) 请提供你们完成代码实现的代码仓库链接。

浙公网安备 33010602011771号