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

来源:互联网 发布:福彩3d软件分析软件 编辑:程序博客网 时间:2024/06/06 12:47


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


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

//出单牌if (clsHandCardData.value_aHandCardList[i] > 0){clsHandCardData.value_aHandCardList[i]--;clsHandCardData.nHandCardCount--;HandCardValue tmpHandCardValue = get_HandCardValue(clsHandCardData);clsHandCardData.value_aHandCardList[i]++;clsHandCardData.nHandCardCount++;if ((BestHandCardValue.SumValue - (BestHandCardValue.NeedRound * 7)) <= (tmpHandCardValue.SumValue - (tmpHandCardValue.NeedRound * 7))){BestHandCardValue = tmpHandCardValue;BestCardGroup= get_GroupData(cgSINGLE, i, 1);}}//出对牌if (clsHandCardData.value_aHandCardList[i] > 1){//尝试打出一对牌,估算剩余手牌价值clsHandCardData.value_aHandCardList[i] -= 2;clsHandCardData.nHandCardCount -= 2;HandCardValue tmpHandCardValue = get_HandCardValue(clsHandCardData);clsHandCardData.value_aHandCardList[i] += 2;clsHandCardData.nHandCardCount += 2;//选取总权值-轮次*7值最高的策略  因为我们认为剩余的手牌需要n次控手的机会才能出完,若轮次牌型很大(如炸弹) 则其-7的价值也会为正if ((BestHandCardValue.SumValue - (BestHandCardValue.NeedRound * 7)) <= (tmpHandCardValue.SumValue - (tmpHandCardValue.NeedRound * 7))){BestHandCardValue = tmpHandCardValue;BestCardGroup = get_GroupData(cgDOUBLE, i, 2);}}//出三牌if (clsHandCardData.value_aHandCardList[i] > 2){clsHandCardData.value_aHandCardList[i] -= 3;clsHandCardData.nHandCardCount -= 3;HandCardValue tmpHandCardValue = get_HandCardValue(clsHandCardData);clsHandCardData.value_aHandCardList[i] += 3;clsHandCardData.nHandCardCount += 3;//选取总权值-轮次*7值最高的策略  因为我们认为剩余的手牌需要n次控手的机会才能出完,若轮次牌型很大(如炸弹) 则其-7的价值也会为正if ((BestHandCardValue.SumValue - (BestHandCardValue.NeedRound * 7)) <= (tmpHandCardValue.SumValue - (tmpHandCardValue.NeedRound * 7))){BestHandCardValue = tmpHandCardValue;BestCardGroup = get_GroupData(cgTHREE, i, 3);}}

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

