鬥地主之癩子牌型適配方法

場景:相信你們都知道,鬥地主遊戲中有一個新的模式--癩子玩法。所以咱們的出牌的時候,N張正常的牌+M張癩子牌  就可能組合成多種牌型,這中間就涉及到了可否適配相應牌型和如何適配相應的牌型的問題。數組

 

輸入:N張正常的牌,M張癩子牌 固然癩子牌不超過四張。ide

輸出:R種結果,每種結果包含M張癩子牌所適配的正常牌值以及當前適配所表明的牌型。ui

 

言歸正傳,咱們知道鬥地主有以下幾種牌型:this

· 火箭:即雙王(雙鬼牌),什麼牌型均可打,是最大的牌。
· 炸彈:四張同數值牌(如四個5)。除火箭和比本身大的炸彈外,什麼牌型均可打。
· 單牌(一手牌):單個牌。
· 對牌(一手牌):數值相同的兩張牌。
· 三張牌:數值相同的三張牌(如三個10)。
· 三帶一手:數值相同的三張牌+ 一張單牌或一對牌。例如: 333+4或333+44
· 單順:五張或更多的連續單牌(如:34567或678910J)。不包括2點和雙王,不分花色。
· 雙順:三對或更多的連續對牌(如:33445五、88991010JJ)。不包括2點和雙王。
· 三順:二個或更多的連續三張牌(如:33344四、444555666777)。不包括2點和雙王。也叫飛機不帶翅膀。
· 飛機帶翅膀。三順+同數量的一手牌。例如:333444+69 或333444555+667799
· 四帶二:四張牌+兩手牌。例如:5555+3+8或 4444+55+77
 
像炸彈,單牌,雙牌,對牌,三張牌,四帶二這些牌型的適配在這裏就很少說啦。這裏着重講的是 單順,雙順,三順,三帶一及三帶一的飛機,三帶對以及三帶對的飛機牌型適配。


前期處理:
  1 public static enum PokerSuit {
  2         DIAMOND("DIAMOND", 0), CLUB("CLUB", 1), HEART("HEART", 2), SPADE("SPADE", 3), BLACK("BLACK", 4), RED("RED", 5);//black與red是爲大小王準備的
  3 
  4         private final String name;
  5         private final int value;
  6 
  7         PokerSuit(String name, int value) {
  8             this.name = name;
  9             this.value = value;
 10         }
 11 
 12         @Override
 13         public String toString() {
 14             return getName() + ":" + getValue();
 15         }
 16 
 17         public String getName() {
 18             return name;
 19         }
 20 
 21         public int getValue() {
 22             return value;
 23         }
 24 
 25         public static int getSize() {
 26             return 6;
 27         }
 28     }
 29 
 30     public static enum PokerRank {
 31         THREE("THREE", 3), FOUR("FOUR", 4), FIVE("FIVE", 5), SIX("SIX", 6), SEVEN("SEVEN", 7), EIGHT("EIGHT", 8), NINE("NINE", 9),
 32         TEN("TEN", 10), JACKY("JACKY", 11), QUEENE("QUEENE", 12), KING("KING", 13), ACE("ACE", 14), TWO("TWO", 15), JOKER("JOKER", 16);
 33 
 34         private final String name;
 35         private final int value;
 36 
 37         PokerRank(String name, int value) {
 38             this.name = name;
 39             this.value = value;
 40         }
 41 
 42         @Override
 43         public String toString() {
 44             return getName() + ":" + getValue();
 45         }
 46 
 47         public String getName() {
 48             return name;
 49         }
 50 
 51         public int getValue() {
 52             return value;
 53         }
 54 
 55         public static int getSize() {
 56             return 14;
 57         }
 58     }
 59 
 60     public static class PokerCard implements Comparable<PokerCard> {
 61         private int mIndex;
 62         private PokerSuit mSuit;
 63         private PokerRank mRank;
 64 
 65         PokerCard(int index, PokerSuit suit, PokerRank rank) {
 66             this.mIndex = index;
 67             this.mSuit = suit;
 68             this.mRank = rank;
 69         }
 70 
 71         public PokerSuit getSuit() {
 72             return mSuit;
 73         }
 74 
 75         public PokerRank getRank() {
 76             return mRank;
 77         }
 78 
 79         public int getIndex() {
 80             return mIndex;
 81         }
 82 
 83         @Override
 84         public String toString() {
 85             return "CARD[[" + getIndex() + "=" + mSuit.getName() +  ":" + mRank.getName() + "]]";
 86         }
 87 
 88         @Override
 89         public int compareTo(PokerCard another) {
 90             if(this.getRank().getValue() > another.getRank().getValue()) {
 91                 return -1;
 92             } else if(this.getRank().getValue() < another.getRank().getValue()) {
 93                 return 1;
 94             } else {
 95                 if(this.getSuit().getValue() > another.getSuit().getValue()) {
 96                     return -1;
 97                 } else if(this.getSuit().getValue() < another.getSuit().getValue()) {
 98                     return 1;
 99                 } else {
100                     return 0;
101                 }
102             }
103         }
104     }
輸入的總牌數:PokerCard [] inputCards;

