如何实现Java麻将胡牌算法?开发教程+源码分享

长按可调倍速

js实现麻将的听牌算法

核心数据结构设计

麻将牌对象建模

如何实现Java麻将胡牌算法

public enum MahjongTile {
    // 万子(1-9)
    CHARACTER_1, CHARACTER_2, CHARACTER_3, CHARACTER_4, CHARACTER_5, CHARACTER_6, CHARACTER_7, CHARACTER_8, CHARACTER_9,
    // 筒子
    DOT_1, DOT_2, DOT_3, DOT_4, DOT_5, DOT_6, DOT_7, DOT_8, DOT_9,
    // 索子
    BAMBOO_1, BAMBOO_2, BAMBOO_3, BAMBOO_4, BAMBOO_5, BAMBOO_6, BAMBOO_7, BAMBOO_8, BAMBOO_9,
    // 风牌
    EAST, SOUTH, WEST, NORTH,
    // 箭牌
    RED_DRAGON, GREEN_DRAGON, WHITE_DRAGON;
}

玩家类与游戏状态

public class Player {
    private List<MahjongTile> handTiles = new ArrayList<>();  // 手牌
    private List<MahjongTile> discardedTiles = new ArrayList<>(); // 弃牌
    private boolean isReady;
}
public class GameState {
    private List<MahjongTile> wallTiles = new ArrayList<>();  // 牌墙
    private Player[] players = new Player[4];
    private int currentPlayerIndex;
}

关键逻辑实现

洗牌与初始化

public void initializeGame() {
    // 创建136张牌
    List<MahjongTile> allTiles = new ArrayList<>();
    for (MahjongTile tile : MahjongTile.values()) {
        // 每种牌添加4张(除特殊规则)
        for (int i = 0; i < 4; i++) {
            allTiles.add(tile);
        }
    }
    // Fisher-Yates洗牌算法
    Collections.shuffle(allTiles);
    // 初始化牌墙
    gameState.setWallTiles(allTiles);
}

发牌逻辑

public void dealTiles() {
    for (int round = 0; round < 3; round++) {
        for (Player player : players) {
            for (int i = 0; i < 4; i++) {
                player.drawTile(wallTiles.remove(0));
            }
        }
    }
    // 庄家多摸一张
    players[0].drawTile(wallTiles.remove(0));
}

胡牌算法(核心)

public boolean checkWin(List<MahjongTile> hand) {
    // 1. 将手牌按类型分组
    Map<MahjongTile, Integer> tileCount = new HashMap<>();
    for (MahjongTile tile : hand) {
        tileCount.put(tile, tileCount.getOrDefault(tile, 0) + 1);
    }
    // 2. 检查七对子特殊牌型
    if (checkSevenPairs(tileCount)) return true;
    // 3. 标准胡牌:1对将 + 4组顺子/刻子
    return standardWinCheck(tileCount);
}
private boolean standardWinCheck(Map<MahjongTile, Integer> tiles) {
    // 递归移除将牌和顺子/刻子组合
    // ...
    // 详细实现参考麻将规则状态机
}

网络通信架构

基于Netty的通信框架

如何实现Java麻将胡牌算法

// 消息协议
public class MahjongMessage {
    private int msgType;  // 1:摸牌 2:打牌 3:碰 4:杠 5:胡
    private MahjongTile tile;
    private int playerId;
}
// Netty处理器
public class MahjongServerHandler extends ChannelInboundHandlerAdapter {
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        MahjongMessage request = (MahjongMessage) msg;
        switch (request.getMsgType()) {
            case 1: handleDrawTile(ctx, request); break;
            case 2: handleDiscard(ctx, request); break;
            // ...其他操作
        }
    }
}

性能优化方案

  1. 胡牌算法加速

    • 使用预生成胡牌模式库
    • 位运算表示牌型组合(如用int的二进制位表示特定牌的数量)
  2. 状态同步策略

    • 采用增量更新:仅同步变动牌信息
    • 客户端预测机制:提前计算可能的操作
  3. 防作弊设计

    • 牌墙状态仅存在服务端
    • 关键操作需服务端二次验证
    • 采用种子随机数保证洗牌可验证

