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

上一章我们已经搭好了出牌算法的基本框架,本章主要实现优先处理的三带、飞机等牌型。

首先定义一些基本变量:

 

[cpp] view plain copy
 
  1. //暂存最佳的价值  
  2. HandCardValue BestHandCardValue;  
  3. BestHandCardValue.NeedRound = 20;  
  4. BestHandCardValue.SumValue = MinCardsValue;  
  5. //我们认为不出牌的话会让对手一个轮次,即加一轮(权值减少7)便于后续的对比参考。  
  6. BestHandCardValue.NeedRound += 1;  
  7.   
  8. //暂存最佳的组合  
  9. CardGroupData BestCardGroup;  
  10.   
  11. //带出去的牌  
  12. int tmp_1 = 0;  
  13. int tmp_2 = 0;  
  14. int tmp_3 = 0;  
  15. int tmp_4 = 0;  


因为枚举了牌型,所以实际和被动出牌逻辑都差不多,且没有nMaxCard的限制,所以我们要从3开始遍历。且上一章我们提到,不考虑炸弹拆分的情况。故value_aHandCardList[i]不能等于4。

 

 

[cpp] view plain copy
 
  1. for (int i = 3; i < 16; i++)  
  2.     {  
  3.         //2.0版本策略主动出牌不拆分炸弹,朕自己从来就不打四带二,因为浪  
  4.         if (clsHandCardData.value_aHandCardList[i] != 4)  
  5.         {  
  6.             //出三带一  
  7.             if (clsHandCardData.value_aHandCardList[i] > 2)  
  8.             {  
  9.                 clsHandCardData.value_aHandCardList[i] -= 3;  
  10.                 for (int j = 3; j < 18; j++)  
  11.                 {  
  12.                     if (clsHandCardData.value_aHandCardList[j] > 0 )  
  13.                     {  
  14.                         clsHandCardData.value_aHandCardList[j] -= 1;  
  15.                         clsHandCardData.nHandCardCount -= 4;  
  16.                         HandCardValue tmpHandCardValue = get_HandCardValue(clsHandCardData);  
  17.                         clsHandCardData.value_aHandCardList[j] += 1;  
  18.                         clsHandCardData.nHandCardCount += 4;  
  19.                         //选取总权值-轮次*7值最高的策略  因为我们认为剩余的手牌需要n次控手的机会才能出完,若轮次牌型很大(如炸弹) 则其-7的价值也会为正  
  20.                         if ((BestHandCardValue.SumValue - (BestHandCardValue.NeedRound * 7)) <= (tmpHandCardValue.SumValue - (tmpHandCardValue.NeedRound * 7)))  
  21.                         {  
  22.                             BestHandCardValue = tmpHandCardValue;  
  23.                             BestCardGroup = get_GroupData(cgTHREE_TAKE_ONE, i, 4);  
  24.                             tmp_1 = j;  
  25.                         }  
  26.                     }  
  27.                 }  
  28.                 clsHandCardData.value_aHandCardList[i] += 3;  
  29.             }  
  30.             //出三带二  
  31.             if (clsHandCardData.value_aHandCardList[i] > 2)  
  32.             {  
  33.                 for (int j = 3; j < 16; j++)  
  34.                 {  
  35.                     clsHandCardData.value_aHandCardList[i] -= 3;  
  36.                     if (clsHandCardData.value_aHandCardList[j] > 1)  
  37.                     {  
  38.                         clsHandCardData.value_aHandCardList[j] -= 2;  
  39.                         clsHandCardData.nHandCardCount -= 5;  
  40.                         HandCardValue tmpHandCardValue = get_HandCardValue(clsHandCardData);  
  41.                         clsHandCardData.value_aHandCardList[j] += 2;  
  42.                         clsHandCardData.nHandCardCount += 5;  
  43.                         //选取总权值-轮次*7值最高的策略  因为我们认为剩余的手牌需要n次控手的机会才能出完,若轮次牌型很大(如炸弹) 则其-7的价值也会为正  
  44.                         if ((BestHandCardValue.SumValue - (BestHandCardValue.NeedRound * 7)) <= (tmpHandCardValue.SumValue - (tmpHandCardValue.NeedRound * 7)))  
  45.                         {  
  46.                             BestHandCardValue = tmpHandCardValue;  
  47.                             BestCardGroup = get_GroupData(cgTHREE_TAKE_TWO, i, 5);  
  48.                             tmp_1 = j;  
  49.                         }  
  50.                     }  
  51.                     clsHandCardData.value_aHandCardList[i] += 3;  
  52.                 }  
  53.             }  
  54.             //出四带二单  
  55.             if (clsHandCardData.value_aHandCardList[i] > 3)  
  56.             {  
  57.                 //2.0版本策略主动出牌不拆分炸弹,朕自己从来就不打四带二,因为浪  
  58.             }  
  59.             //出四带二对  
  60.             if (clsHandCardData.value_aHandCardList[i] > 3)  
  61.             {  
  62.                 //2.0版本策略主动出牌不拆分炸弹,朕自己从来就不打四带二,因为浪  
  63.             }  
  64.             //出三带一单连  
  65.             if (clsHandCardData.value_aHandCardList[i] > 2)  
  66.             {  
  67.                 int prov = 0;  
  68.                 for (int j = i; j < 15; j++)  
  69.                 {  
  70.                     if (clsHandCardData.value_aHandCardList[j] > 2)  
  71.                     {  
  72.                         prov++;  
  73.                     }  
  74.                     else  
  75.                     {  
  76.                         break;  
  77.                     }  
  78.                     /*本来想做全排列选取带出的牌然后枚举出最高价值的,但考虑到当飞机长度也就是在2-4之间 
  79.                     所以干脆做三个分支处理算了*/  
  80.                     //为两连飞机  
  81.                     if (prov == 2)  
  82.                     {  
  83.   
  84.                         for (int k = i; k <= j; k++)  
  85.                         {  
  86.                             clsHandCardData.value_aHandCardList[k] -= 3;  
  87.                         }  
  88.                         clsHandCardData.nHandCardCount -= prov * 4;  
  89.                         for (int tmp1 = 3; tmp1 < 18; tmp1++)  
  90.                         {  
  91.                             if (clsHandCardData.value_aHandCardList[tmp1] > 0 )  
  92.                             {  
  93.                                 clsHandCardData.value_aHandCardList[tmp1] -= 1;  
  94.                                 for (int tmp2 = tmp1; tmp2 < 18; tmp2++)  
  95.                                 {  
  96.                                     if (clsHandCardData.value_aHandCardList[tmp2] > 0 )  
  97.                                     {  
  98.                                         clsHandCardData.value_aHandCardList[tmp2] -= 1;  
  99.                                         HandCardValue tmpHandCardValue = get_HandCardValue(clsHandCardData);  
  100.                                       
  101.                                         if ((BestHandCardValue.SumValue - (BestHandCardValue.NeedRound * 7)) <= (tmpHandCardValue.SumValue - (tmpHandCardValue.NeedRound * 7)))  
  102.                                         {  
  103.                                             BestHandCardValue = tmpHandCardValue;  
  104.                                             BestCardGroup = get_GroupData(cgTHREE_TAKE_ONE_LINE, j, prov * 4);  
  105.                                             tmp_1 = tmp1;  
  106.                                             tmp_2 = tmp2;  
  107.   
  108.                                         }  
  109.                                         clsHandCardData.value_aHandCardList[tmp2] += 1;  
  110.                                     }  
  111.                                 }  
  112.                                 clsHandCardData.value_aHandCardList[tmp1] += 1;  
  113.                             }  
  114.                         }  
  115.                         for (int k = i; k <= j; k++)  
  116.                         {  
  117.                             clsHandCardData.value_aHandCardList[k] += 3;  
  118.                         }  
  119.                         clsHandCardData.nHandCardCount += prov * 4;  
  120.                     }  
  121.                     //为三连飞机  
  122.                     if (prov == 3)  
  123.                     {  
  124.                         for (int k = i; k <= j; k++)  
  125.                         {  
  126.                             clsHandCardData.value_aHandCardList[k] -= 3;  
  127.                         }  
  128.                         clsHandCardData.nHandCardCount -= prov * 4;  
  129.                         for (int tmp1 = 3; tmp1 < 18; tmp1++)  
  130.                         {  
  131.                             if (clsHandCardData.value_aHandCardList[tmp1] > 0 )  
  132.                             {  
  133.                                 clsHandCardData.value_aHandCardList[tmp1] -= 1;  
  134.                                 for (int tmp2 = tmp1; tmp2 < 18; tmp2++)  
  135.                                 {  
  136.                                     if (clsHandCardData.value_aHandCardList[tmp2] > 0 )  
  137.                                     {  
  138.                                         clsHandCardData.value_aHandCardList[tmp2] -= 1;  
  139.                                         for (int tmp3 = tmp2; tmp3 < 18; tmp3++)  
  140.                                         {  
  141.                                             if (clsHandCardData.value_aHandCardList[tmp3] > 0 )  
  142.                                             {  
  143.                                                 clsHandCardData.value_aHandCardList[tmp3] -= 1;  
  144.   
  145.                                                 HandCardValue tmpHandCardValue = get_HandCardValue(clsHandCardData);  
  146.                                                 if ((BestHandCardValue.SumValue - (BestHandCardValue.NeedRound * 7)) <= (tmpHandCardValue.SumValue - (tmpHandCardValue.NeedRound * 7)))  
  147.                                                 {  
  148.   
  149.                                                     BestHandCardValue = tmpHandCardValue;  
  150.                                                     BestCardGroup = get_GroupData(cgTHREE_TAKE_ONE_LINE, j, prov * 4);  
  151.                                                     tmp_1 = tmp1;  
  152.                                                     tmp_2 = tmp2;  
  153.                                                     tmp_3 = tmp3;  
  154.   
  155.                                                 }  
  156.                                                 clsHandCardData.value_aHandCardList[tmp3] += 1;  
  157.                                             }  
  158.   
  159.                                         }  
  160.                                         clsHandCardData.value_aHandCardList[tmp2] += 1;  
  161.                                     }  
  162.   
  163.                                 }  
  164.                                 clsHandCardData.value_aHandCardList[tmp1] += 1;  
  165.                             }  
  166.                         }  
  167.                         for (int k = i; k <= j; k++)  
  168.                         {  
  169.                             clsHandCardData.value_aHandCardList[k] += 3;  
  170.                         }  
  171.                         clsHandCardData.nHandCardCount += prov * 4;  
  172.                     }  
  173.                     //为四连飞机  
  174.                     if (prov == 4)  
  175.                     {  
  176.                         for (int k = i; k <= j; k++)  
  177.                         {  
  178.                             clsHandCardData.value_aHandCardList[k] -= 3;  
  179.                         }  
  180.                         clsHandCardData.nHandCardCount -= prov * 4;  
  181.                         for (int tmp1 = 3; tmp1 < 18; tmp1++)  
  182.                         {  
  183.                             if (clsHandCardData.value_aHandCardList[tmp1] > 0 )  
  184.                             {  
  185.                                 clsHandCardData.value_aHandCardList[tmp1] -= 1;  
  186.                                 for (int tmp2 = tmp1; tmp2 < 18; tmp2++)  
  187.                                 {  
  188.                                     if (clsHandCardData.value_aHandCardList[tmp2] > 0 )  
  189.                                     {  
  190.                                         clsHandCardData.value_aHandCardList[tmp2] -= 1;  
  191.                                         for (int tmp3 = tmp2; tmp3 < 18; tmp3++)  
  192.                                         {  
  193.                                             if (clsHandCardData.value_aHandCardList[tmp3] > 0 )  
  194.                                             {  
  195.                                                 clsHandCardData.value_aHandCardList[tmp3] -= 1;  
  196.                                                 for (int tmp4 = tmp3; tmp4 < 18; tmp4++)  
  197.                                                 {  
  198.                                                     if (clsHandCardData.value_aHandCardList[tmp4] > 0 )  
  199.                                                     {  
  200.                                                         clsHandCardData.value_aHandCardList[tmp4] -= 1;  
  201.                                                         HandCardValue tmpHandCardValue = get_HandCardValue(clsHandCardData);  
  202.                                                         if ((BestHandCardValue.SumValue - (BestHandCardValue.NeedRound * 7)) <= (tmpHandCardValue.SumValue - (tmpHandCardValue.NeedRound * 7)))  
  203.                                                         {  
  204.                                                             BestHandCardValue = tmpHandCardValue;  
  205.                                                             BestCardGroup = get_GroupData(cgTHREE_TAKE_ONE_LINE, j, prov * 4);  
  206.                                                             tmp_1 = tmp1;  
  207.                                                             tmp_2 = tmp2;  
  208.                                                             tmp_3 = tmp3;  
  209.                                                             tmp_4 = tmp4;  
  210.                                                         }  
  211.                                                         clsHandCardData.value_aHandCardList[tmp4] += 1;  
  212.                                                     }  
  213.   
  214.                                                 }  
  215.                                                 clsHandCardData.value_aHandCardList[tmp3] += 1;  
  216.                                             }  
  217.   
  218.                                         }  
  219.                                         clsHandCardData.value_aHandCardList[tmp2] += 1;  
  220.                                     }  
  221.   
  222.                                 }  
  223.                                 clsHandCardData.value_aHandCardList[tmp1] += 1;  
  224.                             }  
  225.                         }  
  226.                         for (int k = i; k <= j; k++)  
  227.                         {  
  228.                             clsHandCardData.value_aHandCardList[k] += 3;  
  229.                         }  
  230.                         clsHandCardData.nHandCardCount += prov * 4;  
  231.                     }  
  232.                     //若prov==5,则是地主可以直接出去,在剪枝部分已经处理  
  233.                 }  
  234.   
  235.             }  
  236.             //出三带一双连  
  237.             if (clsHandCardData.value_aHandCardList[i] > 2)  
  238.             {  
  239.                 int prov = 0;  
  240.                 for (int j = i; j < 15; j++)  
  241.                 {  
  242.                     if (clsHandCardData.value_aHandCardList[j] > 2 )  
  243.                     {  
  244.                         prov++;  
  245.                     }  
  246.                     else  
  247.                     {  
  248.                         break;  
  249.                     }  
  250.                     /*本来想做全排列选取带出的牌然后枚举出最高价值的,但考虑到当飞机长度也就是在2-4之间 
  251.                     所以干脆做三个分支处理算了*/  
  252.                     //为两连飞机  
  253.                     if (prov == 2)  
  254.                     {  
  255.   
  256.                         for (int k = i; k <= j; k++)  
  257.                         {  
  258.                             clsHandCardData.value_aHandCardList[k] -= 3;  
  259.                         }  
  260.                         clsHandCardData.nHandCardCount -= prov * 5;  
  261.                         for (int tmp1 = 3; tmp1 < 16; tmp1++)  
  262.                         {  
  263.                             if (clsHandCardData.value_aHandCardList[tmp1] > 1 )  
  264.                             {  
  265.                                 clsHandCardData.value_aHandCardList[tmp1] -= 2;  
  266.                                 for (int tmp2 = tmp1; tmp2 < 16; tmp2++)  
  267.                                 {  
  268.                                     if (clsHandCardData.value_aHandCardList[tmp2] > 1 )  
  269.                                     {  
  270.                                         clsHandCardData.value_aHandCardList[tmp2] -= 2;  
  271.                                         HandCardValue tmpHandCardValue = get_HandCardValue(clsHandCardData);  
  272.                                         if ((BestHandCardValue.SumValue - (BestHandCardValue.NeedRound * 7)) <= (tmpHandCardValue.SumValue - (tmpHandCardValue.NeedRound * 7)))  
  273.                                         {  
  274.                                             BestHandCardValue = tmpHandCardValue;  
  275.                                             BestCardGroup = get_GroupData(cgTHREE_TAKE_TWO_LINE, j, prov * 5);  
  276.                                             tmp_1 = tmp1;  
  277.                                             tmp_2 = tmp2;  
  278.                                         }  
  279.                                         clsHandCardData.value_aHandCardList[tmp2] += 2;  
  280.                                     }  
  281.                                 }  
  282.                                 clsHandCardData.value_aHandCardList[tmp1] += 2;  
  283.                             }  
  284.                         }  
  285.                         for (int k = i; k <= j; k++)  
  286.                         {  
  287.                             clsHandCardData.value_aHandCardList[k] += 3;  
  288.                         }  
  289.                         clsHandCardData.nHandCardCount += prov * 5;  
  290.                     }  
  291.                     //为三连飞机  
  292.                     if (prov == 3)  
  293.                     {  
  294.                         for (int k = i; k <= j; k++)  
  295.                         {  
  296.                             clsHandCardData.value_aHandCardList[k] -= 3;  
  297.                         }  
  298.                         clsHandCardData.nHandCardCount -= prov * 5;  
  299.                         for (int tmp1 = 3; tmp1 < 16; tmp1++)  
  300.                         {  
  301.                             if (clsHandCardData.value_aHandCardList[tmp1] > 1 )  
  302.                             {  
  303.                                 clsHandCardData.value_aHandCardList[tmp1] -= 2;  
  304.                                 for (int tmp2 = tmp1; tmp2 < 16; tmp2++)  
  305.                                 {  
  306.                                     if (clsHandCardData.value_aHandCardList[tmp2] > 1 )  
  307.                                     {  
  308.                                         clsHandCardData.value_aHandCardList[tmp2] -= 2;  
  309.                                         for (int tmp3 = tmp2; tmp3 < 16; tmp3++)  
  310.                                         {  
  311.                                             if (clsHandCardData.value_aHandCardList[tmp3] > 1 )  
  312.                                             {  
  313.                                                 clsHandCardData.value_aHandCardList[tmp3] -= 2;  
  314.                                                 HandCardValue tmpHandCardValue = get_HandCardValue(clsHandCardData);  
  315.                                                 if ((BestHandCardValue.SumValue - (BestHandCardValue.NeedRound * 7)) <= (tmpHandCardValue.SumValue - (tmpHandCardValue.NeedRound * 7)))  
  316.                                                 {  
  317.                                                     BestHandCardValue = tmpHandCardValue;  
  318.                                                     BestCardGroup = get_GroupData(cgTHREE_TAKE_TWO_LINE, j, prov * 5);  
  319.                                                     tmp_1 = tmp1;  
  320.                                                     tmp_2 = tmp2;  
  321.                                                     tmp_3 = tmp3;  
  322.                                                 }  
  323.                                                 clsHandCardData.value_aHandCardList[tmp3] += 2;  
  324.                                             }  
  325.   
  326.                                         }  
  327.                                         clsHandCardData.value_aHandCardList[tmp2] += 2;  
  328.                                     }  
  329.   
  330.                                 }  
  331.                                 clsHandCardData.value_aHandCardList[tmp1] += 2;  
  332.                             }  
  333.                         }  
  334.                         for (int k = i; k <= j; k++)  
  335.                         {  
  336.                             clsHandCardData.value_aHandCardList[k] += 3;  
  337.                         }  
  338.                         clsHandCardData.nHandCardCount += prov * 5;  
  339.                     }  
  340.                     //若prov==4,则是地主可以直接出去,在剪枝部分已经处理  
  341.                 }  
  342.             }  
  343.         }  
  344.   
  345.     }  





 


