斗地主AI算法——第十四章の主动出牌(3)

上一章已经排除了飞机、三带等牌型,那么除去炸弹王炸以外,我们只剩下单牌、对牌、三牌以及单顺、双顺、三顺了。

 

首先说单牌、对牌、三牌。其逻辑基本一样,只是出牌的个数有差别,即:如果该i牌数量满足这种牌型要求,即先打出,计算其剩余价值。

 

[cpp] view plain copy
 
  1. //出单牌  
  2. if (clsHandCardData.value_aHandCardList[i] > 0)  
  3. {  
  4.     clsHandCardData.value_aHandCardList[i]--;  
  5.     clsHandCardData.nHandCardCount--;  
  6.     HandCardValue tmpHandCardValue = get_HandCardValue(clsHandCardData);  
  7.     clsHandCardData.value_aHandCardList[i]++;  
  8.     clsHandCardData.nHandCardCount++;  
  9.     if ((BestHandCardValue.SumValue - (BestHandCardValue.NeedRound * 7)) <= (tmpHandCardValue.SumValue - (tmpHandCardValue.NeedRound * 7)))  
  10.     {  
  11.         BestHandCardValue = tmpHandCardValue;  
  12.         BestCardGroup= get_GroupData(cgSINGLE, i, 1);  
  13.     }  
  14. }  
  15. //出对牌  
  16. if (clsHandCardData.value_aHandCardList[i] > 1)  
  17. {  
  18.     //尝试打出一对牌,估算剩余手牌价值  
  19.     clsHandCardData.value_aHandCardList[i] -= 2;  
  20.     clsHandCardData.nHandCardCount -= 2;  
  21.     HandCardValue tmpHandCardValue = get_HandCardValue(clsHandCardData);  
  22.     clsHandCardData.value_aHandCardList[i] += 2;  
  23.     clsHandCardData.nHandCardCount += 2;  
  24.   
  25.     //选取总权值-轮次*7值最高的策略  因为我们认为剩余的手牌需要n次控手的机会才能出完,若轮次牌型很大(如炸弹) 则其-7的价值也会为正  
  26.     if ((BestHandCardValue.SumValue - (BestHandCardValue.NeedRound * 7)) <= (tmpHandCardValue.SumValue - (tmpHandCardValue.NeedRound * 7)))  
  27.     {  
  28.         BestHandCardValue = tmpHandCardValue;  
  29.         BestCardGroup = get_GroupData(cgDOUBLE, i, 2);  
  30.     }  
  31. }  
  32. //出三牌  
  33. if (clsHandCardData.value_aHandCardList[i] > 2)  
  34. {  
  35.     clsHandCardData.value_aHandCardList[i] -= 3;  
  36.     clsHandCardData.nHandCardCount -= 3;  
  37.     HandCardValue tmpHandCardValue = get_HandCardValue(clsHandCardData);  
  38.     clsHandCardData.value_aHandCardList[i] += 3;  
  39.     clsHandCardData.nHandCardCount += 3;  
  40.   
  41.     //选取总权值-轮次*7值最高的策略  因为我们认为剩余的手牌需要n次控手的机会才能出完,若轮次牌型很大(如炸弹) 则其-7的价值也会为正  
  42.     if ((BestHandCardValue.SumValue - (BestHandCardValue.NeedRound * 7)) <= (tmpHandCardValue.SumValue - (tmpHandCardValue.NeedRound * 7)))  
  43.     {  
  44.         BestHandCardValue = tmpHandCardValue;  
  45.         BestCardGroup = get_GroupData(cgTHREE, i, 3);  
  46.     }  
  47. }  


至于顺子的算法,和被动出牌的有一点点差别,就是因为没有了数量限制,所以需要遍历以i牌为起点可以组成的所有顺子。

 

 