咱們將輸入的牌,除癩子外,所有解析成  單張的多少個(PokerRank singleSet[]),對子的多少個(PokerRank pairSet[]),三張的多少個(PokerRank threeSet[]),四張的多少個(PokerRank fourSet[]);癩子解析成癩子張數(PokerRank laiziSet[])。

新建二個輔助數組:
  int [] assistValue = new int [17]; (~,~,~,3,4,5,6,7,8,9,10,J,Q,K,A,2,JOKER)前面三個值是不用的。
  PokerRank[] sAssistRanks = {
null, null, null, PokerRank.THREE, PokerRank.FOUR, PokerRank.FIVE, PokerRank.SIX, PokerRank.SEVEN, PokerRank.EIGHT, PokerRank.NINE,
PokerRank.TEN, PokerRank.JACKY, PokerRank.QUEENE, PokerRank.KING, PokerRank.ACE, PokerRank.TWO, PokerRank.JOKER
};
 
順子的適配(單順,雙順,三順):
順子,必須是3~A之間的連續五個或五個以上的牌組成。因此咱們能夠根據牌的總數來肯定是多少順,而後在3~A之間循環判斷一次就能夠肯定有多少種適配方式。
首先初始化assistValue:
// needLaiziCount 表示當前這張牌若是適配當前牌型的話,須要的癩子牌數。
// 單順:needLaiziCount = 1
// 雙順:needLaiziCount = 2
// 三順:needLaiziCount = 3
        
for(int i=0; i<assistValue.length; i++) {
    assistValue[i] = needLaiziCount;
}
而後根據singleSet, pairSet, threeSet, fourSet的值來填充assistValue的值對應值。
// 在配單順的時候,不該該出現pairSet.length>0或者threeSet.length>0或者fourSet.length>0的狀況。
// 一樣在配雙順的時候,不該該出現threeSet.length>0或者fourSet.length>0的狀況。
// 一樣在配三順的時候,不該該出現fourSet.length>0的狀況。
// 在配單順,雙順,三順的時候也不該該出現JOKER,或者TWO的牌。
// 上述狀況在配以前就應該作下判斷,就能夠直接跳過。
for(int i=0; i<singleSet.length; i++) {
    assistValue[singleSet[i].getValue()] = needLaiziCount - 1;
}
for(int i=0; i<pairSet.length; i++) {
    assistValue[pairSet[i].getValue()] = needLaiziCount - 2;
}
for(int i=0; i<threeSet.length; i++) {
    assistValue[threeSet[i].getValue()] = needLaiziCount - 3;
}
for(int i=0; i<fourSet.length; i++) {
    assistValue[fourSet[i].getValue()] = needLaiziCount - 4;
}
接下來就開始配牌啦:
        // 單順:STRAIGHT_SINGLE_COUNT = 1;雙順:STRAIGHT_SINGLE_COUNT = 2;三順:STRAIGHT_SINGLE_COUNT = 3;
        int straightLength = inputCards.length/STRAIGHT_SINGLE_COUNT;
        int startIndex = straightLength + 2;

        for(int i=startIndex; i<=PokerRank.ACE.getValue(); i++) {
            int valuesCount = 0;
            for(int j=i; j<i+straightLength; j++) {
                valuesCount += assistValue[j];
            }

            if(valuesCount != laiziSet.length) {
                continue; // 不可適配
            }

            // 開始適配
            List<PokerCard> replaceCards = new ArrayList<PokerCard>();
            for(int j=i; j<i+straightLength; j++) {
                for(int k=0; k<assistValue[j]; k++) {
                    // getPokerCard(PokerRank rank) 表示獲取一個牌值爲rank,花色與當前手牌中不重複的PokerCard
                    replaceCards.add(getPokerCard(sAssistRanks[j]));
                }
            }
            
            // 將本次適配的結果保存起來。
            sAllReplaceCards.add(replaceCards);
        }

OK到如今爲止,單雙三順的牌就判斷完畢(其中的一些細節部分須要讀者本身去考慮)。spa

 

三帶一以及三帶一的飛機,三帶對以及三帶對的飛機牌型適配:code

飛機去掉翅膀,就是一個三個的連子,而單個的三張,能夠當作一個特殊的連子。所以咱們首先適配飛機的部分,而後適配翅膀的部分。blog

預處理:若是是三帶對及三帶對的飛機,能夠先將單張的配成對子。 固然,這幾種牌型fourSet.length都不能大於0。three

配飛機的方法同配順子同樣(你們琢磨琢磨)。遊戲

配翅膀就好辦,只要不跟當前手中的牌重複就是啦。get

這個就交給博友們本身思考吧。

相關文章
相關標籤/搜索