上一章已經排除了飛機、三帶等牌型,那麼除去炸彈王炸以外,我們只剩下單牌、對牌、三牌以及單順、雙順、三順了。
首先說單牌、對牌、三牌。其邏輯基本一樣,只是出牌的個數有差別,即:如果該i牌數量滿足這種牌型要求,即先打出,計算其剩餘價值。
//出單牌
if (clshandcarddata.value_ahandcardlist[i] > 0)}
//出對牌
if (clshandcarddata.value_ahandcardlist[i] > 1)}
//出三牌
if (clshandcarddata.value_ahandcardlist[i] > 2)}
至於順子的演算法,和被動出牌的有一點點差別,就是因為沒有了數量限制,所以需要遍歷以i牌為起點可以組成的所有順子。
//出單順
if (clshandcarddata.value_ahandcardlist[i] >
0)else
if (prov >=
5)clshandcarddata.nhandcardcount -= prov;
handcardvalue tmphandcardvalue = get_handcardvalue(clshandcarddata);
for (
int k = i; k <= j; k++)
clshandcarddata.nhandcardcount += prov;
//選取總權值-輪次*7值最高的策略 因為我們認為剩餘的手牌需要n次控手的機會才能出完,若輪次牌型很大(如炸彈) 則其-7的價值也會為正
if ((besthandcardvalue.sumvalue - (besthandcardvalue.needround *
7)) <= (tmphandcardvalue.sumvalue - (tmphandcardvalue.needround *
7)))}}
}//出雙順
if (clshandcarddata.value_ahandcardlist[i] >
1)else
if (prov >=
3)clshandcarddata.nhandcardcount -= prov*
2;handcardvalue tmphandcardvalue = get_handcardvalue(clshandcarddata);
for (
int k = i; k <= j; k++)
clshandcarddata.nhandcardcount += prov*
2;//選取總權值-輪次*7值最高的策略 因為我們認為剩餘的手牌需要n次控手的機會才能出完,若輪次牌型很大(如炸彈) 則其-7的價值也會為正
if ((besthandcardvalue.sumvalue - (besthandcardvalue.needround *
7)) <= (tmphandcardvalue.sumvalue - (tmphandcardvalue.needround *
7)))}}
}//出三順
if(clshandcarddata.value_ahandcardlist[i] >
2)else
if (prov >=
2)clshandcarddata.nhandcardcount -= prov *
3;handcardvalue tmphandcardvalue = get_handcardvalue(clshandcarddata);
for (
int k = i; k <= j; k++)
clshandcarddata.nhandcardcount += prov *
3;//選取總權值-輪次*7值最高的策略 因為我們認為剩餘的手牌需要n次控手的機會才能出完,若輪次牌型很大(如炸彈) 則其-7的價值也會為正
if ((besthandcardvalue.sumvalue - (besthandcardvalue.needround *
7)) <= (tmphandcardvalue.sumvalue - (tmphandcardvalue.needround *
7)))}}
}
因為本策略是必須解決掉至少乙個i牌的,所以出牌操作放在迴圈內進行,也就是說,只要你不是炸3,若你手牌有3,在處理3時一定會return 就絕對不會再走到4。
if (bestcardgroup.cgtype == cgerror)
else
if (bestcardgroup.cgtype == cgsingle)
else
if (bestcardgroup.cgtype == cgdouble)
else
if (bestcardgroup.cgtype == cgthree)
else
if (bestcardgroup.cgtype == cgsingle_line)
clshandcarddata.uctputcardtype = bestcardgroup;
}else
if (bestcardgroup.cgtype == cgdouble_line)
clshandcarddata.uctputcardtype = bestcardgroup;
}else
if (bestcardgroup.cgtype == cgthree_line)
clshandcarddata.uctputcardtype = bestcardgroup;
}else
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;
}else
if (bestcardgroup.cgtype == cgthree_take_two_line)
if (bestcardgroup.ncount /
5 ==
2)if (bestcardgroup.ncount /
5 ==
3)clshandcarddata.uctputcardtype = bestcardgroup;
}return;
至此,主動出牌的所有邏輯均已實現,同時整個鬥地主演算法也基本完成了。接下來我們便可寫一些測試模組來進行整合聯調。
鬥地主AI演算法 第十三章 主動出牌 2
上一章我們已經搭好了出牌演算法的基本框架,本章主要實現優先處理的三帶 飛機等牌型。首先定義一些基本變數 cpp view plain copy 暫存最佳的價值 handcardvalue besthandcardvalue besthandcardvalue.needround 20 besthan...
鬥地主AI演算法 第十二章 主動出牌 1
本章開始,我們介紹主動出牌的演算法,和被動出牌類似,我們第一步把主要架子搭起來。首先清空出牌序列 cpp view plain copy clshandcarddata.clearputcardlist 主動出牌的策略按照優先順序大體可以分為三類 一 能直接一手牌出去,優先出。二 兩手牌出去且有絕對...
鬥地主AI演算法 第十二章 主動出牌 1
本章開始,我們介紹主動出牌的演算法,和被動出牌類似,我們第一步把主要架子搭起來。首先清空出牌序列 clshandcarddata.clearputcardlist 主動出牌的策略按照優先順序大體可以分為三類 一 能直接一手牌出去,優先出。二 兩手牌出去且有絕對大牌,先出絕對大牌。三 出一手牌使得接下...