斗地主AI算法——第六章の牌型判断

本章实现了上一章提到的检查当前是否只是一手牌函数ins_SurCardsType

 

 

[cpp] view plain copy
 
  1. /* 
  2. 检查剩余的牌是否只是一手牌 
  3.  
  4. 是:  返回手牌类型数据 
  5. 不是:返回错误类型(cgERROR) 
  6. */  
  7. CardGroupData ins_SurCardsType(int arr[]);  

 

 

输入很简单,就是一个状态数组。输出是手牌类型结构

 

[cpp] view plain copy
 
  1. //牌型组合数据结构  
  2. struct CardGroupData  
  3. {  
  4.     //枚举类型  
  5.     CardGroupType cgType=cgERROR;  
  6.     //该牌的价值  
  7.     int  nValue=0;  
  8.     //含牌的个数  
  9.     int  nCount=0;  
  10.     //牌中决定大小的牌值,用于对比  
  11.     int nMaxCard=0;  
  12.   
  13. };  

 

 

其中  cgType通过枚举获取,nValue计算规则参考第四章权值定义,nCount可以通过引入数组算出,nMaxCard是用于比大小的那个牌值。

首先我们要计算出剩余手牌个数,因为这样便于快速筛选分支。

 

 

[cpp] view plain copy
 
  1. int nCount = 0;  
  2. for (int i = 3; i < 18; i++)  
  3. {  
  4.     nCount += arr[i];  
  5. }  
  6.   
  7. CardGroupData retCardGroupData;  
  8. retCardGroupData.nCount = nCount;  


以单牌为例,若该牌型满足单牌,则nCount==1,然后我们再找出那张牌。

 

 

[cpp] view plain copy
 
  1. //单牌类型  
  2. if (nCount == 1)  
  3. {  
  4.     //用于验证的变量  
  5.     int prov = 0;  
  6.     int SumValue = 0;  
  7.     for (int i = 3; i < 18; i++)  
  8.     {  
  9.         if (arr[i] == 1)  
  10.         {  
  11.             SumValue = i - 10;  
  12.             prov++;  
  13.             retCardGroupData.nMaxCard = i;  
  14.         }  
  15.     }  
  16.     if (prov == 1)  
  17.     {  
  18.         retCardGroupData.cgType = cgSINGLE;  
  19.         retCardGroupData.nValue= SumValue;  
  20.         return retCardGroupData;  
  21.     }  
  22. }  

 

 

对牌,三牌,炸弹同理。

 

三带一的话需要设置两个验证变量,例如三带一单

 

[cpp] view plain copy
 
  1. if (nCount == 4)  
  2.     {  
  3.         //用于验证的变量  
  4.         int prov1 = 0;  
  5.         int prov2 = 0;  
  6.         int SumValue = 0;  
  7.         for (int i = 3; i < 18; i++)  
  8.         {  
  9.             if (arr[i] == 3)  
  10.             {  
  11.                 SumValue = i - 10;  
  12.                 prov1++;  
  13.                 retCardGroupData.nMaxCard = i;  
  14.   
  15.             }  
  16.             if (arr[i] == 1)  
  17.             {  
  18.                 prov2++;  
  19.             }  
  20.   
  21.         }  
  22.         if (prov1 == 1 && prov2 == 1)  
  23.         {  
  24.             retCardGroupData.cgType = cgTHREE_TAKE_ONE;  
  25.             retCardGroupData.nValue = SumValue;  
  26.             return retCardGroupData;  
  27.         }  
  28.     }  


三带一对

 

 

