`
墙头上一根草
  • 浏览: 154530 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

麻将胡牌逻辑 java

阅读更多

      最近写了一个麻将的胡牌逻辑,这个麻将是没有万字牌 和 东西南北风牌,以前也写过麻将胡牌逻辑,都没有记录,这次记录一下,方便以后查阅

 

   

/**
	 * 胡牌
	 * @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;
	}

 

0
0
分享到:
评论
1 楼 oyhuang 2019-08-17  
看不懂啊,这么多行

相关推荐

    各种语言的麻将胡牌算法。干货。 c++ c# lua go js麻将胡牌算法.zip

    本压缩包中包含了多种编程语言实现的麻将胡牌算法,包括C++、C#、Lua、Go以及JavaScript。虽然标签中提到了“Java”,但在这个上下文中,我们主要关注的是其他五种编程语言的实现。 麻将胡牌算法的核心是判断一副...

    简单的麻将胡牌算法

    总结来说,实现“简单的麻将胡牌算法”涉及麻将规则的理解、数据结构的设计、逻辑判断的编写,以及可能的优化和效率提升。通过这样的项目,不仅可以提升编程技能,也能对麻将游戏有更深入的认识。对于想要进一步探索...

    Java麻将算法汇总(胡牌算法、AI算法、查胡算法、评估算法、出牌算法)majiang_algorithm-master.zip

    在Java编程领域,麻将算法是游戏开发中的一个重要组成部分,尤其对于设计复杂的AI系统而言。本压缩包"majiang_algorithm-master.zip"包含了一系列与麻将相关的算法实现,如胡牌算法、AI算法、查胡算法、评估算法和出...

    麻将算法源码(任意癞子)

    分享一个麻将胡牌算法,支持多癞子,自己对麻将胡牌的理解写的一套快速识别胡牌逻辑,核心逻辑500行代码,仅对同条万进行处理,字花牌不包含在内,易理解,1M次随机胡牌牌型大概3秒左右。原创分享,我的算法也许可以...

    麻将游戏Java源码

    1. **游戏逻辑**:麻将游戏涉及到复杂的规则和策略,包括牌型判断、胡牌条件、摸牌算法等。开发者需要了解并实现这些规则,这涉及到对数据结构和算法的熟练掌握,例如使用栈或队列来模拟摸牌过程,用状态机来处理...

    JAVA麻将源代码

    这个项目包含了实现麻将游戏逻辑所需的各类组件和文件,适合对Java编程和游戏开发感兴趣的开发者进行学习和研究。下面将详细阐述其中的关键知识点。 首先,`Main.java`是整个程序的入口点,它通常包含`main`方法,...

    java 麻将小游戏

    总之,Java麻将小游戏的开发涉及到数据结构设计、游戏逻辑实现、用户界面创建、多线程编程等多个方面,是学习和提升Java编程技能的好项目。通过这个项目,开发者可以深入理解面向对象编程思想,同时也能接触到图形...

    Java麻将程序

    在Java中实现麻将程序,涉及到许多核心的计算机科学和软件工程概念,包括面向对象编程、算法设计、数据结构、游戏规则逻辑以及图形用户界面(GUI)的创建。 1. **面向对象编程**:Java是一种面向对象的语言,麻将...

    Java实现的麻将编程

    在麻将游戏中,Java的这些优势得以体现,开发者可以利用Java的多线程来处理游戏逻辑和用户界面的同步,确保游戏流畅运行。 麻将游戏的实现涉及到几个关键部分: 1. **游戏规则**:麻将游戏的规则复杂多样,包括...

    长沙麻将算法和AI源代码

    在开发长沙麻将的算法时,编程者可能会面临各种挑战,如牌型计算、胡牌条件判断、玩家策略优化等。本项目提供了使用链表和STL实现的长沙麻将算法和AI的四个不同版本的源代码。 首先,让我们来探讨一下链表这一数据...

    人工智能AI麻将,麻将AlphaGo,可直接运行

    描述进一步强调了其中包含麻将胡牌算法和AI算法,并且提供了用Java编程语言编写的可执行代码。 麻将胡牌算法是让AI理解麻将游戏规则的关键部分。麻将是一种策略性强、规则复杂的四人桌面游戏,玩家需要通过抓牌、...

    unity3d 麻将

    - **转转麻将**:转转麻将的特点是玩家可以在一定条件下换牌,这需要在游戏逻辑中实现相应的交换规则。 3. **用户交互** - **输入处理**:Unity3D支持鼠标、键盘和触摸屏等多种输入方式,开发者需要编写事件监听...

    java 麻将 游戏

    在游戏逻辑方面,Java可以实现`麻将游戏`类(MahjongGame),其中包含玩家对象、游戏状态(如摸牌、出牌、胡牌)以及游戏规则的判断。每个玩家应该有自己的牌堆(PlayerHand),并且有方法处理吃、碰、杠等操作。...

    简单的单机麻将源码

    【标题】"简单的单机麻将源码"是一个基于Java编程语言实现的单机版麻将游戏项目,它提供了麻将游戏的基本逻辑和算法,适用于学习和研究Java编程、游戏开发或者麻将规则实现的人员。 【描述】中多次强调了“简单”和...

    JAVA麻将红中杠口口翻源码

    【JAVA麻将红中杠口口翻源码】是一款基于JAVA编程语言实现的麻将游戏软件,其核心在于模拟了“红中杠”这一麻将规则,并且加入了“口口翻”的特殊玩法,增加了游戏的趣味性和挑战性。源码的提供使得开发者能够深入...

    麻将源代码

    在麻将源代码中,Java可能用于编写后端逻辑,处理玩家数据、游戏状态管理、网络通信等。它强大的类库和稳定的性能使得它在复杂的游戏系统中得到广泛应用。 【Unity】:Unity是一款流行的跨平台游戏引擎,支持2D和3D...

    一个java fx 做的 麻将小游戏.zip

    你需要理解麻将的基本规则,如胡牌条件、碰、杠、吃等操作,并将其转化为计算机可以理解的逻辑。这涉及到数据结构和算法的设计,如如何表示麻将牌、如何进行洗牌、如何判断玩家是否胡牌等。 4. **用户交互**:...

    麻将全集 2 小程序

    综上所述,麻将全集 2 小程序涵盖了微信小程序开发、Java和iOS后端服务、麻将游戏逻辑实现、应用部署以及二次开发等多个方面的技术知识。无论是对想要学习小程序开发的新手,还是寻求拓展现有项目的专业开发者,这个...

    Java实现的麻将游戏

    6. **游戏逻辑**:实现麻将游戏的规则是一项挑战,包括洗牌、发牌、打牌、碰、杠、胡牌等操作。需要编写清晰的逻辑代码,确保游戏的公平性和一致性。 7. **并发处理**:由于游戏涉及到多个玩家同时操作,服务器需要...

    大众麻将源码

    这些规则在源码中被转化为逻辑算法,包括摸牌逻辑、出牌逻辑、碰杠逻辑以及胡牌判断等。源码中的每一个函数、类和模块都是为了实现这些规则而设计的。 服务器端的实现是整个系统的核心部分,它负责处理玩家的连接、...

Global site tag (gtag.js) - Google Analytics