我們在前面講到過,各牌手的牌力估計就是我們在用蟻群演算法構造最優牌型時的啟發性知識。啟發性知識其實就是我們利用自己的經驗對事物做出的判優性評估,或者說就是對事物價值的判斷。
原則上,應用蟻群演算法需要用到兩類啟發性的知識:
結構評分:單步最優未必全域性最優,所以當單只螞蟻圍繞每輪次的優勝解爬出乙個新解時,對這個解的質量需做乙個總體評價
對於我們的牌型整理問題來說,單步擇優是每手牌的牌力大小,結構評分是對所有牌手威力最大化的綜合評價。那麼,三張2和a23456789這兩手牌的牌力該如何估算呢?!如果分不清這兩手牌的大小,那麼我們就無法判斷2到底應該組成哪一手才更好。
首先我們得把所有的牌手做乙個區分:炸彈和其它。因為其它型別的牌手都只能打同型別的牌手,而炸彈可以炸掉所有比自己小的牌手,包括其它型別的牌手和比自己小的炸彈。
我們做it的有所謂三個世界的說法:
這種轉換有兩個要點:
這時我們就看到牌力這個真實世界中的概念的問題了:牌力反映了牌手的大小,但反映不出來4張3的炸彈和3張3的本質區別!這個本質區別就是:3張3可以被比3大的其它三張打停,而4張3的炸彈則只能用炸彈才能打停!
這可不是廢話,這就是我們解決牌型整理問題時跨越數字鴻溝的關鍵!
我針對這個問題,引入了自己的乙個概念:剩餘牌手數。即這手牌,需要消耗的炸彈數。鬥地主的關鍵就是爭奪牌權,剩餘牌手數反映的就是這手牌需要消耗掉自己多少炸彈才能得到打出去的機會。
我把剩餘牌手數的取值範圍定義在:【-1,1】:
這樣一來,牌力的大小只要看兩手牌誰更小就可以簡單比較了,比如三張2我定義的剩餘牌手數是-0.95,而a23456789我定義的是0.55(既不好順也不大),所以如果不考慮其它牌,三個2、a、3-9各一張這些牌最有可能組成的兩種牌型分別是:
因此理論上,就給出的牌,2應該組成三張2。
所以,剩餘牌手數反映的是初始情況下不考慮任何對家的情況(即在叫完牌,對其它三家是什麼樣的牌還是零知識的情況下),只看自己手中的牌做出的乙個基本估計。
那麼,問題來了:三張2我定義的剩餘牌手數是-0.95,而a23456789我定義的是0.55,這是否意味著三張2要比a23456789大?!
當然是不!剩餘牌手數反映的是想打出本手牌需要消耗的炸彈數(如果需要消耗-1手炸彈則代表消耗的是對家的炸彈哦,我們用正負就完成了消耗誰的炸彈的轉換),不同牌型之間的剩餘牌手數隻表明了本手牌的有利程度而已(價值)。這個就是我們前面所說的轉換,要從真實世界各手牌的大小比較,轉換到各手牌的有利程度的比較上!即本手牌能貢獻多大的牌權
但是,問題又來了:單張大鬼和對大鬼的剩餘牌手數都是-0.95,那豈非我們把對大鬼拆為兩個單張的大鬼更為有利?!不是的,如果我們手中所有的牌組合完後,留有兩張以上的單張,那麼兩個單張的大鬼確實要比對大鬼有利,但如果我們手中沒有單張,對方打了次單張之後判斷另外一張大鬼還在我們手中,從此就不出單張了,那所謂的兩個單張大鬼的價值就不是很大了(當然對方的牌型要非常整齊)。所以,剩餘牌手數的正確用法其實是把本型別所有牌手的剩餘牌手數全部累加之後看看還需要消耗多少炸彈!同型別累加後的剩餘牌手數反映了我們打了一手小牌之後能不能收回來,即不需要額外消耗炸彈而繼續保有出牌權。所以我才會把它叫做剩餘牌手數。
比如,我有單張3(0.99)、單張4(0.99)、單張小鬼(-0.4)、單張大鬼(-0.95),那麼單張的剩餘牌手數就是這四手牌各自的剩餘牌手數的累加值:0.63。也就是說我們估計:這樣的四手牌需要消耗自己0.63手炸彈才能出完。
所以除了炸彈,其它型別的牌手,如果剩餘牌手數累計小於某個門限之後,就屬於牌力過剩了(只具有阻擊的用途,但對家判斷該型別你比較強之後就會選擇嘗試其它攻擊路線,這種情況下這些牌力就浪費掉了),我們在計算剩餘牌手數時就不能統計在有效的剩餘牌手數中了:此即再多的大對,也擋不住對家出三帶二的。
最後總結下:
類似剩餘牌手數這樣的先驗性的領域常識、啟發性知識很令人頭疼,如果不抽出來,則人工智慧沒有通用性;可抽出來,又存在數量龐大、處理/應用效率極低的毛病。可能,這也正好對我們人類來說是個福音吧,我們暫時還可以不需要太過憂慮被人工智慧所取代:)
鬥地主演算法1判斷牌型
using unityengine using system.collections.generic 牌型 3 4 5 6 7 8 9 10 11 j 12 q 13 k 14 a 15 2 16 小王 17 大王 public class ddz cardtype 是否是單張 public sta...
鬥地主含賴子的牌型判斷演算法
打出n張牌 可能含有賴子 需要判斷這n張牌能組成什麼牌型 對子 順子 飛機 整體思路 假設我們已經提前那種牌作為癩子。1 找出n張牌中的賴子,假設有m個賴子 2 計算出這剩餘n m張牌的牌值,存到和牌值一一對應的陣列,並記錄對應數量。3 計算剩餘牌能組成對應牌型所需要的賴子是否滿足需要。定義撲克陣列...
鬥地主AI演算法 第六章 牌型判斷
本章實現了上一章提到的檢查當前是否只是一手牌函式ins surcardstype 檢查剩餘的牌是否只是一手牌 是 返回手牌型別資料 不是 返回錯誤型別 cgerror cardgroupdata ins surcardstype int arr 輸入很簡單,就是乙個狀態陣列。輸出是手牌型別結構 牌型...