//出单顺if (clsHandCardData.value_aHandCardList[i] > 0){int prov = 0;for (int j = i; j < 15; j++){if(clsHandCardData.value_aHandCardList[j]>0){prov++;}else{break;}if (prov >= 5){for (int k = i; k <= j; k++){clsHandCardData.value_aHandCardList[k] --;}clsHandCardData.nHandCardCount -= prov;HandCardValue tmpHandCardValue = get_HandCardValue(clsHandCardData);for (int k = i; k <= j; k++){clsHandCardData.value_aHandCardList[k] ++;}clsHandCardData.nHandCardCount += prov;//选取总权值-轮次*7值最高的策略  因为我们认为剩余的手牌需要n次控手的机会才能出完,若轮次牌型很大(如炸弹) 则其-7的价值也会为正if ((BestHandCardValue.SumValue - (BestHandCardValue.NeedRound * 7)) <= (tmpHandCardValue.SumValue - (tmpHandCardValue.NeedRound * 7))){BestHandCardValue = tmpHandCardValue;BestCardGroup = get_GroupData(cgSINGLE_LINE, j, prov);}}}}//出双顺if (clsHandCardData.value_aHandCardList[i] > 1){int prov = 0;for (int j = i; j < 15; j++){if (clsHandCardData.value_aHandCardList[j]>1){prov++;}else{break;}if (prov >= 3){for (int k = i; k <= j; k++){clsHandCardData.value_aHandCardList[k] -=2;}clsHandCardData.nHandCardCount -= prov*2;HandCardValue tmpHandCardValue = get_HandCardValue(clsHandCardData);for (int k = i; k <= j; k++){clsHandCardData.value_aHandCardList[k] +=2;}clsHandCardData.nHandCardCount += prov*2;//选取总权值-轮次*7值最高的策略  因为我们认为剩余的手牌需要n次控手的机会才能出完,若轮次牌型很大(如炸弹) 则其-7的价值也会为正if ((BestHandCardValue.SumValue - (BestHandCardValue.NeedRound * 7)) <= (tmpHandCardValue.SumValue - (tmpHandCardValue.NeedRound * 7))){BestHandCardValue = tmpHandCardValue;BestCardGroup = get_GroupData(cgDOUBLE_LINE, j, prov*2);}}}}//出三顺if(clsHandCardData.value_aHandCardList[i] > 2){int prov = 0;for (int j = i; j < 15; j++){if (clsHandCardData.value_aHandCardList[j]>2){prov++;}else{break;}if (prov >= 2){for (int k = i; k <= j; k++){clsHandCardData.value_aHandCardList[k] -= 3;}clsHandCardData.nHandCardCount -= prov * 3;HandCardValue tmpHandCardValue = get_HandCardValue(clsHandCardData);for (int k = i; k <= j; k++){clsHandCardData.value_aHandCardList[k] += 3;}clsHandCardData.nHandCardCount += prov * 3;//选取总权值-轮次*7值最高的策略  因为我们认为剩余的手牌需要n次控手的机会才能出完,若轮次牌型很大(如炸弹) 则其-7的价值也会为正if ((BestHandCardValue.SumValue - (BestHandCardValue.NeedRound * 7)) <= (tmpHandCardValue.SumValue - (tmpHandCardValue.NeedRound * 7))){BestHandCardValue = tmpHandCardValue;BestCardGroup = get_GroupData(cgTHREE_LINE, j, prov * 3);}}}}

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


