第二次结对编程作业

第二次结对作业



1、博客链接、本作业博客的链接、你所Fork的同名仓库的Github项目地址

2、分工

  • 高鹏-AI & 陈志明-UI


3、给出PSP表格


PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
Planning 计划 60 120
·Estimate 估计这个任务需要多少时间 20 20
·Development 开发 1200 1050
· Analysis 需求分析 (包括学习新技术) 120 360
·Design Spec 生成设计文档 30 40
·Design Review 设计复审 20 30
· Coding Standard 代码规范 (为目前的开发制定合适的规范) 30 30
Design 具体设计 120 150
·Coding 具体编码 300 360
· Code Review 代码复审 60 120
·Test 测试(自我测试,修改代码,提交修改) 200 150
·Reporting 报告 120 150
·Test Report 测试报告 100 120
·Size Measurement 计算工作量 10 10
·Postmortem & Process Improvement Plan 事后总结, 并提出过程改进计划 50 50
合计 2440 2760

4、解题思路描述与设计实现说明


  • 网络接口的使用

    • 通过HTTP请求Get或Post方式请求Json数据,然后解析JSON格式
    • 参考: address1 address2
  • 代码组织与内部实现设计(类图)


    shisanshui类内函数 功能
    pro_work() 开始预处理出每种组合
    fun() 每次游戏开始
    data_in() 开局输入
    data_out() 出牌
    judge() 计算牌型价值
    cmp_all() 选出牌型进行博弈
    deal_head()、deal_mid()、deal_tail() 计算、判断三墩大小类型
  • 算法思路

    • 取所有组合(组合情况数量=(13C5)*(8C3)不是很大约7e4),每种牌型都有对应价值

    • 枚举所有组合,判定每种摆牌总价值,不合法倒水牌直接筛掉

    • 取总价值最大的那些摆牌,进行互相博弈,最后取最大的作为答案

      实现流程图:


5、关键代码解释

a.

struct cards{

  int rank;
  
  int val;
  
  char poker[5];
  
}
  • 将牌转化为数字价值存储处理
  • 每张牌价值为:X*100+Y
  • X:不同花色记1、2、3、4
  • Y:A按14,2~K 按02~13

b.

void pro_work(){
  for(int i=1;i<=13;i++)
  
  for(int ii=i+1;ii<=13;ii++)
  
  for(int iii=ii+1;iii<=13;iii++)
  
  for(int iiii=iii+1;iiii<=13;iiii++)
  
  for(int iiiii=iiii+1;iiiii<=13;iiiii++){
  …………
 
}





for(int x=1;x<=13;x++){

  if(!flag[x]){
  
    for(int y=x+1;y<=13;y++){
    
      if(!flag[y]){
      
        for(int z=y+1;z<=13;z++){
        
        …………

}       
  • 用循环取牌型组合
  • 利用x+1细节降低要跑的次数,要跑次数等于组合数量( 13 C 5 )*( 8 C 3 )
  • 循环用字符串打表写的,怕写dfs()容易出问题,debug比较浪费时间,加上数据比较少,所以用循环写

c.

deal_head();

deal_mid();

deal_tail();
  • 处理三墩牌型,牌面最大值(对应牌型的最大值)
  • 对于三墩中牌型相同,牌型对应最大值相等,不必比较次大牌,因为必定存在牌型价值大的情况,使得三墩存在相同牌型、最大牌面相等导致取出组合倒水的情况必定被剪掉

d.

while(select.top().tolval<aans.tolval){

	select.pop();

}
  • 只取牌型价值最大的情况进行互相比较pk
  • 因为存在三墩都大翻倍的规则,存在一个比较普通取牌,对于所有情况互相竞技,这种普通取排在大多数杂牌上能赢得6水,使得牌型价值不是很高的牌能赢得更多,而掩盖了牌型价值更高的取法的优势
  • 所以只考虑牌型价值最大的几副摆牌之间进行博弈,只取牌型价值最大互相博弈
  • 博弈策略略不同于规则,只比较每墩对应牌面最大牌型那张;(这样优势其一在于对于像葫芦中对子可能很大而首墩对子很小情况被pk下去,而首墩更大情况会被采纳)

6、性能分析与改进

  • 描述你改进的思路

    • 预处理出所有组合若在在线进行连续多局情况下,可只处理出取的组合下标重复利用
    • judge()倒水牌判断可在deal_head()、deal_mid()、deal_tail()之间先判断,直接先return,不在做后面的无用功
    • 对于三墩中,必然存在三墩某一墩重复的情况,从枚举组合顺序入手,减少取牌、判每一墩重复牌次数
  • 展示性能分析图和程序中消耗最大的函数


7、单元测试

  • 展示出项目部分单元测试代码,并说明测试的函数,构造测试数据的思路

  • 构造的数据:

    • #5 #6 $A $3 $2 &3 *4 &A *A *10 #10 $K &K
  • 得到输出:

    • $K &K $3
    • $2 &3 *4 #5 #6
    • $A &A *A *10 #10
  • 构造数据的思路:

    • 牌能有对子,又有能构成顺子的散牌,散牌中又有能够被拆掉换对子
    • 牌里有葫芦,除了构造葫芦之外还能留出多余的对子
    • 正常人摆牌一般情况肯定希望保证有葫芦,给葫芦的对子尽量小,顺子又不被破坏,顺子不被破坏就希望首墩尽量大
  • 测试函数:

    希望函数能够judge能尽量被覆盖提高代码利用率


8、贴出Github的代码签入记录


9、遇到的代码模块异常或结对困难及解决方法

  • 问题描述
    • 出现牌型判断错误情况
    • 没有出现预期摆牌
    • 选择出摆拍方式有显然更优的摆拍
  • 做过哪些尝试
    • deal_head()、deal_mid()、deal_tail()分离出逐行审查
    • 算法策略部分改变
    • 算法策略优化
  • 解决
    • 发现temp值每次处理时未初始化加上杂牌值价值为0的情况没特判,进行初始化和更改
    • cmp_all() 需要比较博弈摆牌总数太大,出现性价比比较低的牌由于三墩都大三获利太大,牌型更优的摆拍不能凸显出来,减少需要博弈的摆牌数量。
    • 细节处理,cmp_all() 只比较牌型价值最大的摆牌,优化博弈积分细节,使得更优的组合能被选出
  • 有何收获
    • 初始化很重要,所有情况都要考虑周到
    • 十三水同一副牌,不同摆法之间互相博弈的贪心

10、评价你的队友

  • 值得学习的地方
    • 非常积极,设计UI想法非常丰富,找资源能力很强
  • 需要改进的地方
    • 慢点搞,跟不上了,等等我

11、学习进度条


第N周 新增代码(行) 累计代码(行) 本周学习耗时(小时) 累计学习耗时(小时) 重要成长
1 260 260 8 8 牌价值转成数字思路
2 296 556 20 28 取所有组合快速方法
3 485 1041 18 46 c++get、post
4
5


原文地址:https://www.cnblogs.com/gp131415/p/11679410.html