[cpp] view plain copy
 
  1. //出单顺  
  2.             if (clsHandCardData.value_aHandCardList[i] > 0)  
  3.             {  
  4.                 int prov = 0;  
  5.                 for (int j = i; j < 15; j++)  
  6.                 {  
  7.                     if(clsHandCardData.value_aHandCardList[j]>0)  
  8.                     {  
  9.                         prov++;  
  10.                     }  
  11.                     else  
  12.                     {  
  13.                         break;  
  14.                     }  
  15.                     if (prov >= 5)  
  16.                     {  
  17.   
  18.                         for (int k = i; k <= j; k++)  
  19.                         {  
  20.                             clsHandCardData.value_aHandCardList[k] --;  
  21.                         }  
  22.                         clsHandCardData.nHandCardCount -= prov;  
  23.                         HandCardValue tmpHandCardValue = get_HandCardValue(clsHandCardData);  
  24.                         for (int k = i; k <= j; k++)  
  25.                         {  
  26.                             clsHandCardData.value_aHandCardList[k] ++;  
  27.                         }  
  28.                         clsHandCardData.nHandCardCount += prov;  
  29.   
  30.                         //选取总权值-轮次*7值最高的策略  因为我们认为剩余的手牌需要n次控手的机会才能出完,若轮次牌型很大(如炸弹) 则其-7的价值也会为正  
  31.                         if ((BestHandCardValue.SumValue - (BestHandCardValue.NeedRound * 7)) <= (tmpHandCardValue.SumValue - (tmpHandCardValue.NeedRound * 7)))  
  32.                         {  
  33.                             BestHandCardValue = tmpHandCardValue;  
  34.                             BestCardGroup = get_GroupData(cgSINGLE_LINE, j, prov);  
  35.                         }  
  36.                     }  
  37.                 }  
  38.                   
  39.             }  
  40.             //出双顺  
  41.             if (clsHandCardData.value_aHandCardList[i] > 1)  
  42.             {  
  43.                 int prov = 0;  
  44.                 for (int j = i; j < 15; j++)  
  45.                 {  
  46.                     if (clsHandCardData.value_aHandCardList[j]>1)  
  47.                     {  
  48.                         prov++;  
  49.                     }  
  50.                     else  
  51.                     {  
  52.                         break;  
  53.                     }  
  54.                     if (prov >= 3)  
  55.                     {  
  56.   
  57.                         for (int k = i; k <= j; k++)  
  58.                         {  
  59.                             clsHandCardData.value_aHandCardList[k] -=2;  
  60.                         }  
  61.                         clsHandCardData.nHandCardCount -= prov*2;  
  62.                         HandCardValue tmpHandCardValue = get_HandCardValue(clsHandCardData);  
  63.                         for (int k = i; k <= j; k++)  
  64.                         {  
  65.                             clsHandCardData.value_aHandCardList[k] +=2;  
  66.                         }  
  67.                         clsHandCardData.nHandCardCount += prov*2;  
  68.   
  69.                         //选取总权值-轮次*7值最高的策略  因为我们认为剩余的手牌需要n次控手的机会才能出完,若轮次牌型很大(如炸弹) 则其-7的价值也会为正  
  70.                         if ((BestHandCardValue.SumValue - (BestHandCardValue.NeedRound * 7)) <= (tmpHandCardValue.SumValue - (tmpHandCardValue.NeedRound * 7)))  
  71.                         {  
  72.                             BestHandCardValue = tmpHandCardValue;  
  73.                             BestCardGroup = get_GroupData(cgDOUBLE_LINE, j, prov*2);  
  74.                         }  
  75.                     }  
  76.                 }  
  77.             }  
  78.             //出三顺  
  79.             if(clsHandCardData.value_aHandCardList[i] > 2)  
  80.             {  
  81.                 int prov = 0;  
  82.                 for (int j = i; j < 15; j++)  
  83.                 {  
  84.                     if (clsHandCardData.value_aHandCardList[j]>2)  
  85.                     {  
  86.                         prov++;  
  87.                     }  
  88.                     else  
  89.                     {  
  90.                         break;  
  91.                     }  
  92.                     if (prov >= 2)  
  93.                     {  
  94.   
  95.                         for (int k = i; k <= j; k++)  
  96.                         {  
  97.                             clsHandCardData.value_aHandCardList[k] -= 3;  
  98.                         }  
  99.                         clsHandCardData.nHandCardCount -= prov * 3;  
  100.                         HandCardValue tmpHandCardValue = get_HandCardValue(clsHandCardData);  
  101.                         for (int k = i; k <= j; k++)  
  102.                         {  
  103.                             clsHandCardData.value_aHandCardList[k] += 3;  
  104.                         }  
  105.                         clsHandCardData.nHandCardCount += prov * 3;  
  106.   
  107.                         //选取总权值-轮次*7值最高的策略  因为我们认为剩余的手牌需要n次控手的机会才能出完,若轮次牌型很大(如炸弹) 则其-7的价值也会为正  
  108.                         if ((BestHandCardValue.SumValue - (BestHandCardValue.NeedRound * 7)) <= (tmpHandCardValue.SumValue - (tmpHandCardValue.NeedRound * 7)))  
  109.                         {  
  110.                             BestHandCardValue = tmpHandCardValue;  
  111.                             BestCardGroup = get_GroupData(cgTHREE_LINE, j, prov * 3);  
  112.                         }  
  113.                     }  
  114.                 }  
  115.             }  


