【原創(chuàng)博文专酗,轉載請注明出處尤蛮!】
在分析麻將的排序算法之前我們先大致了解一下麻將玩法中的一些專業(yè)名詞以及其國際化代稱??疏叨。麻將的專有詞匯表。
有了上面這些詞匯基礎降淮,我們開始今天的分享主題----->麻將排序。我將會從兩個方面入手:
①:全部桌牌的排序(例如一副麻將144張牌按規(guī)則排序)搏讶。
②:玩家的手牌排序佳鳖。
首先說明的是①相對②要容易很多,我們先分析①窍蓝。
不同地方的玩法腋颠,實際需要的總牌數(shù)不一樣,我們暫且按144張這種吓笙,反正大同小異淑玫,對我們的算法思路沒有影響。所謂的“規(guī)則”面睛,無非就是先將麻將按照牌的大類(也就是“花色”)排序絮蒿,例如“萬牌”、“條牌”叁鉴、“筒牌”土涝、“箭牌”......,從玩法的專業(yè)詞匯中幌墓,我們知道一副麻將有下面7大類牌:
1. 'CHARACTER',(萬牌)
2. 'BAMBOO',(條牌)
3. 'DOT',(筒牌)
4. 'WIND',(東南西北風牌)
5. 'DRAGON',(紅 發(fā) 白板)
6. 'FLOWER',(梅蘭竹菊)
7. 'SEASON',(春夏秋冬)
大類排序好以后再對大類里面的牌按照一定順序排序(如萬字牌按 “一萬”但壮、“二萬”......“九萬”)。接下來我們就開始對整副牌排序啦常侣,完成開頭提到的任務①蜡饵。
Step One:
將大類規(guī)則按順序存入數(shù)組_defaultRules中??:
_defaultRules : [
'CHARACTER',
'BAMBOO',
'DOT',
'WIND',
'DRAGON',
'FLOWER',
'SEASON',
],
Step Two:
小類所有的牌按順序存入小類數(shù)組管理器中,提供getDot()胳施、 getCharacter()溯祸、getBamboo()、getWind()、getDragon()焦辅、 getSeason()博杖、 getFlower()七個API。
getDot(){
var arr = [
'DOT_1',
'DOT_2',
'DOT_3',
'DOT_4',
'DOT_5',
'DOT_6',
'DOT_7',
'DOT_8',
'DOT_9'
];
return arr;
},
getCharacter(){
......
},
getBamboo(){
......
},
getWind(){
......
},
getDragon(){
......
},
getSeason(){
var arr = [
'SEASON_SPRING',
'SEASON_SUMMER',
'SEASON_AUTUMN',
'SEASON_WINTER'
];
return arr;
},
getFlower(){
var arr = [
'FLOWER_PLUM',
'FLOWER_ORCHID',
'FLOWER_BAMBOO',
'FLOWER_CHRYSANTHEMUM'
];
return arr;
},
完成上面??操作后筷登,我們聲明定義一個空數(shù)組_allMjWithRule :[]剃根,然后將上面七個API的結果依次存入_allMjWithRule中,嗯仆抵,這樣一副牌(共有42種不同的牌)就按照_defaultRules中的規(guī)則依次盛放在_allMjWithRule數(shù)組中跟继。[具體實現(xiàn)如下所示??]
/**
*
* @param {排序規(guī)則的數(shù)組} ruleArr
*/
getAllMjWithRules(ruleArr = this._defaultRules){
this._allMjWithRule = [];
if (ruleArr instanceof Array) {
ruleArr.forEach(element => {
switch (element) {
case 'CHARACTER':{
this.getCharacter().forEach(element => {
this._allMjWithRule.push(element);
});
}
break;
case 'BAMBOO':{
this.getBamboo().forEach(element => {
this._allMjWithRule.push(element);
});
}
break;
case 'DOT':{
this.getDot().forEach(element => {
this._allMjWithRule.push(element);
});
}
break;
case 'WIND':{
this.getWind().forEach(element => {
this._allMjWithRule.push(element);
});
}
break;
case 'DRAGON':{
this.getDragon().forEach(element => {
this._allMjWithRule.push(element);
});
}
break;
case 'FLOWER':{
this.getFlower().forEach(element => {
this._allMjWithRule.push(element);
});
}
break;
case 'SEASON':{
this.getSeason().forEach(element => {
this._allMjWithRule.push(element);
});
}
break;
default:
break;
}
});
return this._allMjWithRule;
}else{
console.log('傳入的排序規(guī)則錯誤');
return;
}
},
排好序的牌結果如下??:
Simulator: JS: CHARACTER_1,CHARACTER_2,CHARACTER_3,CHARACTER_4,CHARACTER_5,CHARACTER_6,CHARACTER_7,CHARACTER_8,CHARACTER_9,BAMBOO_1,BAMBOO_2,BAMBOO_3,BAMBOO_4,BAMBOO_5,BAMBOO_6,BAMBOO_7,BAMBOO_8,BAMBOO_9,DOT_1,DOT_2,DOT_3,DOT_4,DOT_5,DOT_6,DOT_7,DOT_8,DOT_9,WIND_EAST,WIND_SOUTH,WIND_WEST,WIND_NORTH,DRAGON_RED,DRAGON_GREEN,DRAGON_WHITE,FLOWER_PLUM,FLOWER_ORCHID,FLOWER_BAMBOO,FLOWER_CHRYSANTHEMUM,SEASON_SPRING,SEASON_SUMMER,SEASON_AUTUMN,SEASON_WINTER
嗯,上面??講到任務①不難镣丑。簡單地組裝一下就好了舔糖,畢竟是一副完整的牌嘛,每張牌都在莺匠,對號入座罷了金吗。但是針對任務②如何處理呢?一般手牌視麻將玩法而定趣竣,我所知道的“沈家門”和“定阂∶恚”的手牌有14張,那么可能是“ BAMBOO_9”遥缕、“ BAMBOO_5”卫袒、“ DOT_8”、“ CHARACTER_4”单匣、“ BAMBOO_1”夕凝、“ WIND_WEST”、“ DRAGON_RED”...可以有重復的牌户秤,并且某些大類的牌可能沒有码秉,即便有的話也不連貫??,是吧鸡号,怎么排序呢转砖??鲸伴?
其實我們任務①所做的工作也是為任務②做鋪墊的府蔗!任務①我們已經(jīng)將所有的牌排好序了,這樣我們知道“ BAMBOO_9”汞窗、“ BAMBOO_5”姓赤、“ DOT_8”、“ CHARACTER_4”杉辙、“ BAMBOO_1”模捂、“ WIND_WEST”、“ DRAGON_RED”...這些毫無規(guī)律的牌蜘矢,每一張在_allMjWithRule中的位置了吧狂男?那簡單了,我們將手牌依次去_allMjWithRule數(shù)組中映射出自己的位置并設置為自己的localId品腹,代碼如下所示:tempModelArr指的是自己的手牌對象(如:name岖食、serverId、LocalId…)數(shù)組舞吭,
tempModelArr.forEach(element => {
for (const key in this._allMjWithRule) {
//如果未排序的手牌與已經(jīng)排好序的全部牌相同泡垃,則設置未排序手牌的本地id(這個id后面重新設置)
if (element.name === this._allMjWithRule[key]) {
element.localId = key;
}
}
});
這樣,我們將映射完成后的手牌對象放入一個數(shù)組中羡鸥,根據(jù)localId的大小進行排序蔑穴,嘿嘿惧浴,是不是就完成了存和?
tempModelArr.sort(function(a,b){
return a.localId - b.localId;
});
上面就是我最近在游戲開發(fā)中處理的麻將排序算法的分享。