这个循环结束后,若有好的选择,则BestCardGroup会保留出牌的类型,在循环外进行出牌处理。

 

 

[cpp] view plain copy
 
  1. if (BestCardGroup.cgType == cgTHREE_TAKE_ONE)  
  2.         {  
  3.             clsHandCardData.value_nPutCardList.push_back(BestCardGroup.nMaxCard);  
  4.             clsHandCardData.value_nPutCardList.push_back(BestCardGroup.nMaxCard);  
  5.             clsHandCardData.value_nPutCardList.push_back(BestCardGroup.nMaxCard);  
  6.             clsHandCardData.value_nPutCardList.push_back(tmp_1);  
  7.             clsHandCardData.uctPutCardType = BestCardGroup;  
  8.             return;  
  9.         }  
  10.     else if (BestCardGroup.cgType == cgTHREE_TAKE_TWO)  
  11.         {  
  12.             clsHandCardData.value_nPutCardList.push_back(BestCardGroup.nMaxCard);  
  13.             clsHandCardData.value_nPutCardList.push_back(BestCardGroup.nMaxCard);  
  14.             clsHandCardData.value_nPutCardList.push_back(BestCardGroup.nMaxCard);  
  15.             clsHandCardData.value_nPutCardList.push_back(tmp_1);  
  16.             clsHandCardData.value_nPutCardList.push_back(tmp_1);  
  17.             clsHandCardData.uctPutCardType = BestCardGroup;  
  18.             return;  
  19.         }  
  20.     else if (BestCardGroup.cgType == cgTHREE_TAKE_ONE_LINE)  
  21.         {  
  22.             for (int j = BestCardGroup.nMaxCard - (BestCardGroup.nCount / 4) + 1; j <= BestCardGroup.nMaxCard; j++)  
  23.             {  
  24.                 clsHandCardData.value_nPutCardList.push_back(j);  
  25.                 clsHandCardData.value_nPutCardList.push_back(j);  
  26.                 clsHandCardData.value_nPutCardList.push_back(j);  
  27.             }  
  28.   
  29.             if (BestCardGroup.nCount / 4 == 2)  
  30.             {  
  31.                 clsHandCardData.value_nPutCardList.push_back(tmp_1);  
  32.                 clsHandCardData.value_nPutCardList.push_back(tmp_2);  
  33.             }  
  34.             if (BestCardGroup.nCount / 4 == 3)  
  35.             {  
  36.                 clsHandCardData.value_nPutCardList.push_back(tmp_1);  
  37.                 clsHandCardData.value_nPutCardList.push_back(tmp_2);  
  38.                 clsHandCardData.value_nPutCardList.push_back(tmp_3);  
  39.             }  
  40.             if (BestCardGroup.nCount / 4 == 4)  
  41.             {  
  42.                 clsHandCardData.value_nPutCardList.push_back(tmp_1);  
  43.                 clsHandCardData.value_nPutCardList.push_back(tmp_2);  
  44.                 clsHandCardData.value_nPutCardList.push_back(tmp_3);  
  45.                 clsHandCardData.value_nPutCardList.push_back(tmp_4);  
  46.             }  
  47.   
  48.             clsHandCardData.uctPutCardType = BestCardGroup;  
  49.             return;  
  50.         }  
  51.     else if (BestCardGroup.cgType == cgTHREE_TAKE_TWO_LINE)  
  52.         {  
  53.             for (int j = BestCardGroup.nMaxCard - (BestCardGroup.nCount / 5) + 1; j <= BestCardGroup.nMaxCard; j++)  
  54.             {  
  55.                 clsHandCardData.value_nPutCardList.push_back(j);  
  56.                 clsHandCardData.value_nPutCardList.push_back(j);  
  57.                 clsHandCardData.value_nPutCardList.push_back(j);  
  58.             }  
  59.             if (BestCardGroup.nCount / 5 == 2)  
  60.             {  
  61.                 clsHandCardData.value_nPutCardList.push_back(tmp_1);  
  62.                 clsHandCardData.value_nPutCardList.push_back(tmp_1);  
  63.                 clsHandCardData.value_nPutCardList.push_back(tmp_2);  
  64.                 clsHandCardData.value_nPutCardList.push_back(tmp_2);  
  65.             }  
  66.             if (BestCardGroup.nCount / 5 == 3)  
  67.             {  
  68.                 clsHandCardData.value_nPutCardList.push_back(tmp_1);  
  69.                 clsHandCardData.value_nPutCardList.push_back(tmp_1);  
  70.                 clsHandCardData.value_nPutCardList.push_back(tmp_2);  
  71.                 clsHandCardData.value_nPutCardList.push_back(tmp_2);  
  72.                 clsHandCardData.value_nPutCardList.push_back(tmp_3);  
  73.                 clsHandCardData.value_nPutCardList.push_back(tmp_3);  
  74.             }  
  75.             clsHandCardData.uctPutCardType = BestCardGroup;  
  76.             return;  
  77.         }  


因为回溯遍历部分与被动出牌完全一样,这里就不再赘述。飞机在出牌阶段的处理比较麻烦,要根据牌数进行判断是几连飞机。

 

 

下一章,我们将实现打出当前最小值牌部分。

敬请关注下一章:斗地主AI算法——第十四章の主动出牌(3)

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

导航