因为本策略是必须解决掉至少一个i牌的,所以出牌操作放在循环内进行,也就是说,只要你不是炸3,若你手牌有3,在处理3时一定会return  就绝对不会再走到4。

 

 

 

[cpp] view plain copy
 
  1. if (BestCardGroup.cgType == cgERROR)  
  2.             {  
  3.   
  4.             }  
  5.             else if (BestCardGroup.cgType == cgSINGLE)  
  6.             {  
  7.                 clsHandCardData.value_nPutCardList.push_back(BestCardGroup.nMaxCard);  
  8.                 clsHandCardData.uctPutCardType = BestCardGroup;  
  9.             }  
  10.             else if (BestCardGroup.cgType == cgDOUBLE)  
  11.             {  
  12.                 clsHandCardData.value_nPutCardList.push_back(BestCardGroup.nMaxCard);  
  13.                 clsHandCardData.value_nPutCardList.push_back(BestCardGroup.nMaxCard);  
  14.                 clsHandCardData.uctPutCardType = BestCardGroup;  
  15.             }  
  16.             else if (BestCardGroup.cgType == cgTHREE)  
  17.             {  
  18.                 clsHandCardData.value_nPutCardList.push_back(BestCardGroup.nMaxCard);  
  19.                 clsHandCardData.value_nPutCardList.push_back(BestCardGroup.nMaxCard);  
  20.                 clsHandCardData.value_nPutCardList.push_back(BestCardGroup.nMaxCard);  
  21.                 clsHandCardData.uctPutCardType = BestCardGroup;  
  22.             }  
  23.             else if (BestCardGroup.cgType == cgSINGLE_LINE)  
  24.             {  
  25.                 for (int j = BestCardGroup.nMaxCard- BestCardGroup.nCount+1; j <= BestCardGroup.nMaxCard; j++)  
  26.                 {  
  27.                     clsHandCardData.value_nPutCardList.push_back(j);  
  28.                 }  
  29.                 clsHandCardData.uctPutCardType = BestCardGroup;  
  30.             }  
  31.             else if (BestCardGroup.cgType == cgDOUBLE_LINE)  
  32.             {  
  33.                 for (int j = BestCardGroup.nMaxCard - (BestCardGroup.nCount/2) + 1; j <= BestCardGroup.nMaxCard; j++)  
  34.                 {  
  35.                     clsHandCardData.value_nPutCardList.push_back(j);  
  36.                     clsHandCardData.value_nPutCardList.push_back(j);  
  37.                 }  
  38.                 clsHandCardData.uctPutCardType = BestCardGroup;  
  39.             }  
  40.             else if (BestCardGroup.cgType == cgTHREE_LINE)  
  41.             {  
  42.                 for (int j = BestCardGroup.nMaxCard - (BestCardGroup.nCount / 3) + 1; j <= BestCardGroup.nMaxCard; j++)  
  43.                 {  
  44.                     clsHandCardData.value_nPutCardList.push_back(j);  
  45.                     clsHandCardData.value_nPutCardList.push_back(j);  
  46.                     clsHandCardData.value_nPutCardList.push_back(j);  
  47.                 }  
  48.                 clsHandCardData.uctPutCardType = BestCardGroup;  
  49.             }  
  50.             else if (BestCardGroup.cgType == cgTHREE_TAKE_ONE)  
  51.             {  
  52.                 clsHandCardData.value_nPutCardList.push_back(BestCardGroup.nMaxCard);  
  53.                 clsHandCardData.value_nPutCardList.push_back(BestCardGroup.nMaxCard);  
  54.                 clsHandCardData.value_nPutCardList.push_back(BestCardGroup.nMaxCard);  
  55.                 clsHandCardData.value_nPutCardList.push_back(tmp_1);  
  56.                 clsHandCardData.uctPutCardType = BestCardGroup;  
  57.             }  
  58.             else if (BestCardGroup.cgType == cgTHREE_TAKE_TWO)  
  59.             {  
  60.                 clsHandCardData.value_nPutCardList.push_back(BestCardGroup.nMaxCard);  
  61.                 clsHandCardData.value_nPutCardList.push_back(BestCardGroup.nMaxCard);  
  62.                 clsHandCardData.value_nPutCardList.push_back(BestCardGroup.nMaxCard);  
  63.                 clsHandCardData.value_nPutCardList.push_back(tmp_1);  
  64.                 clsHandCardData.value_nPutCardList.push_back(tmp_1);  
  65.                 clsHandCardData.uctPutCardType = BestCardGroup;  
  66.             }  
  67.             else if (BestCardGroup.cgType == cgTHREE_TAKE_ONE_LINE)  
  68.             {  
  69.                 for (int j = BestCardGroup.nMaxCard - (BestCardGroup.nCount / 4) + 1; j <= BestCardGroup.nMaxCard; j++)  
  70.                 {  
  71.                     clsHandCardData.value_nPutCardList.push_back(j);  
  72.                     clsHandCardData.value_nPutCardList.push_back(j);  
  73.                     clsHandCardData.value_nPutCardList.push_back(j);  
  74.                 }  
  75.   
  76.                 if (BestCardGroup.nCount / 4 == 2)  
  77.                 {  
  78.                     clsHandCardData.value_nPutCardList.push_back(tmp_1);  
  79.                     clsHandCardData.value_nPutCardList.push_back(tmp_2);  
  80.                 }  
  81.                 if (BestCardGroup.nCount / 4 == 3)  
  82.                 {  
  83.                     clsHandCardData.value_nPutCardList.push_back(tmp_1);  
  84.                     clsHandCardData.value_nPutCardList.push_back(tmp_2);  
  85.                     clsHandCardData.value_nPutCardList.push_back(tmp_3);  
  86.                 }  
  87.                 if (BestCardGroup.nCount / 4 == 4)  
  88.                 {  
  89.                     clsHandCardData.value_nPutCardList.push_back(tmp_1);  
  90.                     clsHandCardData.value_nPutCardList.push_back(tmp_2);  
  91.                     clsHandCardData.value_nPutCardList.push_back(tmp_3);  
  92.                     clsHandCardData.value_nPutCardList.push_back(tmp_4);  
  93.                 }  
  94.   
  95.                 clsHandCardData.uctPutCardType = BestCardGroup;  
  96.             }  
  97.             else if (BestCardGroup.cgType == cgTHREE_TAKE_TWO_LINE)  
  98.             {  
  99.                 for (int j = BestCardGroup.nMaxCard - (BestCardGroup.nCount / 5) + 1; j <= BestCardGroup.nMaxCard; j++)  
  100.                 {  
  101.                     clsHandCardData.value_nPutCardList.push_back(j);  
  102.                     clsHandCardData.value_nPutCardList.push_back(j);  
  103.                     clsHandCardData.value_nPutCardList.push_back(j);  
  104.                 }  
  105.                 if (BestCardGroup.nCount / 5 == 2)  
  106.                 {  
  107.                     clsHandCardData.value_nPutCardList.push_back(tmp_1);  
  108.                     clsHandCardData.value_nPutCardList.push_back(tmp_1);  
  109.                     clsHandCardData.value_nPutCardList.push_back(tmp_2);  
  110.                     clsHandCardData.value_nPutCardList.push_back(tmp_2);  
  111.                 }  
  112.                 if (BestCardGroup.nCount / 5 == 3)  
  113.                 {  
  114.                     clsHandCardData.value_nPutCardList.push_back(tmp_1);  
  115.                     clsHandCardData.value_nPutCardList.push_back(tmp_1);  
  116.                     clsHandCardData.value_nPutCardList.push_back(tmp_2);  
  117.                     clsHandCardData.value_nPutCardList.push_back(tmp_2);  
  118.                     clsHandCardData.value_nPutCardList.push_back(tmp_3);  
  119.                     clsHandCardData.value_nPutCardList.push_back(tmp_3);  
  120.                 }  
  121.                 clsHandCardData.uctPutCardType = BestCardGroup;  
  122.             }  
  123.             return;  

 

 

至此,主动出牌的所有逻辑均已实现,同时整个斗地主算法也基本完成了。接下来我们便可写一些测试模块来进行整合联调。

 

敬请关注下一章:斗地主AI算法——第十五章の测试模块

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

导航