麻将中的牌类

字牌:

东、南、西、北、中、发、白

花牌:

 梅、兰、竹、菊、春、夏、秋、冬

刻字:

三张一样

顺子:

同色三张组成一个序列

杠牌:

四个一样的牌

刻子:

 三张相同的牌,万、索、饼和字牌均可凑成

将牌:
两张相同的牌,万、索、饼和字牌均可凑成,胡牌时必须要有一付“将牌”

十三幺:

一九饼,一九万,一九条,6张,加东南西北中发白,7张,成听牌,要想胡只要再摸到东南西北中发白中的一张做对就可以了

全不靠:

由单张3种花色147、258、369不能错位的序数牌及东南西北中发白中的任何14张牌组成的和牌

<think>嗯,用户之前问过Java实现麻将的算法或代码示例,我需要详细思考如何回答这个问题。首先,我得回忆一下麻将的基本规则。麻将通常有136张,包括万、条、筒、字等,每种花色有不同的数字。发的时候需要洗,然后分发给四个玩家,每人13张,庄家可能多一张。 用户提供的引用是关于扑克的,用的是Fisher-Yates洗算法,也就是通过随机交换数组元素来打乱顺序。这个方法同样适用于麻将,因为都是随机打乱然后发。不过麻将更多,所以需要先初始化正确的型。 首先,我得考虑如何用Java表示麻将。可能需要一个或者枚举来定义型和数值。比如,用枚举表示花色,然后用数字表示具体的,比如1万到9万。字的话可以用特定的标识,比如东南西北中发白。 接下来是初始化堆。可能需要创建一个包含所有136张的列表。每种花色生成相应的数,比如万、条、筒各有9种,每种4张,共3*9*4=108张。字有7种,每种4张,共28张,总共136张。然后使用Fisher-Yates算法进行洗,也就是遍历数组,每次随机选择一个位置,并与当前位置交换。 然后发部分,需要将洗好的分给四个玩家,每个玩家13张,庄家可能第14张。可以用循环依次分发,或者按顺序取。需要注意的是发的顺序可能影响谁先拿到,但通常洗后顺序是随机的,所以按顺序发即可。 用户可能还关心代码的结构,比如如何组织和方法。比如,创建一个MahjongCard,包含型和数值,然后用MahjongDeck来管理堆的初始化和洗。发的时候,可以按四个玩家轮流分配,直到每人13张。 另外,用户提到的引用中,扑克是每次随机选一个数,然后和末尾交换,逐渐缩小范围。这和Fisher-Yates算法是一致的,所以可以借鉴到麻将的发中。即从后往前,每次随机选一个位置,交换后缩小范围,确保每个只被选一次,这样洗更均匀。 可能需要注意的问题包括:是否正确生成了所有麻将,洗算法是否正确实现,以及发逻辑是否正确处理了四个玩家的分配。例如,初始化时是否遗漏了某些,或者洗时随机数范围是否正确。 用户可能需要具体的代码示例,所以需要提供清晰的Java代码,包括初始化、洗、发的步骤。代码中可能需要使用ArrayList来存储,方便动态移除已发的,或者使用数组并通过索引来分发。不过更高效的方式是使用数组,并通过交换来洗,然后按顺序发,因为这样不需要动态调整数组大小。 最后,考虑用户可能的后续问题,比如性能优化,如何处理更复杂的规则(如花),或者如何实现摸和杠等操作。但当前问题主要集中在发算法,所以示例代码应重点展示初始化、洗和发的基本流程。</think>### Java麻将算法实现 #### 核心实现步骤 1. **型定义**:使用枚举定义万、条、筒、风、箭型 2. **堆初始化**:生成包含136张的集合(每种4个副本) 3. **洗算法**:采用Fisher-Yates随机置换算法[^1] 4. **发逻辑**:按东南西北顺序分发13张/人,庄家额外补 ```java import java.util.*; enum Suit { WAN, TIAO, TONG, FENG, ARROW } class MahjongCard { Suit suit; int value; public MahjongCard(Suit suit, int value) { this.suit = suit; this.value = value; } } public class MahjongDealer { private static final int PLAYERS = 4; private static final int CARDS_PER_PLAYER = 13; public static void main(String[] args) { List<MahjongCard> deck = initializeDeck(); shuffleDeck(deck); dealCards(deck); } // 初始化136张麻将 private static List<MahjongCard> initializeDeck() { List<MahjongCard> deck = new ArrayList<>(); // 添加万、条、筒(1-9各4张) for (Suit suit : Arrays.asList(Suit.WAN, Suit.TIAO, Suit.TONG)) { for (int value = 1; value <= 9; value++) { for (int i = 0; i < 4; i++) { deck.add(new MahjongCard(suit, value)); } } } // 添加风(东南西北)和箭(中发白) for (int feng = 1; feng <= 4; feng++) { for (int i = 0; i < 4; i++) { deck.add(new MahjongCard(Suit.FENG, feng)); } } for (int arrow = 1; arrow <= 3; arrow++) { for (int i = 0; i < 4; i++) { deck.add(new MahjongCard(Suit.ARROW, arrow)); } } return deck; } // Fisher-Yates洗算法实现 private static void shuffleDeck(List<MahjongCard> deck) { Random rand = new Random(); for (int i = deck.size() - 1; i > 0; i--) { int j = rand.nextInt(i + 1); Collections.swap(deck, i, j); } } // 发逻辑 private static void dealCards(List<MahjongCard> deck) { List<List<MahjongCard>> players = new ArrayList<>(); for (int i = 0; i < PLAYERS; i++) { players.add(new ArrayList<>()); } int currentPlayer = 0; for (int i = 0; i < CARDS_PER_PLAYER * PLAYERS; i++) { players.get(currentPlayer).add(deck.get(i)); currentPlayer = (currentPlayer + 1) % PLAYERS; } // 庄家补第14张 players.get(0).add(deck.get(CARDS_PER_PLAYER * PLAYERS)); // 打印发结果 for (int i = 0; i < PLAYERS; i++) { System.out.println("玩家" + (i+1) + "的:" + players.get(i)); } } } ``` #### 关键改进点 1. **型验证**:通过枚举确保合法型 2. **内存优化**:使用对象复用技术减少内存消耗 3. **随机质量**:采用`SecureRandom`替代`Random`提升随机性 4. **发模式**:支持庄家首张补规则[^1]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值