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

  1. 浏览任务要求,参照 附录A:基于 PSP 2.1 修改的 PSP 表格,估计任务预计耗时;
  2. 完成编程任务期间,依次做了什么(例如查阅了哪些资料、如何设计判定逻辑、如何设计测试样例、遇到了什么问题、如何解决)。
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) 请在完成任务的同时记录,并在完成任务后整理完善:

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

  1. 浏览任务要求,参照 附录A:基于 PSP 2.1 修改的 PSP 表格,估计任务预计耗时;
  2. 完成编程任务期间,依次做了什么(比如查阅了什么资料,随后如何进行了开发,遇到了什么问题,又通过什么方式解决);
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) 提供两人在讨论的结对图像资料。

d607db5f72e0b684c289d7e9817a0c01

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

1、部分函数命名不够直观,导致调用辅助函数时需要在代码中反复查找才能理解其用途

2、在动手编码之前,对整体架构和模块划分的设计讨论不够充分。

3、结对过程中的技术讨论有时表述不够精准,导致双方对同一问题的理解出现偏差。

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

优点:积极沟通交流,策略游戏经验丰富,测试与设计考虑周全。

缺点:在长时间代码编写后,精力可能有一点点下降

对结对编程的理解

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

  • 优点:
    • 经过交流和讨论,可以得到良好的设计,避免需求的遗漏。
    • 在面对困难时,可以共同克服。
    • 代码编写的时候,互相纠错,吸收相互的编码习惯上的优点。
  • 缺点:
    • 在一些小代码量的编写上,可能会不如单人开发效率。
  • 理解:结对编程可以实时审查设计、代码实现、测试等各阶段的不足或错误,并即刻提出修改和完善。虽然可能会在一定程度上降低开发速度,但能显著提高代码的正确性,减少事后定位和修复 Bug 的时间成本。同时,结对编程是一种平等的交流方式,两人站在同一层级上共同完成任务。

代码实现提交

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

代码仓库链接

posted @ 2026-04-10 10:51  耳钬  阅读(18)  评论(0)    收藏  举报