麻将胡牌逻辑 java
程序员文章站
2022-05-10 21:30:38
...
最近写了一个麻将的胡牌逻辑,这个麻将是没有万字牌 和 东西南北风牌,以前也写过麻将胡牌逻辑,都没有记录,这次记录一下,方便以后查阅
/** * 胡牌 * @param isZiMo 是否自摸 * @param roleId 胡牌玩家 * @param pcc 麻将场 */ public static boolean huCard(boolean isZiMo,int roleId,PlayCardContext pcc){ PlayCardUnit pcu = pcc.getCardUnitByRoleId(roleId); List<Byte> handCards = pcu.getCards(); List<OperateCardData> chiPengGangCard = pcu.getChiPengGangCard(); int cardSize = handCards.size(); //1-9的索引为筒子 11-19为条子 21-23为中发白 byte[] cards = new byte[24]; byte[] color = new byte[3]; for (int i = 0; i < cardSize; i++) { byte cardId = handCards.get(i); SCard card = (SCard) StaticData.getStaticModel(EStaticData.CARD, cardId); int index = 0; if(card.type == EColorType.TONG_ZI.getType()){ index = card.value; color[0]++; }else if (card.type == EColorType.TIAO_ZI.getType()) { index = 10+card.value; color[1]++; }else { index = 20+card.value; color[2]++; } cards[index]++; } int colorCount = (color[0]!=0?1:0)+(color[1]!=0?1:0)+(color[2]!=0?1:0); boolean isSameColor = colorCount==1; if(isSameColor){ int size = chiPengGangCard==null?0:chiPengGangCard.size(); if(size>0){ for (int i = 0; i < size; i++) {//计算吃碰杠的牌是否清一色 OperateCardData ocd = chiPengGangCard.get(i); SCard card = (SCard) StaticData.getStaticModel(EStaticData.CARD, ocd.getCards().get(0)); if(card.type == EColorType.TONG_ZI.getType()){ color[0]++; }else if (card.type == EColorType.TIAO_ZI.getType()) { color[1]++; }else { color[2]++; } } colorCount = (color[0]!=0?1:0)+(color[1]!=0?1:0)+(color[2]!=0?1:0); isSameColor = colorCount==1; } } List<String> huCardPatterns = new ArrayList<>();//胡牌牌型 int fanCount =isHu(cards, cardSize, chiPengGangCard,isSameColor,huCardPatterns); boolean isHuCard = fanCount !=-1; if(isHuCard){ pcc.setStart(false); pcc.setReadyRoleIds(null); pcc.calHuScore(roleId, isZiMo, fanCount); pcc.setWinUnit(pcu); } return isHuCard; } /** * 是否胡牌 * @param cards 具有的手牌信息 * @param cardSize 手牌数量 * @param chiPengGangCard 所有吃碰杠的牌 * @param isSameColor 是否清一色 * @return -1-没有胡牌 其他-为胡牌的翻数 */ public static int isHu(byte[] cards,int cardSize,List<OperateCardData> chiPengGangCard,boolean isSameColor,List<String> huCardPatterns){ if(cardSize<2||((cardSize-2)%3)!=0) return -1;//查看牌型是否满足3n+2 Map<Byte,Byte> cardTypeCounts = new HashMap<>(3); Map<Byte,Byte> chiPengGang = new HashMap<>(3); for (int i = 0; i < CARD_COUNT; i++) {//计算手牌 每种牌 的数量(0 1 2 3 4) byte count = cards[i]; if(count<=1) continue; Byte inCount = cardTypeCounts.get(count); cardTypeCounts.put(count, (byte)(1+(inCount==null?0:inCount))); } int size = chiPengGangCard==null?0:chiPengGangCard.size(); for (int i = 0; i < size; i++) {//计算吃碰杠的牌 OperateCardData ocd = chiPengGangCard.get(i); if(ocd.getCardType() == EOperateCardType.CHI_TYPE){ Byte inCount = cardTypeCounts.get((byte)1); cardTypeCounts.put((byte)1, (byte)(1+(inCount==null?0:inCount))); }else if(ocd.getCardType() == EOperateCardType.PENG_TYPE){ Byte inCount = cardTypeCounts.get((byte)2); cardTypeCounts.put((byte)2, (byte)(1+(inCount==null?0:inCount))); }else if(ocd.getCardType() == EOperateCardType.AN_GANG_TYPE ||ocd.getCardType() == EOperateCardType.MING_GANG_TYPE){ Byte inCount = cardTypeCounts.get((byte)3); cardTypeCounts.put((byte)3, (byte)(1+(inCount==null?0:inCount))); } } Byte qiDuiZiCount = cardTypeCounts.get((byte)2);//对子的数量 Byte anGangCount = cardTypeCounts.get((byte)4);//四个的数量 Byte anKeCount = cardTypeCounts.get((byte)3);//三个的数量 Byte chiCardCount = chiPengGang.get((byte)1);//吃的数量 Byte mingKeCount = chiPengGang.get((byte)2);//碰的数量 Byte mingGangCount = chiPengGang.get((byte)3);//杠的数量(包括明杠 暗杠) //七对子的数量 int qdzCount = (qiDuiZiCount==null?0:qiDuiZiCount)+(anGangCount==null?0:(anGangCount*2)); //刻和杠的数量 int keZiAndGangCount = (anGangCount==null?0:anGangCount)+(mingGangCount==null?0:mingGangCount) +(anKeCount==null?0:anKeCount)+(mingKeCount==null?0:mingKeCount); //吃碰杠的数量 int chiPengGangCount = (mingGangCount==null?0:mingGangCount) +(chiCardCount==null?0:chiCardCount)+(mingKeCount==null?0:mingKeCount); int hongZhongCount = cards[21]; int faCaiCount = cards[22]; int baiBanCount = cards[23]; //红中 发财 白板的数量 int totalCount = hongZhongCount+faCaiCount+baiBanCount; if(qdzCount==7){//七对子 if(isSameColor){//清一色七对子 huCardPatterns.add(Hu_card_type_1); return 8; }else if (anGangCount!=null) {//豪华七对子 huCardPatterns.add(Hu_card_type_3); return 8; }else if (totalCount>=8){//三元七对 huCardPatterns.add(Hu_card_type_4); return 8; } huCardPatterns.add(Hu_card_type_2); return 4; }else if(chiCardCount==null&&(qiDuiZiCount==null? 0:qiDuiZiCount)==1&&keZiAndGangCount>=4){//碰碰胡 huCardPatterns.add(Hu_card_type_5); if(isSameColor){ huCardPatterns.add(Hu_card_type_1); return 8; } return 4; }else if((qiDuiZiCount==null?0:qiDuiZiCount)==1&&chiPengGangCount>=4){//手抓一 huCardPatterns.add(Hu_card_type_6); if(isSameColor){ huCardPatterns.add(Hu_card_type_1); return 8; } return 4; }else {//普通胡牌 List<List<CardTypeData>> cardTypeDatas = new ArrayList<>(); for (int i = 0; i < CARD_COUNT; i++) { int count = cards[i]; if(count>=2){ byte[] data = new byte[CARD_COUNT]; System.arraycopy(cards, 0, data, 0, CARD_COUNT); data[i] -=2 ; List<CardTypeData> currData = new ArrayList<>(); currData.add(new CardTypeData(ECardType.JIANG, data[i])); if (isHuCurrCardType(data, currData)) { cardTypeDatas.add(currData); } } } if(cardTypeDatas.size()<=0) return -1;//不胡牌 if(totalCount==8){//小三元 huCardPatterns.add(Hu_card_type_7); return 4; }else if(totalCount==9){//大三元 huCardPatterns.add(Hu_card_type_8); return 8; } huCardPatterns.add(Hu_card_type_9); return 1; } } /** * 当前牌型是否能胡牌 * @param cards 胡牌信息 * @param result 胡牌牌型 * @return */ private static boolean isHuCurrCardType(byte[] cards,List<CardTypeData> result){ for (int i = 0; i < CARD_COUNT; i++) { int value = cards[i]; if(value == 0) continue; if(value ==1||value ==4){ if(i>20||cards[i+1]<1||cards[i+2]<1) return false; result.add(new CardTypeData(ECardType.SHUN_ZI, (byte)cards[i+2])); cards[i]--; cards[i+1]--; cards[i+2]--; if(value ==4){ result.add(new CardTypeData(ECardType.AN_KE_ZI, (byte)value)); cards[i]=0; } }else if (value ==2) { if(i>20||cards[i+1]<2||cards[i+2]<2) return false; cards[i]-=2; cards[i+1]-=2; cards[i+2]-=2; CardTypeData ctd = new CardTypeData(ECardType.SHUN_ZI, (byte)cards[i+2]); result.add(ctd); result.add(ctd); }else if (value ==3) { result.add(new CardTypeData(ECardType.AN_KE_ZI, (byte)value)); cards[i]=0; } isHuCurrCardType(cards, result); } return true; }
上一篇: 一路前行,一路珍惜
下一篇: 念你,只为光阴许我的柔情
推荐阅读