news 2026/5/6 22:06:25

用Java实现麻将胡牌算法:从牌值映射到递归拆解,一个实战项目带你搞定3N+2

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
用Java实现麻将胡牌算法:从牌值映射到递归拆解,一个实战项目带你搞定3N+2

麻将胡牌算法的Java实现:从数据结构设计到递归拆解实战

麻将作为中国传统博弈游戏,其算法实现一直是开发者们感兴趣的编程挑战。本文将带您从零开始构建一个完整的麻将胡牌判定系统,重点解析3N+2牌型的算法实现。不同于简单的代码堆砌,我们将深入探讨数据结构设计、递归拆解策略以及性能优化技巧,帮助中级Java开发者掌握算法落地的核心方法论。

1. 麻将牌型的数据建模艺术

麻将算法的第一步是建立合理的牌值映射系统。优秀的牌值设计能大幅降低后续算法的复杂度。我们采用分段编码策略:

  • 万子:11-19(一万到九万)
  • 条子:21-29(幺鸡到九条)
  • 筒子:31-39(一筒到九筒)
  • 风牌:41(东)、43(南)、45(西)、47(北)
  • 箭牌:51(中)、53(发)、55(白)

这种设计的精妙之处在于:

// 牌值范围定义示例 public static final List<KVEntity<Integer, Integer>> WAN_TIAO_TONG = Arrays.asList( KVEntity.build(11, 19), // 万 KVEntity.build(21, 29), // 条 KVEntity.build(31, 39) // 筒 );

关键提示:风牌和箭牌采用不连续编码(间隔为2)是为了防止算法误判为顺子。例如东(41)、南(43)、西(45)虽然数值连续,但实际不能组成顺子。

2. 3N+2牌型的判定框架

胡牌的基本模式是N个顺子或刻子加上一对将牌(3N+2)。算法实现分为两个主要阶段:

  1. 找将阶段:遍历所有可能的对子候选
  2. 3N判定阶段:验证剩余牌是否能组成完整的顺子或刻子组合
