鬥地主AI演算法 第五章 總值計算

2021-07-31 05:31:39 字數 3808 閱讀 5316

本章算是比較重點的一章,前一章已經對各個牌型做出了價值定義,本章主要實現計算手牌總價值模組函式。

根據之前的思路,我們設定一下輸入輸出:

輸入:手牌資料類(主要用手牌個數nhandcardcount以及手牌狀態陣列clshandcarddata.value_ahandcardlist)

輸出:手牌價值結構 handcardvalue

先處理剪枝部分,如果剩下的手牌是一手牌,我們即直接返回該牌型的價值,這個下一章會寫出,我們先假設存在這個函式ins_surcardstype。

其返回值設計:若是一手牌,返回牌型,若不是一手牌,返回錯誤牌型。

cardgroupdata uctcardgroupdata = ins_surcardstype(clshandcarddata.value_ahandcardlist);

//如果能一次性出去且沒有炸彈,因為有炸彈的話權值可能會更大

if (uctcardgroupdata.cgtype != cgerror&& !hasboom(clshandcarddata.value_ahandcardlist))

若不是一手牌的情況,我們通過get_putcardlist函式(後續幾章會寫出實現方法)獲取最佳的出牌策略 進行出牌,

/*只是獲取出牌的序列,即clshandcarddata.value_nputcardlist及clshandcarddata.uctputcardtype

其他成員均無改變,也不會呼叫出牌函式,get_putcardlist返回最優方案*/

get_putcardlist_2(clshandcarddata);

//要儲存當前的clshandcarddata.value_nputcardlist及clshandcarddata.uctputcardtype用於回溯

cardgroupdata nowputcardtype = clshandcarddata.uctputcardtype;

vectornowputcardlist = clshandcarddata.value_nputcardlist;

if (clshandcarddata.uctputcardtype.cgtype == cgerror)

獲取完出牌序列後,打出這些牌(只改變value_ahandcardlist陣列),再計算剩餘的牌總價值。

for (vector::iterator iter = nowputcardlist.begin();

iter != nowputcardlist.end(); iter++)

clshandcarddata.nhandcardcount -= nowputcardtype.ncount;

//---回溯↑

handcardvalue tmp_survalue = get_handcardvalue(clshandcarddata);//遞迴剩餘牌價值

//---回溯↓

for (vector::iterator iter = nowputcardlist.begin();

iter != nowputcardlist.end(); iter++)

clshandcarddata.nhandcardcount += nowputcardtype.ncount;

//---回溯↑

ucthandcardvalue.sumvalue = nowputcardtype.nvalue + tmp_survalue.sumvalue;

ucthandcardvalue.needround = tmp_survalue.needround + 1;

最後將返回的價值與當前打出的牌價值相加即時該階段手牌總價值。

下面給出完整**

/*

通過回溯dp的方式獲取手牌價值

與get_putcardlist作為交替遞迴呼叫

返回:價值結構體handcardvalue

權值的計算規則參考標頭檔案評分邏輯思維

*/handcardvalue get_handcardvalue(handcarddata &clshandcarddata)

//————以下為剪枝:判斷是否可以一手出完牌

cardgroupdata uctcardgroupdata = ins_surcardstype(clshandcarddata.value_ahandcardlist);

//————不到萬不得已我們都不會出四帶二,都盡量保炸彈

if (uctcardgroupdata.cgtype != cgerror&&uctcardgroupdata.cgtype != cgfour_take_one&&uctcardgroupdata.cgtype != cgfour_take_two)

//非剪枝操作,即非一手能出完的牌

/*只是獲取出牌的序列,即clshandcarddata.value_nputcardlist及clshandcarddata.uctputcardtype

其他成員均無改變,也不會呼叫出牌函式,get_putcardlist返回最優方案*/

get_putcardlist_2(clshandcarddata);

//要儲存當前的clshandcarddata.value_nputcardlist及clshandcarddata.uctputcardtype用於回溯

cardgroupdata nowputcardtype = clshandcarddata.uctputcardtype;

vectornowputcardlist = clshandcarddata.value_nputcardlist;

if (clshandcarddata.uctputcardtype.cgtype == cgerror)

//---回溯↓

for (vector::iterator iter = nowputcardlist.begin();

iter != nowputcardlist.end(); iter++)

clshandcarddata.nhandcardcount -= nowputcardtype.ncount;

//---回溯↑

handcardvalue tmp_survalue = get_handcardvalue(clshandcarddata);//遞迴剩餘牌價值

//---回溯↓

for (vector::iterator iter = nowputcardlist.begin();

iter != nowputcardlist.end(); iter++)

clshandcarddata.nhandcardcount += nowputcardtype.ncount;

//---回溯↑

ucthandcardvalue.sumvalue = nowputcardtype.nvalue + tmp_survalue.sumvalue;

ucthandcardvalue.needround = tmp_survalue.needround + 1;

return ucthandcardvalue;

}

注:當前出牌策略是2.0版本,所以是

get_putcardlist_2,後續還會寫出更多的版本,敬請期待。

如果你之前了解回溯演算法的話,那麼應該很好理解上述**,若沒有接觸過回溯,可以看我以前的部落格

總值計算的模組就算完成了,其實並沒有太多東西,除了乙個回溯遞迴以外就是裡面呼叫了兩個函式ins_surcardstype判斷是否是一手牌以及get_putcardlist出牌邏輯。那麼下一章我們便要實現這個ins_surcardstype函式。

鬥地主AI演算法 第五章 總值計算

本章算是比較重點的一章,前一章已經對各個牌型做出了價值定義,本章主要實現計算手牌總價值模組函式。根據之前的思路,我們設定一下輸入輸出 輸入 手牌資料類 主要用手牌個數nhandcardcount以及手牌狀態陣列clshandcarddata.value ahandcardlist 輸出 手牌價值結構...

演算法第五章實踐

寫在開頭 emm,這一次的上機是目前來說最自閉的一次,因為,居然!只做出了一道!看來最近的學習跟刷題還是怠慢了,要加把勁了 正文 第一題,用回溯法實現0 1揹包。一開始直接貼了乙個dfs然後稍微的剪了一下枝,然後發現無論怎麼剪枝,第三第四個樣例都會tle。沒辦法,只好加乙個限界函式,在每一次遞迴前加...

演算法第五章作業

1.你對回溯演算法的理解 回溯演算法實際上乙個類似列舉的搜尋嘗試過程,主要是在搜尋嘗試過程中尋找問題的解,當發現已不滿足求解條件時,就 回溯 返回,嘗試別的路徑。回溯法是一種選優搜尋法,按選優條件向前搜尋,以達到目標。但當探索到某一步時,發現原先選擇並不優或達不到目標,就退回一步重新選擇,這種走不通...