棋牌遊戲開發之地主AI演算法實現
棋牌遊戲開發疑問交流 QQ:325131039(勿發廣告)
棋牌遊戲開發技術交流群: 490287966(勿發廣告)
ps: 轉載自一位遠古大神的,本博文只適合像我一樣的菜鳥閱讀,高手們請別噴呀,謝謝!
“人工智慧”(Artificial Intelligence)簡稱AI。它是研究、開發用於模擬、延伸和擴充套件人的智慧的理論、方法、技術及應用系統的一門新的技術科學。人工智慧研究如何用計算機去模擬、延伸和擴充套件人的智慧;如何把計算機用得更聰明;如何設計和建造具有高智慧水平的計算機應用系統;如何設計和製造更聰明的計算機以及智慧水平更高的智慧計算機等
----------摘自百度百科
在這裡我們主要的談論如何電腦來模擬人的思維出牌,並且實現一種具體的演算法。
名詞解釋:
出牌手數:在假設別人都不要並且滿足出牌規則的情況下,最多幾次能把所有的牌出完,這幾次就叫做出牌手數,你可千萬別理解成這個手術喲。
首先我們可以將地主AI演算法分成2部分來討論。
今天我們來討論第一部分:
拆牌
拆牌是地主AI中比較重要的一部分,拆牌的好壞直接影響著地主AI演算法的高效問題。
我們首先還是上一張圖片,這樣比較直觀,有利於我們以後的討論。
為每一種牌型定義權值的大小:
單張 1
對子 2
三帶 3
連牌 4 (每多一張牌權值+1)
連對 5(每多一對牌,權值+2)
飛機 6(每對以飛機,權值在基礎上+3)
炸彈 7(包括對王在內)
看到這副牌,我們先按照人的正常思路來拆牌看是怎麼樣的。
QQQ 222
45678910J
AA
小鬼 6,4
我們現在就來討論一種方案,看最終能達到這樣的拆牌方案嗎?
我們把拆牌的過程分幾個步驟來討論。
第一步:找牌
定義對應的牌型vector
vector<three> //3條
vector<lianzi> //連子
vector<duizi>//對子
vector<danzhang> //單張
vector<fly> //飛機
首先 找出一副牌中只能組成一種牌型的牌(3條,對子,單張為一種牌型。)意思就是有一張牌和剩餘牌中的任何一張牌沒有聯絡。當然是否和剩餘的牌有聯絡是需要定義一個規則的:是否和剩餘的牌能組成連子,連隊。如果這2個條件都不滿足那麼我們稱這張牌和剩餘的牌沒有任何聯絡。一般情況下通過這個步驟就能找出幾張牌,這樣能為以後的拆牌減輕任務量。
比如上面我們就能找出:小鬼,2,A,接下來找出牌值和他們一樣的牌。即小鬼,222,AA,剩下的牌就是:QQQJ1098766544,可能有人會問為什麼沒有找出QQQ了,這是因為Q除了能組成3條,對子以外,還能和剩餘的牌組合成連牌。這裡找出來是對子最終的拆牌方案中就為對子,是連3條就是3條。3條>對>單張 於是有了我們接下來的結論。
vector<three> 222
vector<duizi> AA
vector<danzhang> 小鬼
接下來我們就來拆分剩餘的牌:QQQJ1098766544
找出牌中所有的炸彈
找出牌中所有的3個
找出牌中所有的對子
根據剩餘的牌我們首先提出 QQQ 66 44
我們這裡可以定義對應的vector來存入我們臨時找出的牌,注意裡定義的vector和上面的vector是不一樣的。
vector<three> QQQ
vector<two>66,44
第二步:計算每一種牌的手數和權值問題(拆牌中的難點)
分幾種情況來討論,每次只找出剩餘牌中的5張連牌,然後拿這5張連牌和剩餘牌依次拼接看能否組合成更長的連牌
提出牌之後,剩餘的全部牌全部看做為單牌,不管是炸彈,3條,還是對子。
1 在剩餘牌中提出QQQ ,J1098766544 首先找出5張單牌,從最小還是最大由你來決定。我們這裡就以最小來討論。
第一次:45678 剩餘牌為 4 6 9 10 J
第二次:45678910J 46
最後拆出來的2組牌都沒有聯絡,拆牌結束。
方案為:45678910J 4 6 QQQ
對應的權值和手數:7+1+1+3 =12 3(因為3個可以帶一張或者是1對,當有對子和單張張的時候手數要減去1)
以下的幾種方案也是同樣的步驟,我就不寫過程了,直接寫最終的方案。
2在剩餘牌中提出 QQQ 66
方案為: QQQ 66 78910j 5 44
對應的權值和手數: 3+2+4+1+2=12 4
3.在剩餘牌中提出 QQQ 44
方案為: QQQ 44 678910j 6
對應的權值和手數:3+2+5+1 =11 3
4 .在剩餘排中提出 66
方案為: 66 78910jQ QQ 5 44
對應的權值和手數:2+5+2+1+2=10 5
5 .在剩餘牌中提出 44
方案為: 44 5678910JQ 6 QQ
對應的權值和手數:2+7+1+2 =12 4
6 .什麼牌也不提出
45678910JQ 4 6 Q
對應的權值和手數:9+1+1+1=12 4
第三步:選出最優的一組牌作為最後的拆牌方案
通過以上步驟我們確定出了幾種出牌方案,我們最後找出出牌手數最小的方案。
如果手數相同的情況下,找權值最大的一組拆牌方案。
如果2者都相同,就隨機選一種就是了。(這種情況很小很小)
通過比較我們確定了下面的這一種拆牌方案。
方案為:45678910J 4 6 QQQ
對應的權值和手數:7+1+1+3 =12 3(因為3個可以帶一張或者是1對,當有對子和單張張的時候手數要減去1)
最後加入我們最先找出的牌,最終的拆牌方案為:
vector<three> 222 ,QQQ
vector<duizi> AA
vector<danzhang> 小鬼 ,4,6
vector<lianzi> 45678910J
呵呵,通過這樣拆出來的牌是不是很符合正常人的思維呀。
我們拆這樣一種拆牌方案出來是當電腦出牌的時候用。
當然我們還需要定義一個結構體來存入每張牌能組成的所有牌型。和每種牌型的最大值,這樣供以後的接牌最準備。
好了,就到這裡了,以後再來討論出牌!!