算法题 牌型判断 Java

题目

德州扑克的花型由 N 张扑克牌组成 0<N<8,可以组成的牌型按照价值从高到低来区分分别为:

  1. 皇家同花顺:最高为 Ace (一点)的同花顺。
    如 A K Q J 10 的同花顺
  2. 同花顺:同一花色,五张顺字的牌。
    如:K Q J 10 9 的同花顺
  3. 四条:有四张同一点数的牌。
    如:4 4 4 4 9
  4. 葫芦:三张同一点数的牌。加—对其他点数的牌。
    如:3 3 3 10 10
  5. 同花:五张同一花色的牌。
    如:J 10 8 7 5 的全是红桃的牌
  6. 顺子:五张顺连的牌。
    如:5 4 3 2 A 的非同花牌(此牌型为最小的顺子)
  7. 三条:仅有三张同一点数的牌。其余两张点数不同。
    如:9 9 9 5 3
  8. 两对:两张相同点数的牌,加另外两张相同点数的牌。
    如:K K 5 5 2
  9. —对:仅有两张相同点数的牌。
    如:10 10 9 4 2
  10. 高牌:不符合上面任何一种牌型的牌型,由单牌且不连续不同花的组成,以点数决定大小。
    如:A 10 9 5 3 的非同花的牌
    这十种牌型分别输出 HuangJiaTongHuaShun、TongHuaShun、SiTiao、HuLu、TongHua、Shunzi、SanTiao、LiangDui、YiDui、GaoPai
    扑克牌有 4 种花色,分别为(S 表示黑桃,H 表示红心,C 表示草花,D 表示方片)
    本题的输入为任意小于 8 的 N 张牌
    得到的结果为这些牌中排序最靠前的类型。

输入描述:
2(牌数为 2)
SA HA(两张牌为黑桃 A 红心 A)
输出描述:
YiDui(结果为一对)

样例输入:
5
SA SK SQ SJ S10
样例输出:
HuangJiaTongHuashun

求解

package test;

import java.util.*;

public class Test3 {

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		int N = sc.nextInt();

		Map<Character, Integer> map1 = new HashMap<>();
		map1.put('S', 0); map1.put('H', 1); map1.put('C', 2); map1.put('D', 3);

		Map<String, Integer> map2 = new HashMap<>();
		map2.put("J", 10); map2.put("Q", 11); map2.put("K", 12); map2.put("A", 0);

		int[][] hd_count = new int[4][13];
		int[] h_count = new int[4];
		int[] d_count = new int[13];

		for(int n = 0; n < N; ++n) {
			String s = sc.next();
			int i = map1.get(s.charAt(0));
			String dian = s.substring(1);
			Integer j = map2.get(dian);
			if(j == null) j = Integer.valueOf(dian)-1;
			hd_count[i][j]++;
			h_count[i]++;
			d_count[j]++;
		}

		// HuangjiaTongHuaShun
		for(int i = 0; i < 4; ++i) {
			int j = 9;
			for(; j < 13; ++j) {
				if(hd_count[i][j] == 0) break;
			}
			if(j == 13 && hd_count[i][0] > 0) {
				System.out.println("HuangjiaTongHuaShun");
				return;
			}
		}

		// TongHuaShun
		for(int i = 0; i < 4; ++i) {
			int count = 0;
			for(int j = 0; j < 13; ++j) {
				if(hd_count[i][j] > 0) count++;
				else {
					if(count >= 5) {
						System.out.println("TongHuaShun");
						return;
					}else count = 0;
				}
			}
		}

		Map<Integer, Integer> cmap = new HashMap<>();
		for(int i = 0; i < 13; ++i) {
			int count = cmap.getOrDefault(d_count[i], 0);
			cmap.put(d_count[i], count+1);
		}

		// SiTiao
		if(cmap.containsKey(4)) {
			System.out.println("SiTiao");
			return;
		}

		// HuLu
		if(cmap.containsKey(3) && cmap.containsKey(2)) {
			System.out.println("HuLu");
			return;
		}

		// TongHua
		for(int i = 0; i < 4; ++i) {
			if(h_count[i] >= 5) {
				System.out.println("TongHua");
				return;
			}
		}
		
		// ShunZi
		int count = 0;
		for(int i = 0; i < 13; ++i) {
			if(d_count[i] > 0) count++;
			else {
				if(count >= 5) {
					System.out.println("ShunZi");
					return;
				}else count = 0;
			}
		}
		
		// SanTiao
		if(cmap.containsKey(3)) {
			System.out.println("SanTiao");
			return;
		}
		
		// LiangDui
		if(cmap.get(2) >= 2) {
			System.out.println("LiangDui");
			return;
		}
		