测试要点

  1. 牌型验证覆盖率

    • 覆盖常见胡牌牌型(平胡、碰碰胡、清一色等)
    • 特殊规则测试(国标/日麻/川麻差异)
  2. 并发压力测试

    如何实现Java麻将胡牌算法

    • 模拟1000房间同时进行游戏
    • 网络延迟波动测试(200ms-2s延迟)
  3. 异常处理测试

    • 断线重连数据一致性
    • 非法操作拦截(如无效碰牌)

实战建议:开发初期优先实现核心判胡算法,建议采用”状态机+递归回溯”混合方案,对于网络模块,建议使用Protobuf定义通信协议以保证跨平台兼容性,在日麻等变种规则中,需特别注意役种判定与符数计算的复杂度。

您在开发过程中遇到最棘手的技术问题是什么?是胡牌算法的性能瓶颈,还是网络同步的延迟处理?欢迎在评论区分享您的实战经验或技术疑问!

首发原创文章,作者:世雄 - 原生数据库架构专家,如若转载,请注明出处:https://idctop.com/article/30738.html

(0)
上一篇 2026年2月14日 06:52
下一篇 2026年2月14日 06:56

相关推荐

  • 微信公众平台开发url怎么填,url接口配置教程

    微信公众平台开发URL配置是连接业务系统与微信生态的唯一通道,其核心价值在于实现消息的精准接收与服务器的安全验证,这一配置过程不仅决定了公众号能否正常收发消息,更直接关系到后续业务逻辑的执行效率与数据安全,服务器配置的成功与否,是微信开发模式开启的标志,也是所有高级接口调用能力的基础,核心结论:微信公众平台开发……

    2026年3月9日
    10900
  • 华为手机如何开启开发者选项?详细步骤解答疑惑

    华为手机的开发者选项可以通过设置菜单中的“关于手机”选项启用,具体步骤是进入“设置”应用,找到“系统”或“关于手机”,然后连续点击“版本号”7次,系统会提示“您已进入开发者模式”,之后,在设置中会出现“开发人员选项”菜单,其中包含各种调试和测试功能,如USB调试、GPU渲染等,这些功能对于程序开发者来说至关重要……

    2026年2月5日
    17700
  • 2440开发板原理图在哪下载?2440开发板原理图免费下载

    S3C2440开发板的设计核心在于构建稳定可靠的嵌入式硬件底层架构,而2440开发板原理图正是这一架构的直观表达,核心结论在于:读懂并掌握原理图,不仅是硬件调试的基础,更是解决电磁兼容(EMC)问题、实现系统稳定运行的关键钥匙, 一张高质量的原理图,清晰地展示了电源分配网络、时钟系统、存储接口及外设连接的逻辑关……

    2026年3月24日
    7600
  • Sublime插件开发难吗?Sublime Text插件开发教程

    Sublime Text插件开发的核心价值在于通过Python脚本实现编辑器功能的无限扩展,从而构建高度定制化、极致流畅的编码环境,掌握插件开发技术,意味着开发者不再受限于现成工具的功能边界,能够针对特定工作流痛点打造专属效率神器,这是从“工具使用者”向“工具创造者”跨越的关键一步,构建开发环境是sublime……

    2026年3月15日
    8600
  • 如何学习Windows驱动开发?详解PDF下载与实战教程

    Windows驱动开发详解 PDF获取权威的Windows驱动开发详解PDF资源是开发者系统学习的关键起点,推荐微软官方发布的Windows Driver Kit (WDK) 文档(包含完整的PDF手册),以及经典教材《Windows Internals》作者Mark Russinovich的《Windows……

    2026年2月9日
    16430
  • Android开发社区有哪些?国内最好的安卓开发者论坛推荐

    Android开发社区是开发者技术进阶与解决复杂工程问题的核心生态系统,在移动应用开发日益复杂的今天,单打独斗已无法满足快速迭代的需求,深度融入并利用开发社区,是每一位Android开发者从入门到精通的必经之路,通过社区,开发者不仅能获取最新的技术动态,还能在遇到棘手Bug时获得高手的指点,更能通过参与开源项目……

    2026年2月16日
    23230
  • java开发cpu过高怎么排查,java cpu占用率高原因分析

    Java应用CPU使用率飙升甚至服务器宕机,90%以上的情况源于代码逻辑缺陷而非硬件资源不足,核心解决路径在于精准定位高消耗代码并实施算法级或代码级优化,处理CPU性能问题,必须遵循“发现异常、定位线程、追踪堆栈、优化代码”的闭环逻辑,任何脱离代码分析的硬件扩容都是治标不治本, CPU飙升的底层逻辑与根因分析在……

    2026年3月2日
    10100
  • 开发票要注意什么,发票开具时有哪些细节不能错?

    发票管理是企业税务合规的基石,直接关系到企业的税负成本与法律风险,在探讨开发票要注意什么这一核心议题时,首要原则是确保业务真实性与票据合规性的高度统一,企业必须建立严格的发票管理制度,从源头规避虚开风险,在操作中确保信息精准,在流转中保障数据安全,只有构建起全生命周期的发票风控体系,才能在金税四期的大数据监管下……

    2026年2月22日
    11200
  • app开发如何寻找创意?创意app点子大全

    在移动互联深度渗透的当下,应用市场的红利期并未结束,而是进入了“精耕细作”的阶段,成功的应用不再单纯依赖技术堆砌,而是源于精准的需求洞察与差异化的价值主张,App开发的核心竞争力在于将创意转化为可落地的商业解决方案,通过极致的用户体验解决特定场景下的痛点,而非盲目追求功能的大而全, 这一过程需要遵循严谨的逻辑闭……

    2026年4月4日
    5600
  • java开发可以转行做什么?java开发转行方向推荐

    Java开发人员具备极强的底层逻辑思维能力和系统架构潜力,职业转型并非由于行业衰退,而是基于技术复用性的主动跃迁,核心结论是:Java开发可以转行的方向主要集中在技术管理、架构师、大数据处理以及新兴的AI工程化领域,转型的本质是能力维度的平移与升维,而非从零开始, Java语言生态的成熟度决定了从业者在并发处理……

    2026年3月13日
    10200

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