[cpp] view plain copy
 
  1. if (nCount == 5)  
  2. {  
  3.     //用于验证的变量  
  4.     int prov1 = 0;  
  5.     int prov2 = 0;  
  6.     int SumValue = 0;  
  7.     for (int i = 3; i < 16; i++)  
  8.     {  
  9.         if (arr[i] == 3)  
  10.         {  
  11.             SumValue = i - 10;  
  12.             prov1++;  
  13.             retCardGroupData.nMaxCard = i;  
  14.   
  15.         }  
  16.         if (arr[i] == 2)  
  17.         {  
  18.             prov2++;  
  19.   
  20.         }  
  21.     }  

 

 

这里我们看,循环改为3~15,因为三牌、对牌是不包括王的。

 

四带二同理,不过四带二要考虑到带出去的那两张牌型是不是相同

 

[cpp] view plain copy
 
  1. if (nCount == 6)  
  2. {  
  3.     //用于验证的变量  
  4.     int prov1 = 0;  
  5.     int prov2 = 0;  
  6.     int SumValue = 0;  
  7.     for (int i = 3; i < 18; i++)  
  8.     {  
  9.         if (arr[i] == 4)  
  10.         {  
  11.             SumValue = (i - 3) / 2;  
  12.             prov1++;  
  13.             retCardGroupData.nMaxCard = i;  
  14.   
  15.         }  
  16.         if (arr[i] == 1|| arr[i] == 2)  
  17.         {  
  18.             prov2+= arr[i];  
  19.         }  
  20.     }  
  21.   
  22.     if (prov1 == 1 && prov2 == 2)  
  23.     {  
  24.         retCardGroupData.cgType = cgFOUR_TAKE_ONE;  
  25.         retCardGroupData.nValue = SumValue;  
  26.         return retCardGroupData;  
  27.     }  
  28. }  


判断顺子的话用一个变量记录长度,若当前i值等于0并且之前存在i大于0的情况下,即这个长度就是顺子的长度

 

例如单连:

 

[cpp] view plain copy
 
  1. if (nCount >= 5)  
  2. {  
  3.     //用于验证的变量  
  4.     int prov = 0;  
  5.     int SumValue = 0;  
  6.     int i;  
  7.     for (i = 3; i < 15; i++)  
  8.     {  
  9.         if (arr[i] == 1)  
  10.         {  
  11.             prov++;  
  12.         }  
  13.         else  
  14.         {  
  15.             if (prov != 0)  
  16.             {  
  17.                 break;  
  18.             }  
  19.   
  20.         }  
  21.     }  
  22.     SumValue = i - 10;  
  23.   
  24.     if (prov == nCount)  
  25.     {  
  26.         retCardGroupData.nMaxCard = i-1;  
  27.         retCardGroupData.cgType = cgSINGLE_LINE;  
  28.         retCardGroupData.nValue = SumValue;  
  29.         return retCardGroupData;  
  30.     }  
  31. }  



王炸就更好判断了,直接判断arr[17]和arr[16]就好了

 

 

下面贴出完整代码:

 

 

[cpp] view plain copy
 
  1. /* 
  2. 检查剩余的牌是否只是一手牌 
  3.  
  4. 是:  返回手牌类型数据 
  5. 不是:返回错误类型(cgERROR) 
  6. */  
  7. CardGroupData ins_SurCardsType(int arr[])  
  8. {  
  9.   
  10.     int nCount = 0;  
  11.     for (int i = 3; i < 18; i++)  
  12.     {  
  13.         nCount += arr[i];  
  14.     }  
  15.   
  16.     CardGroupData retCardGroupData;  
  17.     retCardGroupData.nCount = nCount;  
  18.   
  19.   
  20.     //单牌类型  
  21.     if (nCount == 1)  
  22.     {  
  23.         //用于验证的变量  
  24.         int prov = 0;  
  25.         int SumValue = 0;  
  26.         for (int i = 3; i < 18; i++)  
  27.         {  
  28.             if (arr[i] == 1)  
  29.             {  
  30.                 SumValue = i - 10;  
  31.                 prov++;  
  32.                 retCardGroupData.nMaxCard = i;  
  33.             }  
  34.         }  
  35.         if (prov == 1)  
  36.         {  
  37.             retCardGroupData.cgType = cgSINGLE;  
  38.             retCardGroupData.nValue= SumValue;  
  39.             return retCardGroupData;  
  40.         }  
  41.     }  
  42.     //对牌类型  
  43.     if (nCount == 2)  
  44.     {  
  45.         //用于验证的变量  
  46.         int prov = 0;  
  47.         int SumValue = 0;  
  48.         int i = 0;  
  49.         for (i = 3; i < 16; i++)  
  50.         {  
  51.             if (arr[i] == 2)  
  52.             {  
  53.                 SumValue = i - 10;  
  54.                 prov++;  
  55.                 retCardGroupData.nMaxCard = i;  
  56.             }  
  57.         }  
  58.         if (prov == 1)  
  59.         {  
  60.             retCardGroupData.cgType = cgDOUBLE;  
  61.             retCardGroupData.nValue = SumValue;  
  62.             return retCardGroupData;  
  63.         }  
  64.     }  
  65.     //三条类型  
  66.     if (nCount == 3)  
  67.     {  
  68.         //用于验证的变量  
  69.         int prov = 0;  
  70.         int SumValue = 0;  
  71.         int i = 0;  
  72.         for (i = 3; i < 16; i++)  
  73.         {  
  74.             if (arr[i] == 3)  
  75.             {  
  76.                 SumValue = i - 10;  
  77.                 prov++;  
  78.                 retCardGroupData.nMaxCard = i;  
  79.             }  
  80.         }  
  81.         if (prov == 1)  
  82.         {  
  83.             retCardGroupData.cgType = cgTHREE;  
  84.             retCardGroupData.nValue = SumValue;  
  85.             return retCardGroupData;  
  86.         }  
  87.     }  
  88.     //三带一单  
  89.     if (nCount == 4)  
  90.     {  
  91.         //用于验证的变量  
  92.         int prov1 = 0;  
  93.         int prov2 = 0;  
  94.         int SumValue = 0;  
  95.         for (int i = 3; i < 18; i++)  
  96.         {  
  97.             if (arr[i] == 3)  
  98.             {  
  99.                 SumValue = i - 10;  
  100.                 prov1++;  
  101.                 retCardGroupData.nMaxCard = i;  
  102.   
  103.             }  
  104.             if (arr[i] == 1)  
  105.             {  
  106.                 prov2++;  
  107.             }  
  108.   
  109.         }  
  110.         if (prov1 == 1 && prov2 == 1)  
  111.         {  
  112.             retCardGroupData.cgType = cgTHREE_TAKE_ONE;  
  113.             retCardGroupData.nValue = SumValue;  
  114.             return retCardGroupData;  
  115.         }  
  116.     }  
  117.     //三带一对  
  118.     if (nCount == 5)  
  119.     {  
  120.         //用于验证的变量  
  121.         int prov1 = 0;  
  122.         int prov2 = 0;  
  123.         int SumValue = 0;  
  124.         for (int i = 3; i < 16; i++)  
  125.         {  
  126.             if (arr[i] == 3)  
  127.             {  
  128.                 SumValue = i - 10;  
  129.                 prov1++;  
  130.                 retCardGroupData.nMaxCard = i;  
  131.   
  132.             }  
  133.             if (arr[i] == 2)  
  134.             {  
  135.                 prov2++;  
  136.   
  137.             }  
  138.         }  
  139.         if (prov1 == 1 && prov2 == 1)  
  140.         {  
  141.             retCardGroupData.cgType = cgTHREE_TAKE_TWO;  
  142.             retCardGroupData.nValue = SumValue;  
  143.             return retCardGroupData;  
  144.         }  
  145.     }  
  146.     //四带两单  
  147.     if (nCount == 6)  
  148.     {  
  149.         //用于验证的变量  
  150.         int prov1 = 0;  
  151.         int prov2 = 0;  
  152.         int SumValue = 0;  
  153.         for (int i = 3; i < 18; i++)  
  154.         {  
  155.             if (arr[i] == 4)  
  156.             {  
  157.                 SumValue = (i - 3) / 2;  
  158.                 prov1++;  
  159.                 retCardGroupData.nMaxCard = i;  
  160.   
  161.             }  
  162.             if (arr[i] == 1|| arr[i] == 2)  
  163.             {  
  164.                 prov2+= arr[i];  
  165.             }  
  166.         }  
  167.   
  168.         if (prov1 == 1 && prov2 == 2)  
  169.         {  
  170.             retCardGroupData.cgType = cgFOUR_TAKE_ONE;  
  171.             retCardGroupData.nValue = SumValue;  
  172.             return retCardGroupData;  
  173.         }  
  174.     }  
  175.     //四带两对  
  176.     if (nCount == 8)  
  177.     {  
  178.         //用于验证的变量  
  179.         int prov1 = 0;  
  180.         int prov2 = 0;  
  181.         int SumValue = 0;  
  182.         for (int i = 3; i < 16; i++)  
  183.         {  
  184.             if (arr[i] == 4)  
  185.             {  
  186.                 SumValue = (i - 3) / 2;  
  187.   
  188.                 prov1++;  
  189.                 retCardGroupData.nMaxCard = i;  
  190.             }  
  191.             if (arr[i] == 2|| arr[i] == 4)  
  192.             {  
  193.                 prov2+= arr[i]/2;  
  194.   
  195.             }  
  196.         }  
  197.                //注意这里prov2==4因为四牌也是两个对  
  198.         if (prov1 == 1 && prov2 == 4)  
  199.         {  
  200.             retCardGroupData.cgType = cgFOUR_TAKE_TWO;  
  201.             retCardGroupData.nValue = SumValue;  
  202.             return retCardGroupData;  
  203.         }  
  204.     }  
  205.     //炸弹类型  
  206.     if (nCount == 4)  
  207.     {  
  208.         //用于验证的变量  
  209.         int prov = 0;  
  210.         int SumValue = 0;  
  211.         for (int i = 3; i < 16; i++)  
  212.         {  
  213.             if (arr[i] == 4)  
  214.             {  
  215.                 SumValue += i - 3 + 7;  
  216.                 prov++;  
  217.                 retCardGroupData.nMaxCard = i;  
  218.             }  
  219.         }  
  220.         if (prov == 1)  
  221.         {  
  222.             retCardGroupData.cgType = cgBOMB_CARD;  
  223.             retCardGroupData.nValue = SumValue;  
  224.             return retCardGroupData;  
  225.         }  
  226.     }  
  227.     //王炸类型  
  228.     if (nCount == 2)  
  229.     {  
  230.         int SumValue = 0;  
  231.         if (arr[17] > 0 && arr[16] > 0)  
  232.         {  
  233.             SumValue = 20;  
  234.             retCardGroupData.nMaxCard = 17;  
  235.             retCardGroupData.cgType = cgKING_CARD;  
  236.             retCardGroupData.nValue = SumValue;  
  237.             return retCardGroupData;  
  238.         }  
  239.     }  
  240.     //单连类型  
  241.     if (nCount >= 5)  
  242.     {  
  243.         //用于验证的变量  
  244.         int prov = 0;  
  245.         int SumValue = 0;  
  246.         int i;  
  247.         for (i = 3; i < 15; i++)  
  248.         {  
  249.             if (arr[i] == 1)  
  250.             {  
  251.                 prov++;  
  252.             }  
  253.             else  
  254.             {  
  255.                 if (prov != 0)  
  256.                 {  
  257.                     break;  
  258.                 }  
  259.   
  260.             }  
  261.         }  
  262.         SumValue = i - 10;  
  263.   
  264.         if (prov == nCount)  
  265.         {  
  266.             retCardGroupData.nMaxCard = i-1;  
  267.             retCardGroupData.cgType = cgSINGLE_LINE;  
  268.             retCardGroupData.nValue = SumValue;  
  269.             return retCardGroupData;  
  270.         }  
  271.     }  
  272.     //对连类型  
  273.     if (nCount >= 6)  
  274.     {  
  275.         //用于验证的变量  
  276.         int prov = 0;  
  277.         int SumValue = 0;  
  278.         int i;  
  279.         for (i = 3; i < 15; i++)  
  280.         {  
  281.             if (arr[i] == 2)  
  282.             {  
  283.                 prov++;  
  284.             }  
  285.             else  
  286.             {  
  287.                 if (prov != 0)  
  288.                 {  
  289.                     break;  
  290.                 }  
  291.   
  292.             }  
  293.         }  
  294.         SumValue = i - 10;  
  295.   
  296.         if (prov * 2 == nCount)  
  297.         {  
  298.             retCardGroupData.nMaxCard = i - 1;  
  299.             retCardGroupData.cgType = cgDOUBLE_LINE;  
  300.             retCardGroupData.nValue = SumValue;  
  301.             return retCardGroupData;  
  302.         }  
  303.     }  
  304.     //三连类型  
  305.     if (nCount >= 6)  
  306.     {  
  307.         //用于验证的变量  
  308.         int prov = 0;  
  309.   
  310.         int SumValue = 0;  
  311.         int i;  
  312.         for (i = 3; i < 15; i++)  
  313.         {  
  314.             if (arr[i] == 3)  
  315.             {  
  316.                 prov++;  
  317.             }  
  318.             else  
  319.             {  
  320.                 if (prov != 0)  
  321.                 {  
  322.                     break;  
  323.                 }  
  324.   
  325.             }  
  326.         }  
  327.         SumValue = (i - 3) / 2;  
  328.   
  329.         if (prov * 3 == nCount)  
  330.         {  
  331.             retCardGroupData.nMaxCard = i - 1;  
  332.             retCardGroupData.cgType = cgTHREE_LINE;  
  333.             retCardGroupData.nValue = SumValue;  
  334.             return retCardGroupData;  
  335.         }  
  336.     }  
  337.     //三带一连类型  
  338.     if (nCount >= 8)  
  339.     {  
  340.         //用于验证的变量  
  341.         int prov1 = 0;  
  342.         int SumValue = 0;  
  343.         int i, j;  
  344.         for (i = 3; i < 15; i++)  
  345.         {  
  346.             if (arr[i] >= 3)  
  347.             {  
  348.                 prov1++;  
  349.             }  
  350.             else  
  351.             {  
  352.                 if (prov1 != 0)  
  353.                 {  
  354.                     break;  
  355.                 }  
  356.   
  357.             }  
  358.         }  
  359.         SumValue = (i - 3)/2;  
  360.         if (prov1 * 4 == nCount)  
  361.         {  
  362.             retCardGroupData.nMaxCard = i - 1;  
  363.             retCardGroupData.cgType = cgTHREE_TAKE_ONE_LINE;  
  364.             retCardGroupData.nValue = SumValue;  
  365.             return retCardGroupData;  
  366.         }  
  367.   
  368.     }  
  369.     //三带二连类型  
  370.     if (nCount >= 10)  
  371.     {  
  372.         //用于验证的变量  
  373.         int prov1 = 0;  
  374.         int prov2 = 0;  
  375.         int SumValue = 0;  
  376.         int i, j;  
  377.         for (i = 3; i < 15; i++)  
  378.         {  
  379.             if (arr[i] == 3)  
  380.             {  
  381.                 prov1++;  
  382.             }  
  383.             else  
  384.             {  
  385.                 if (prov1 != 0)  
  386.                 {  
  387.                     break;  
  388.                 }  
  389.             }  
  390.         }  
  391.         for (j = 3; j < 16; j++)  
  392.         {  
  393.             if (arr[j] == 2|| arr[j] == 4)  
  394.             {  
  395.                 prov2+= arr[j]/2;  
  396.             }  
  397.         }  
  398.         SumValue = (i - 3) / 2;  
  399.         if (prov1 == prov2&&prov1 * 5 == nCount)  
  400.         {  
  401.             retCardGroupData.nMaxCard = i - 1;  
  402.             retCardGroupData.cgType = cgTHREE_TAKE_TWO_LINE;  
  403.             retCardGroupData.nValue = SumValue;  
  404.             return retCardGroupData;  
  405.         }  
  406.     }  
  407.   
  408.     retCardGroupData.cgType = cgERROR;  
  409.     return retCardGroupData;  
  410. }  
  411.   
  412. /* 
  413. 检查剩余的牌是否只是一手牌(vector重载) 
  414.  
  415. 是:  返回手牌类型数据 
  416. 不是:返回错误类型(cgERROR) 
  417. */  
  418. CardGroupData ins_SurCardsType(vector<int>list)  
  419. {  
  420.     int arr[18];  
  421.     memset(arr, 0, sizeof(arr));  
  422.     for (vector<int>::iterator iter = list.begin(); iter != list.end(); iter++)  
  423.     {  
  424.         arr[*iter]++;  
  425.     }  
  426.     return ins_SurCardsType(arr);  
  427. }  

 

 

怎么样,这么多牌型枚举是不是很头疼?放心吧,接下来的主动出牌算法、被动出牌算法的枚举会更头疼!

所以~从下一章开始我们就要讲出牌的策略了,首先是被动出牌。

 

敬请关注下一章:斗地主AI算法——第七章の被动出牌(1)

posted on 2018-06-12 22:36  &大飞  阅读(1440)  评论(0编辑  收藏  举报

导航