		// YiDui
		if(cmap.get(2) == 1) {
			System.out.println("YiDui");
			return;
		}
		
		// GaoPai
		System.out.println("GaoPai");
	}
}
麻将胡牌的算法涉及到很多细节和规则,下面是一个基本的JAVA实现: 1. 首先,我们需要一个表示牌的数据结构,可以使用一个数组或者列表来存储玩家手牌的牌型。 ```java public class Mahjong { public static final int MAX_COUNT = 34; // 麻将牌的总数 public static final int MAX_WEAVE = 4; // 最大组合数 public static final int COLOR_WAN = 0; // 万 public static final int COLOR_TIAO = 1; // 条 public static final int COLOR_TONG = 2; // 筒 public static final int COLOR_FENG = 3; // 风 public static final int COLOR_JIAN = 4; // 箭 public static final int CARD_FENG_EAST = 27; // 东 public static final int CARD_FENG_SOUTH = 28; // 南 public static final int CARD_FENG_WEST = 29; // 西 public static final int CARD_FENG_NORTH = 30; // 北 public static final int CARD_JIAN_ZHONG = 31; // 中 public static final int CARD_JIAN_FA = 32; // 发 public static final int CARD_JIAN_BAI = 33; // 白 private int[] cards = new int[MAX_COUNT]; private int count = 0; // 添加一张牌 public void addCard(int card) { cards[card]++; count++; } // 移除一张牌 public void removeCard(int card) { if (cards[card] > 0) { cards[card]--; count--; } } // 获取指定牌的数量 public int getCardCount(int card) { return cards[card]; } // 清除手牌 public void clear() { for (int i = 0; i < MAX_COUNT; i++) { cards[i] = 0; } count = 0; } // 获取所有牌的数量 public int getCount() { return count; } } ``` 2. 接下来,我们需要实现一个判断是否能够胡牌的函数。这个函数需要考虑到麻将的基本规则,如顺子、刻子、将牌等。 ```java public class MahjongUtils { public static final int MAX_HU_COUNT = 14; // 最大胡牌数 // 判断是否能够胡牌 public static boolean checkHu(Mahjong mahjong) { int[] cards = mahjong.getCards(); int count = mahjong.getCount(); // 如果牌的数量不是3n+2,则不能胡牌 if ((count % 3) != 2) { return false; } // 拆分牌型,分别判断顺子、刻子、将牌 int[] cardsCopy = Arrays.copyOf(cards, cards.length); int[] huCards = new int[MAX_HU_COUNT]; int huCount = 0; for (int i = 0; i < Mahjong.MAX_COUNT; i++) { if (cardsCopy[i] > 0) { // 判断顺子 if (i < Mahjong.CARD_FENG_EAST) { if (i % 9 <= 6 && cardsCopy[i + 1] > 0 && cardsCopy[i + 2] > 0) { cardsCopy[i]--; cardsCopy[i + 1]--; cardsCopy[i + 2]--; } } // 判断刻子 if (cardsCopy[i] >= 3) { cardsCopy[i] -= 3; } // 判断将牌 if (cardsCopy[i] == 2) { huCards[huCount++] = i; cardsCopy[i] -= 2; } } } // 如果剩余的牌型能够组成完整的顺子和刻子,则说明可以胡牌 for (int i = 0; i < Mahjong.MAX_COUNT; i++) { if (cardsCopy[i] != 0) { return false; } } return true; } } ``` 3. 最后,我们可以编写一个测试函数来验证算法的正确性。 ```java public class MahjongTest { public static void main(String[] args) { Mahjong mahjong = new Mahjong(); mahjong.addCard(Mahjong.CARD_WAN_1); mahjong.addCard(Mahjong.CARD_WAN_1); mahjong.addCard(Mahjong.CARD_WAN_1); mahjong.addCard(Mahjong.CARD_WAN_2); mahjong.addCard(Mahjong.CARD_WAN_3); mahjong.addCard(Mahjong.CARD_WAN_4); mahjong.addCard(Mahjong.CARD_WAN_5); mahjong.addCard(Mahjong.CARD_WAN_6); mahjong.addCard(Mahjong.CARD_WAN_7); mahjong.addCard(Mahjong.CARD_WAN_8); mahjong.addCard(Mahjong.CARD_WAN_9); mahjong.addCard(Mahjong.CARD_TONG_1); mahjong.addCard(Mahjong.CARD_TONG_1); boolean isHu = MahjongUtils.checkHu(mahjong); System.out.println("是否胡牌:" + isHu); } } ``` 这样,我们就实现了一个简单的麻将胡牌算法。当然,实际上麻将的规则非常复杂,这个算法只是一个基本的实现,还需要根据具体的麻将规则进行进一步的优化和调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值