评论列表(3条)

  • 心robot614
    心robot614 2026年2月17日 14:00

    这篇文章讲Java麻将胡牌算法挺实在的,尤其那个牌型用枚举的设计,确实能避免很多低级错误,代码看着也清爽。作为喜欢琢磨并发的人,我脑子里忍不住在想实战场景:这递归回溯的胡牌算法,如果真放到线上麻将平台,四人同时点炮胡牌,压力可不小啊。 递归虽然思路清晰,但层层调用在并发时有点吃性能,尤其胡大牌型(比如清一色)可能要遍历的组合太多。我琢磨着能不能把牌型拆解的任务并行化?比如把“找顺子”和“找刻子”独立成小任务扔进线程池试试。不过难点在牌的组合有依赖关系,分任务时共享状态的同步得小心处理,搞不好反而更慢。 作者用的枚举在并发里倒是个亮点——天生不可变对象,安全省心。要是换用对象实例表示牌,多线程同时修改状态就头疼了。不过递归过程中的临时集合(比如拆分出的顺子组)如果没处理好线程隔离,容易串数据。或许能用ThreadLocal存当前线程的计算状态?或者直接走无共享思路,每次胡牌计算深拷贝一份牌数据?虽然占内存但简单粗暴。 其实这类规则固定的算法,预编译可能更狠。比如把所有胡牌牌型哈希值缓存进ConcurrentHashMap,查胡牌变O(1)操作。不过预处理的时间空间成本得权衡,适合长驻内存的服务端场景。总体感觉思路不错,但要上线还得针对并发场景打磨下性能优化和状态隔离。

    • kind975er
      kind975er 2026年2月17日 15:46

      @心robot614哈哈,你说到点子上了!递归在并发时确实吃性能,你提的并行化思路很有趣。做优化时,真该配个性能监控图表实时看耗时变化,火焰图看调用栈深度特别直观。预编译缓存那招在服务端肯定香。

  • 树树169
    树树169 2026年2月17日 16:49

    作为分布式架构师,我觉得这个算法设计很巧妙。如果扩展到多节点处理在线麻将游戏,能更好地应对并发验证问题,感谢分享源码!