public static boolean is3N_2(List<Integer> cards) { List<Integer> pais = new ArrayList<>(cards); Collections.sort(pais); // 统计各牌出现次数 HashMap<Integer, Integer> paisCount = MapCountUtil.count(pais); for (Integer pai : paisCount.keySet()) { if (paisCount.get(pai) >= 2) { // 找到可能的将牌 List<Integer> temp = new ArrayList<>(pais); CollectionUtil.removeObjects(temp, pai, 2); // 移除将牌 if (is3N(temp)) { // 检查剩余牌 return true; } } } return false; }

3. 递归拆解:刻子优先原则

3N判定的核心在于如何高效拆解牌型。我们采用刻子优先的递归策略:

private static boolean is3N(List<Integer> cards) { if (cards.isEmpty()) return true; HashMap<Integer, Integer> count = MapCountUtil.count(cards); int first = cards.get(0); // 刻子判定优先 if (count.get(first) >= 3) { List<Integer> temp = new ArrayList<>(cards); CollectionUtil.removeObjects(temp, first, 3); return is3N(temp); } // 顺子判定 if (cards.contains(first+1) && cards.contains(first+2)) { List<Integer> temp = new ArrayList<>(cards); CollectionUtil.removeObjects(temp, first, first+1, first+2); return is3N(temp); } return false; }

技术决策:刻子优先能避免AAABCD这类牌型被错误拆解。如果先拆顺子,AAABCD会被拆为AAD+ABC,而实际上应该拆为AAA+BCD。

4. 性能优化实战技巧

4.1 预处理优化

在进入递归前进行快速预判可以显著提升性能:

// 检查各花色牌数是否能被3整除 for (KVEntity<Integer, Integer> range : WAN_TIAO_TONG) { long count = cards.stream() .filter(c -> c >= range.getK() && c <= range.getV()) .count(); if (count % 3 != 0) return false; }

4.2 记忆化技术

对于高频出现的牌型组合,可以使用缓存来避免重复计算:

private static Map<String, Boolean> cache = new ConcurrentHashMap<>(); private static boolean is3N(List<Integer> cards) { String key = cards.toString(); if (cache.containsKey(key)) { return cache.get(key); } // ...原有逻辑... cache.put(key, result); return result; }

4.3 并行流处理

对于大规模牌型统计,可以利用Java 8的并行流:

long sum = cards.parallelStream() .filter(value -> (value >= kv.getK() && value <= kv.getV())) .mapToLong(Integer::longValue) .sum();

5. 测试用例设计与调试

完善的测试是算法可靠性的保障。我们设计多维度测试案例:

测试类型示例牌型预期结果
基本胡牌11,11,12,13,14,15,16true
七对子11,11,22,22,33,33,44false
复杂牌型11,12,13,14,14,14,21,21,24,25,26true
边界情况41,41,41,43,43,43,45,45,45,47,47true
// JUnit测试示例 @Test public void testHu() { List<Integer> case1 = Arrays.asList(11,12,13,14,15,16,17); assertTrue(HuCheckUtil.is3N_2(case1, 14)); List<Integer> case2 = Arrays.asList(11,12,12,12,12,13,21,21,24,25,26); assertTrue(HuCheckUtil.is3N_2(case2, null)); }

6. 工程化扩展思路

在实际项目中,我们可以进一步扩展该算法:

  1. 支持特殊牌型:如七对、十三幺等
  2. 听牌检测:判断当前牌型距离胡牌还差哪些牌
  3. AI策略:基于牌型分析给出最佳出牌建议
  4. 网络同步:优化算法以适应实时对战场景
// 听牌检测示例 public List<Integer> getWaitingTiles(List<Integer> hand) { List<Integer> allTiles = getAllPossibleTiles(); // 获取所有牌型 List<Integer> waiting = new ArrayList<>(); for (Integer tile : allTiles) { if (is3N_2(hand, tile)) { waiting.add(tile); } } return waiting; }

实现麻将算法时最常见的坑是边界条件处理,比如风牌的特殊性、重复牌的处理等。在项目实践中,建议先编写完备的测试用例,再逐步实现核心算法,最后进行性能调优。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/5 20:18:26

终极英雄联盟工具集:如何用League-Toolkit一键提升游戏体验

终极英雄联盟工具集&#xff1a;如何用League-Toolkit一键提升游戏体验 【免费下载链接】League-Toolkit An all-in-one toolkit for LeagueClient. Gathering power &#x1f680;. 项目地址: https://gitcode.com/gh_mirrors/le/League-Toolkit League-Toolkit是一款功…

作者头像 李华
网站建设 2026/5/6 22:23:00

监管沙盒实测数据:Dify问答响应延迟>800ms时,合规风险指数飙升270%——审计时效性红线首度公开

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;监管沙盒实测数据揭示的合规时效性临界点 在金融与数据密集型行业的监管沙盒实测中&#xff0c;合规响应时间并非线性衰减&#xff0c;而是存在明确的时效性临界点——当业务请求从发起至完成全链路合规…

作者头像 李华
网站建设 2026/5/5 20:14:41

cutcli命令行工具实战指南:从数据处理到自动化脚本优化

1. 项目概述与核心价值最近在折腾一些自动化脚本和命令行工具时&#xff0c;发现了一个挺有意思的GitHub项目&#xff0c;叫xuliang2024/cutcli-cookbook。乍一看这个名字&#xff0c;可能会有点摸不着头脑&#xff0c;cutcli是什么&#xff1f;cookbook又是什么菜谱&#xff1…

作者头像 李华
网站建设 2026/5/5 20:12:10

文本到结构推理:SoT提示技术与T2S-Bench评估实践

1. 项目背景与核心价值文本到结构推理&#xff08;Text-to-Structured Reasoning&#xff09;是当前自然语言处理领域的前沿方向&#xff0c;它要求模型不仅理解文本内容&#xff0c;还要能提取结构化逻辑关系。这个需求在金融报告分析、法律条款解读、医疗诊断辅助等专业场景中…

作者头像 李华
网站建设 2026/5/5 20:11:10

eqMac:macOS系统级音频均衡器的终极解决方案

eqMac&#xff1a;macOS系统级音频均衡器的终极解决方案 【免费下载链接】eqMac macOS System-wide Audio Equalizer & Volume Mixer &#x1f3a7; 项目地址: https://gitcode.com/gh_mirrors/eq/eqMac 你是否曾经为Mac电脑平淡无奇的音质感到困扰&#xff1f;无论…

作者头像 李华