鬥地主AI演算法 第十三章 主動出牌 2

2021-09-08 14:06:43 字數 4559 閱讀 6508

上一章我們已經搭好了出牌演算法的基本框架,本章主要實現優先處理的三帶、飛機等牌型。

首先定義一些基本變數:

[cpp]view plain

copy

//暫存最佳的價值  

handcardvalue besthandcardvalue;  

besthandcardvalue.needround = 20;  

besthandcardvalue.sumvalue = mincardsvalue;  

//我們認為不出牌的話會讓對手乙個輪次,即加一輪(權值減少7)便於後續的對比參考。  

besthandcardvalue.needround += 1;  

//暫存最佳的組合  

cardgroupdata bestcardgroup;  

//帶出去的牌  

int tmp_1 = 0;  

int tmp_2 = 0;  

int tmp_3 = 0;  

int tmp_4 = 0;  

因為列舉了牌型,所以實際和被動出牌邏輯都差不多,且沒有nmaxcard的限制,所以我們要從3開始遍歷。且上一章我們提到,不考慮炸彈拆分的情況。故value_ahandcardlist[i]不能等於4。

[cpp]view plain

copy

for (int i = 3; i < 16; i++)  

}  }  clshandcarddata.value_ahandcardlist[i] += 3;  

}  //出三帶二  

if (clshandcarddata.value_ahandcardlist[i] > 2)  

}  clshandcarddata.value_ahandcardlist[i] += 3;  

}  }  

//出四帶二單  

if (clshandcarddata.value_ahandcardlist[i] > 3)  

//出四帶二對  

if (clshandcarddata.value_ahandcardlist[i] > 3)  

//出三帶一單連  

if (clshandcarddata.value_ahandcardlist[i] > 2)  

else  

/*本來想做全排列選取帶出的牌然後列舉出最**值的,但考慮到當飛機長度也就是在2-4之間 

所以乾脆做三個分支處理算了*/  

//為兩連飛機  

if (prov == 2)  

clshandcarddata.nhandcardcount -= prov * 4;  

for (int tmp1 = 3; tmp1 < 18; tmp1++)  

clshandcarddata.value_ahandcardlist[tmp2] += 1;  

}  }  

clshandcarddata.value_ahandcardlist[tmp1] += 1;  

}  }  

for (int k = i; k <= j; k++)  

clshandcarddata.nhandcardcount += prov * 4;  

}  //為三連飛機  

if (prov == 3)  

clshandcarddata.nhandcardcount -= prov * 4;  

for (int tmp1 = 3; tmp1 < 18; tmp1++)  

clshandcarddata.value_ahandcardlist[t***] += 1;  

}  }  

clshandcarddata.value_ahandcardlist[tmp2] += 1;  

}  }  

clshandcarddata.value_ahandcardlist[tmp1] += 1;  

}  }  

for (int k = i; k <= j; k++)  

clshandcarddata.nhandcardcount += prov * 4;  

}  //為四連飛機  

if (prov == 4)  

clshandcarddata.nhandcardcount -= prov * 4;  

for (int tmp1 = 3; tmp1 < 18; tmp1++)  

clshandcarddata.value_ahandcardlist[tmp4] += 1;  

}  }  

clshandcarddata.value_ahandcardlist[t***] += 1;  

}  }  

clshandcarddata.value_ahandcardlist[tmp2] += 1;  

}  }  

clshandcarddata.value_ahandcardlist[tmp1] += 1;  

}  }  

for (int k = i; k <= j; k++)  

clshandcarddata.nhandcardcount += prov * 4;  

}  //若prov==5,則是地主可以直接出去,在剪枝部分已經處理  

}  }  

//出三帶一雙連  

if (clshandcarddata.value_ahandcardlist[i] > 2)  

else  

/*本來想做全排列選取帶出的牌然後列舉出最**值的,但考慮到當飛機長度也就是在2-4之間 

所以乾脆做三個分支處理算了*/  

//為兩連飛機  

if (prov == 2)  

clshandcarddata.nhandcardcount -= prov * 5;  

for (int tmp1 = 3; tmp1 < 16; tmp1++)  

clshandcarddata.value_ahandcardlist[tmp2] += 2;  

}  }  

clshandcarddata.value_ahandcardlist[tmp1] += 2;  

}  }  

for (int k = i; k <= j; k++)  

clshandcarddata.nhandcardcount += prov * 5;  

}  //為三連飛機  

if (prov == 3)  

clshandcarddata.nhandcardcount -= prov * 5;  

for (int tmp1 = 3; tmp1 < 16; tmp1++)  

clshandcarddata.value_ahandcardlist[t***] += 2;  

}  }  

clshandcarddata.value_ahandcardlist[tmp2] += 2;  

}  }  

clshandcarddata.value_ahandcardlist[tmp1] += 2;  

}  }  

for (int k = i; k <= j; k++)  

clshandcarddata.nhandcardcount += prov * 5;  

}  //若prov==4,則是地主可以直接出去,在剪枝部分已經處理  

}  }  

}  }  

這個迴圈結束後,若有好的選擇,則bestcardgroup會保留出牌的型別,在迴圈外進行出牌處理。

[cpp]view plain

copy

if (bestcardgroup.cgtype == cgthree_take_one)  

else if (bestcardgroup.cgtype == cgthree_take_two)  

else if (bestcardgroup.cgtype == cgthree_take_one_line)  

if (bestcardgroup.ncount / 4 == 2)  

if (bestcardgroup.ncount / 4 == 3)  

if (bestcardgroup.ncount / 4 == 4)  

clshandcarddata.uctputcardtype = bestcardgroup;  

return;  

}  else if (bestcardgroup.cgtype == cgthree_take_two_line)  

if (bestcardgroup.ncount / 5 == 2)  

if (bestcardgroup.ncount / 5 == 3)  

clshandcarddata.uctputcardtype = bestcardgroup;  

return;  

}  

因為回溯遍歷部分與被動出牌完全一樣,這裡就不再贅述。飛機在出牌階段的處理比較麻煩,要根據牌數進行判斷是幾連飛機。

下一章,我們將實現打出當前最小值牌部分。

鬥地主AI演算法 第十四章 主動出牌 3

上一章已經排除了飛機 三帶等牌型,那麼除去炸彈王炸以外,我們只剩下單牌 對牌 三牌以及單順 雙順 三順了。首先說單牌 對牌 三牌。其邏輯基本一樣,只是出牌的個數有差別,即 如果該i牌數量滿足這種牌型要求,即先打出,計算其剩餘價值。出單牌 if clshandcarddata.value ahandc...

鬥地主AI演算法 第十二章 主動出牌 1

本章開始,我們介紹主動出牌的演算法,和被動出牌類似,我們第一步把主要架子搭起來。首先清空出牌序列 cpp view plain copy clshandcarddata.clearputcardlist 主動出牌的策略按照優先順序大體可以分為三類 一 能直接一手牌出去,優先出。二 兩手牌出去且有絕對...

鬥地主AI演算法 第十二章 主動出牌 1

本章開始,我們介紹主動出牌的演算法,和被動出牌類似,我們第一步把主要架子搭起來。首先清空出牌序列 clshandcarddata.clearputcardlist 主動出牌的策略按照優先順序大體可以分為三類 一 能直接一手牌出去,優先出。二 兩手牌出去且有絕對大牌,先出絕對大牌。三 出一手牌使得接下...