斗地主AI算法——第七章の被动出牌(1)

哎,之前扯了那么多蛋,终于讲出牌了!

本章开始讲被动出牌的逻辑算法。首先我们先把架子搭起来,被动出牌我们肯定是要知道场上目前打出的是什么牌型。

在第二章数据结构里我们定义过,游戏全局类里面有一个存放当前牌型结构的成员,即

 

[cpp]  view plain  copy
 
  1. //当前打出牌的类型数据,被动出牌时玩家根据这里做出筛选  
  2. CardGroupData uctNowCardGroup;  


我们即将通过他进行类型的筛选,所以肯定是要枚举各类牌型的,也就是这个样子的。

 

 

 

是的不要质疑!就是这个样子的~~

 

当然了,虽然是2.0初级版,我们还是要给予一定的灵性的,比如说当最后只剩两手牌且存在王炸的话,王炸优先出。

 

[cpp]  view plain  copy
 
  1. /*王炸——当前策略只处理王炸作为倒数第二手的优先出牌逻辑,后续版本会在此基础上优化*/  
  2. if (clsHandCardData.value_aHandCardList[17] > 0 && clsHandCardData.value_aHandCardList[16] > 0)  
  3. {  
  4.   
  5.     clsHandCardData.value_aHandCardList[17] --;  
  6.     clsHandCardData.value_aHandCardList[16] --;  
  7.     clsHandCardData.nHandCardCount -= 2;  
  8.     HandCardValue tmpHandCardValue = get_HandCardValue(clsHandCardData);  
  9.     clsHandCardData.value_aHandCardList[16] ++;  
  10.     clsHandCardData.value_aHandCardList[17] ++;  
  11.     clsHandCardData.nHandCardCount += 2;  
  12.     if (tmpHandCardValue.NeedRound == 1)  
  13.     {  
  14.         clsHandCardData.value_nPutCardList.push_back(17);  
  15.         clsHandCardData.value_nPutCardList.push_back(16);  
  16.         clsHandCardData.uctPutCardType = clsGameSituation.uctNowCardGroup = get_GroupData(cgKING_CARD, 17, 2);  
  17.         return;  
  18.     }  
  19. }  


算法思路:若存在手牌17(大王)和16(小王),那么先去除这两张牌

 

然后通过get_HandCardValue获取剩余轮次。

再回溯到原有状态。若只剩一手,则打出王炸。

出牌的操作也很简单,将需要打出的牌进入clsHandCardData.value_nPutCardList数组,且通过第四章提到的get_GroupData函数获取类型结构再赋值给手牌类以及游戏全局类相应的成员变量。当确定好出牌策略后,直接return。因为被动出牌的分支只会走一个,为了节约时间,所以每个分支里都有return,若没有走入任何分支则视为错误数据。

 

我们先把最简单的类型写出来,就是别人出王炸时的策略。

[cpp]  view plain  copy
 
  1. //王炸类型 人都王炸了你还出个毛  
  2. else if (clsGameSituation.uctNowCardGroup.cgType == cgKING_CARD)  
  3. {  
  4.     clsHandCardData.uctPutCardType = get_GroupData(cgZERO, 0, 0);  
  5.     return;  
  6. }  

 

 

怎么样,是不是很简单?

 

若不出牌,我们只更新自己手牌类型就好了。若出牌时,不但要更新自己手牌信息,也要更新游戏全局类里面的当前出牌信息。不过我更推荐后期嵌入的时候通过服务器来获取当前出牌的信息。比如我的测试函数里会加上:

 

[cpp]  view plain  copy
 
  1. if (arrHandCardData[indexID].uctPutCardType.cgType != cgZERO)  
  2. {  
  3.     clsGameSituation.nCardDroit = indexID;  
  4.     clsGameSituation.uctNowCardGroup = arrHandCardData[indexID].uctPutCardType;  
  5. }  

 

另外,出牌前记得清空一下出牌序列,就是在一开始加:

 

[cpp]  view plain  copy
 
  1. clsHandCardData.ClearPutCardList();  

 

 

所以,整个函数的架子是这样的,假设我们啥都管不上。

 

