二、牌型分類
來自專欄 棋牌遊戲感悟
鬥地主中,除了王炸這個特殊牌型外,按照序列是否連續,可以分成單純類型和連續類型,比如單張3和3,4,5,6,7, 比如一對7和連對77,88,99等;按照是否有主副牌,可以分成簡單類型和複合類型,比如單張,對子都是簡單類型,三帶一,四帶二都是複合類型。因此,對於牌型,在演算法里用Node類型表示,我們需要以下成員進行區分:
牌型說明
kCardType_Single: 1, // 單純類型, seriaNum == 1 kCardType_Serial: 2, // 單順, 雙順, 三順(飛機), 4順 kCardType_Rocket: 3,self.resetNode = function(type, val, mainN, len, sub) { this.cardType = type ? type : 0; this.value = val ? val : 0; this.mainNum = mainN ? mainN : 0; this.seralNum = len ? len : 0; this.subNum = sub ? sub : 0; this.aggregate = 0.0; this.cards = [];};
cardType是牌型,只有三種,王炸,單純,連續;
value 是牌型的值,單純類型為牌的面值,連續類型為起始牌的面值,相同牌型以此比較大小;
mainNum是主牌張數,比如三帶二和飛機里mainNum=3, 連對時, mainNum=2;seralNum是連續張數,seralNum=1是單純牌型,順子時seralNum>=5;subNum是副牌數目,三帶一和四帶二時subNum=1,三帶二和四帶兩對時,subNum=2;cards是牌型里包括的牌的面值,比如三帶一時,可能就是[3, 3, 3, 4], 連對時,可能就是
[3, 3, 4, 4, 5, 5, 6, 6]等等aggregate是權重,根據不同的情況求出權重,再按照權重排序所有牌型。可以是本牌型的權重,也可以是手牌里除了本牌型外剩下所有牌加在一起的權重。所有牌型表示
鬥地主里牌型有限,如何用Node類型分別,可以列舉如下:
1. 單張, 比如 一張5,
{ cardType = kCardType_Single, value=5, mainNum=1, seralNum=1, subNum=0, cards=[5],};
2. 順子, 比如 6,7,8,9,T,J
{ cardType = kCardType_Serial, value=6, mainNum=1, seralNum=6, subNum=0, cards=[6, 7, 8, 9, T, J],};
3. 對子,比如7,7
{ cardType = kCardType_Single, value=7, mainNum=2, seralNum=1, subNum=0, cards=[7, 7],};
4. 連對, 比如 8, 8, 9, 9, T, T, J, J
{ cardType = kCardType_Serial, value=8, mainNum=2, seralNum=4, subNum=0, cards=[8, 8, 9, 9, T, T, J, J],};
5. 三張不帶,比如, 3, 3, 3
{ cardType = kCardType_Single, value=3, mainNum=3, seralNum=1, subNum=0, cards=[3, 3, 3],};
6. 三帶一,比如 5, 5, 5, 6
{ cardType = kCardType_Single, value=5, mainNum=3, seralNum=1, subNum=1, cards=[5, 5, 5, 6],};
7. 三帶二,比如 5, 5, 5, 6, 6
{ cardType = kCardType_Single, value=5, mainNum=3, seralNum=1, subNum=2, cards=[5, 5, 5, 6, 6],};
8. 飛機,比如 5, 5, 5, 6, 6, 6, 7, 7, 8, 8
{ cardType = kCardType_Serial, value=5, mainNum=3, seralNum=2, subNum=2, cards=[5, 5, 5, 6, 6, 6, 7, 7, 8, 8],};
Node里,除了cards,別的地方沒有反映7, 7, 8, 8 這兩對,它們也不重要。
9. 炸彈,比如 4, 4, 4, 4
{ cardType = kCardType_Single, value=4, mainNum=4, seralNum=1, subNum=0, cards=[4, 4, 4, 4],};
10. 四帶二,比如 8, 8, 8, 8, Q, A
{ cardType = kCardType_Single, value=8, mainNum=4, seralNum=1, subNum=1, cards=[8, 8, 8, 8, Q, A],};
11. 四帶兩對,比如 9, 9, 9, 9, K, K, A, A
{ cardType = kCardType_Single, value=9, mainNum=4, seralNum=1, subNum=2, cards=[9, 9, 9, 9, K, K, A, A],};
12. 飛機大炮,比如 8, 8, 8, 8, 9, 9, 9, 9, 3, 4, Q, A
{ cardType = kCardType_Single, value=8, mainNum=4, seralNum=2, subNum=1, cards=[8, 8, 8, 8, 9, 9, 9, 9, 3, 4, Q, A],};
13. 王炸,只需要看cardType就可以判別
{ cardType = kCardType_Rocket, value=kCard_ValueJoker1, mainNum=1, seralNum=1, subNum=1, cards=[16, 17],};
以上純手打,如果有問題,歡迎提示更正。
與Node 類型相關的操作
Node里包括的操作類型有,創建,比較,合併,獲取等:
創建
create: function(type, val, mainN, len, sub),self.assign = function(other),self.resetNode = function(type, val, mainN, len, sub),
比較
self.isValidNode = function(),self.isRocket = function(),self.isBomb = function(),self.canExtractBomb = function(),self.isExactLessThan = function(other), // 同類型比大小self.isLooseLessThan = function(other), // 不同類型,或者other含有炸彈self.isSola = function(),self.isPair = function(),
合併
self.startFill = function(), // 根據mainNum, value來填充 cards,不含副牌self.getTopValue = function(), // 獲取連續牌最大的面值
獲取
self.getPower = function(), // 獲得本Node的權重,最重要的函數
確定好不同牌型的表示後,我們可以掃描手牌,並且按照權重進行整理,針對不同情況做最優的理牌。
推薦閱讀:
※模擬退火演算法學習筆記
※基數排序
※數學建模演算法總結
※[阿里]獨家 | 一文讀懂複雜網路(應用、模型和研究歷史)
※九章演算法 | Google 面試題:非下降數組