if (BestCardGroup.cgType == cgERROR){}else if (BestCardGroup.cgType == cgSINGLE){clsHandCardData.value_nPutCardList.push_back(BestCardGroup.nMaxCard);clsHandCardData.uctPutCardType = BestCardGroup;}else if (BestCardGroup.cgType == cgDOUBLE){clsHandCardData.value_nPutCardList.push_back(BestCardGroup.nMaxCard);clsHandCardData.value_nPutCardList.push_back(BestCardGroup.nMaxCard);clsHandCardData.uctPutCardType = BestCardGroup;}else if (BestCardGroup.cgType == cgTHREE){clsHandCardData.value_nPutCardList.push_back(BestCardGroup.nMaxCard);clsHandCardData.value_nPutCardList.push_back(BestCardGroup.nMaxCard);clsHandCardData.value_nPutCardList.push_back(BestCardGroup.nMaxCard);clsHandCardData.uctPutCardType = BestCardGroup;}else if (BestCardGroup.cgType == cgSINGLE_LINE){for (int j = BestCardGroup.nMaxCard- BestCardGroup.nCount+1; j <= BestCardGroup.nMaxCard; j++){clsHandCardData.value_nPutCardList.push_back(j);}clsHandCardData.uctPutCardType = BestCardGroup;}else if (BestCardGroup.cgType == cgDOUBLE_LINE){for (int j = BestCardGroup.nMaxCard - (BestCardGroup.nCount/2) + 1; j <= BestCardGroup.nMaxCard; j++){clsHandCardData.value_nPutCardList.push_back(j);clsHandCardData.value_nPutCardList.push_back(j);}clsHandCardData.uctPutCardType = BestCardGroup;}else if (BestCardGroup.cgType == cgTHREE_LINE){for (int j = BestCardGroup.nMaxCard - (BestCardGroup.nCount / 3) + 1; j <= BestCardGroup.nMaxCard; j++){clsHandCardData.value_nPutCardList.push_back(j);clsHandCardData.value_nPutCardList.push_back(j);clsHandCardData.value_nPutCardList.push_back(j);}clsHandCardData.uctPutCardType = BestCardGroup;}else if (BestCardGroup.cgType == cgTHREE_TAKE_ONE){clsHandCardData.value_nPutCardList.push_back(BestCardGroup.nMaxCard);clsHandCardData.value_nPutCardList.push_back(BestCardGroup.nMaxCard);clsHandCardData.value_nPutCardList.push_back(BestCardGroup.nMaxCard);clsHandCardData.value_nPutCardList.push_back(tmp_1);clsHandCardData.uctPutCardType = BestCardGroup;}else if (BestCardGroup.cgType == cgTHREE_TAKE_TWO){clsHandCardData.value_nPutCardList.push_back(BestCardGroup.nMaxCard);clsHandCardData.value_nPutCardList.push_back(BestCardGroup.nMaxCard);clsHandCardData.value_nPutCardList.push_back(BestCardGroup.nMaxCard);clsHandCardData.value_nPutCardList.push_back(tmp_1);clsHandCardData.value_nPutCardList.push_back(tmp_1);clsHandCardData.uctPutCardType = BestCardGroup;}else if (BestCardGroup.cgType == cgTHREE_TAKE_ONE_LINE){for (int j = BestCardGroup.nMaxCard - (BestCardGroup.nCount / 4) + 1; j <= BestCardGroup.nMaxCard; j++){clsHandCardData.value_nPutCardList.push_back(j);clsHandCardData.value_nPutCardList.push_back(j);clsHandCardData.value_nPutCardList.push_back(j);}if (BestCardGroup.nCount / 4 == 2){clsHandCardData.value_nPutCardList.push_back(tmp_1);clsHandCardData.value_nPutCardList.push_back(tmp_2);}if (BestCardGroup.nCount / 4 == 3){clsHandCardData.value_nPutCardList.push_back(tmp_1);clsHandCardData.value_nPutCardList.push_back(tmp_2);clsHandCardData.value_nPutCardList.push_back(tmp_3);}if (BestCardGroup.nCount / 4 == 4){clsHandCardData.value_nPutCardList.push_back(tmp_1);clsHandCardData.value_nPutCardList.push_back(tmp_2);clsHandCardData.value_nPutCardList.push_back(tmp_3);clsHandCardData.value_nPutCardList.push_back(tmp_4);}clsHandCardData.uctPutCardType = BestCardGroup;}else if (BestCardGroup.cgType == cgTHREE_TAKE_TWO_LINE){for (int j = BestCardGroup.nMaxCard - (BestCardGroup.nCount / 5) + 1; j <= BestCardGroup.nMaxCard; j++){clsHandCardData.value_nPutCardList.push_back(j);clsHandCardData.value_nPutCardList.push_back(j);clsHandCardData.value_nPutCardList.push_back(j);}if (BestCardGroup.nCount / 5 == 2){clsHandCardData.value_nPutCardList.push_back(tmp_1);clsHandCardData.value_nPutCardList.push_back(tmp_1);clsHandCardData.value_nPutCardList.push_back(tmp_2);clsHandCardData.value_nPutCardList.push_back(tmp_2);}if (BestCardGroup.nCount / 5 == 3){clsHandCardData.value_nPutCardList.push_back(tmp_1);clsHandCardData.value_nPutCardList.push_back(tmp_1);clsHandCardData.value_nPutCardList.push_back(tmp_2);clsHandCardData.value_nPutCardList.push_back(tmp_2);clsHandCardData.value_nPutCardList.push_back(tmp_3);clsHandCardData.value_nPutCardList.push_back(tmp_3);}clsHandCardData.uctPutCardType = BestCardGroup;}return;

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


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

1 0
原创粉丝点击