[cpp]  view plain  copy
 
  1. /* 
  2. 2.0版本策略  根据场上形势决定当前预打出的手牌——被动出牌 
  3. */  
  4. void get_PutCardList_2_limit(GameSituation &clsGameSituation, HandCardData &clsHandCardData)  
  5. {  
  6.     clsHandCardData.ClearPutCardList();  
  7.   
  8.   
  9.     /*王炸——当前策略只处理王炸作为倒数第二手的优先出牌逻辑,后续版本会在此基础上优化*/  
  10.     if (clsHandCardData.value_aHandCardList[17] > 0 && clsHandCardData.value_aHandCardList[16] > 0)  
  11.     {  
  12.   
  13.         clsHandCardData.value_aHandCardList[17] --;  
  14.         clsHandCardData.value_aHandCardList[16] --;  
  15.         clsHandCardData.nHandCardCount -= 2;  
  16.         HandCardValue tmpHandCardValue = get_HandCardValue(clsHandCardData);  
  17.         clsHandCardData.value_aHandCardList[16] ++;  
  18.         clsHandCardData.value_aHandCardList[17] ++;  
  19.         clsHandCardData.nHandCardCount += 2;  
  20.         if (tmpHandCardValue.NeedRound == 1)  
  21.         {  
  22.             clsHandCardData.value_nPutCardList.push_back(17);  
  23.             clsHandCardData.value_nPutCardList.push_back(16);  
  24.             clsHandCardData.uctPutCardType = clsGameSituation.uctNowCardGroup = get_GroupData(cgKING_CARD, 17, 2);  
  25.             return;  
  26.         }  
  27.     }  
  28.   
  29.   
  30.     //错误牌型  不出  
  31.     if (clsGameSituation.uctNowCardGroup.cgType == cgERROR)  
  32.     {  
  33.         clsHandCardData.uctPutCardType = get_GroupData(cgERROR, 0, 0);  
  34.         return;  
  35.     }  
  36.     //不出牌型,在被动出牌策略里也是错误数据 不出  
  37.     else if (clsGameSituation.uctNowCardGroup.cgType == cgZERO)  
  38.     {  
  39.         clsHandCardData.uctPutCardType = get_GroupData(cgZERO, 0, 0);  
  40.         return;  
  41.     }  
  42.     //单牌类型  
  43.     else if (clsGameSituation.uctNowCardGroup.cgType == cgSINGLE)  
  44.     {  
  45.         //管不上  
  46.         clsHandCardData.uctPutCardType = get_GroupData(cgZERO, 0, 0);  
  47.         return;  
  48.           
  49.     }  
  50.     //对牌类型  
  51.     else if (clsGameSituation.uctNowCardGroup.cgType == cgDOUBLE)  
  52.     {  
  53.         //管不上  
  54.         clsHandCardData.uctPutCardType = get_GroupData(cgZERO, 0, 0);  
  55.         return;  
  56.     }  
  57.     //三牌类型  
  58.     else if (clsGameSituation.uctNowCardGroup.cgType == cgTHREE)  
  59.     {  
  60.   
  61.         //管不上  
  62.         clsHandCardData.uctPutCardType = get_GroupData(cgZERO, 0, 0);  
  63.         return;  
  64.     }  
  65.     //单连类型  
  66.     else if (clsGameSituation.uctNowCardGroup.cgType == cgSINGLE_LINE)  
  67.     {  
  68.         //管不上  
  69.         clsHandCardData.uctPutCardType = get_GroupData(cgZERO, 0, 0);  
  70.         return;  
  71.     }  
  72.     //对连类型  
  73.     else if (clsGameSituation.uctNowCardGroup.cgType == cgDOUBLE_LINE)  
  74.     {  
  75.         //管不上  
  76.         clsHandCardData.uctPutCardType = get_GroupData(cgZERO, 0, 0);  
  77.         return;  
  78.   
  79.     }  
  80.     //三连类型  
  81.     else if (clsGameSituation.uctNowCardGroup.cgType == cgTHREE_LINE)  
  82.     {     
  83.     //管不上  
  84.         clsHandCardData.uctPutCardType = get_GroupData(cgZERO, 0, 0);  
  85.         return;  
  86.     }  
  87.     //三带一单  
  88.     else if (clsGameSituation.uctNowCardGroup.cgType == cgTHREE_TAKE_ONE)  
  89.     {  
  90.         //管不上  
  91.         clsHandCardData.uctPutCardType = get_GroupData(cgZERO, 0, 0);  
  92.         return;  
  93.     }  
  94.     //三带一对  
  95.     else if (clsGameSituation.uctNowCardGroup.cgType == cgTHREE_TAKE_TWO)  
  96.     {  
  97.         //管不上  
  98.         clsHandCardData.uctPutCardType = get_GroupData(cgZERO, 0, 0);  
  99.         return;  
  100.     }  
  101.     //三带一单连  
  102.     else if (clsGameSituation.uctNowCardGroup.cgType == cgTHREE_TAKE_ONE_LINE)  
  103.     {  
  104.         //管不上  
  105.         clsHandCardData.uctPutCardType = get_GroupData(cgZERO, 0, 0);  
  106.         return;  
  107.     }  
  108.     //三带一对连  
  109.     else if (clsGameSituation.uctNowCardGroup.cgType == cgTHREE_TAKE_TWO_LINE)  
  110.     {  
  111.         //管不上  
  112.         clsHandCardData.uctPutCardType = get_GroupData(cgZERO, 0, 0);  
  113.         return;  
  114.     }  
  115.     //四带两单  
  116.     else if (clsGameSituation.uctNowCardGroup.cgType == cgFOUR_TAKE_ONE)  
  117.     {  
  118.         //管不上  
  119.         clsHandCardData.uctPutCardType = get_GroupData(cgZERO, 0, 0);  
  120.         return;  
  121.     }  
  122.     //四带两对  
  123.     else if (clsGameSituation.uctNowCardGroup.cgType == cgFOUR_TAKE_TWO)  
  124.     {  
  125.         //管不上  
  126.         clsHandCardData.uctPutCardType = get_GroupData(cgZERO, 0, 0);  
  127.         return;  
  128.     }  
  129.     //炸弹类型   
  130.     else if (clsGameSituation.uctNowCardGroup.cgType == cgBOMB_CARD)  
  131.     {     
  132.         //管不上  
  133.         clsHandCardData.uctPutCardType = get_GroupData(cgZERO, 0, 0);  
  134.         return;   
  135.     }  
  136.     //王炸类型 人都王炸了你还出个毛  
  137.     else if (clsGameSituation.uctNowCardGroup.cgType == cgKING_CARD)  
  138.     {  
  139.         clsHandCardData.uctPutCardType = get_GroupData(cgZERO, 0, 0);  
  140.         return;  
  141.     }  
  142.     //异常处理 不出  
  143.     else  
  144.     {  
  145.         clsHandCardData.uctPutCardType = get_GroupData(cgZERO, 0, 0);  
  146.     }  
  147.     return;  
  148. }  

 

 

当然,啥都管不上肯定是不行的,所以接下来我们会填充各种牌型的策略算法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值