zoukankan      html  css  js  c++  java
  • 麻将基本胡的算法——Java

    算法思想


    胡的条件


    • 必须有一对将(两个相同的牌)
    • 除了将,其余牌必须为顺子或刻子

    算法(精简版)


    1. 提取所有将牌
    2. 去除所有刻子
    3. 去除所有顺子
    4. 没有牌了,胡;还有牌,不胡

    算法(完整版)


    1. 提取所有将牌(如果要胡,将牌是必须存在的,而且将牌可能会有多种)
    2. 取一对将牌,如果没有将牌了,则表示不能胡
    3. 将手牌去除选取的将牌
    4. 将剩余的手牌去除所有的刻子,去除所有的刻子后如果手牌没有了,则胡;手牌还有,则继续第5步判断
    5. 将手牌去除所有的顺子,去除所有的顺子后如果手牌没有了,则胡;手牌还有,则回到第2步重新判断

    Java实现


    代码


    import java.util.Arrays;
    
    /**
     * @author Yawei Xi
     * @date 2018-10-9
     */
    public class MahjongCore {
    
        /**
         * 麻将所有牌型
         * 一万,二万,三万,四万,五万,六万,七万,八万,九万
         * 一筒,二筒,三筒,四筒,五筒,六筒,七筒,八筒,九筒
         * 一条,二条,三条,四条,五条,六条,七条,八条,九条
         * 东,西,南,北,中,发,白
         */
        private static final int[] ALL_CARDS = new int[]{
                11, 12, 13, 14, 15, 16, 17, 18, 19,
                21, 22, 23, 24, 25, 26, 27, 28, 29,
                31, 32, 33, 34, 35, 36, 37, 38, 39,
                50, 60, 70, 80, 90, 100, 110
        };
    
        /**
         * 判断手牌是否胡了
         *
         * @param cards 手牌
         * @return 胡了(true), 没有胡(false)
         */
        public static boolean isHu(int[] cards) {
            if (null == cards) {
                return false;
            }
            // 胡的牌的个数必须是2或5或8或11或14
            if (cards.length != 2 && cards.length != 5 && cards.length != 8 && cards.length != 11 && cards.length != 14) {
                return false;
            }
            // 将手牌中的将取出来
            int[] js = getJiangs(cards);
            if (null == js || js.length <= 0) {
                return false;
            }
    
            for (int j : js) {
                int[] tempCards = Arrays.copyOf(cards, cards.length);
                tempCards = removeOne(tempCards, j);
                tempCards = removeOne(tempCards, j);
                Arrays.sort(tempCards);
                // 去掉所有的刻子
                tempCards = removeAllKe(tempCards);
                if (tempCards.length <= 0) {
                    return true;
                }
    
                // 去掉所有的顺子
                tempCards = removeAllShun(tempCards);
                if (tempCards.length <= 0) {
                    return true;
                }
            }
            return false;
        }
    
        /**
         * 获取牌组中所有的“将”
         *
         * @param cards 牌组
         * @return 所有的“将”组成的数组
         */
        private static int[] getJiangs(int[] cards) {
            int[] res = new int[0];
            if (null != cards && cards.length > 1) {
                for (int i = 0; i < cards.length - 1; i++) {
                    if (cards[i] == cards[i + 1]) {
                        res = add(res, cards[i]);
                        i++;
                    }
                }
            }
            return res;
        }
    
        /**
         * 去掉牌组中所有的刻子
         *
         * @param cards 牌组
         */
        private static int[] removeAllKe(int[] cards) {
            for (int i = 0; i < cards.length - 2; i++) {
                if (cards[i] == cards[i + 1] && cards[i] == cards[i + 2]) {
                    cards = removeOne(cards, cards[i]);
                    cards = removeOne(cards, cards[i]);
                    cards = removeOne(cards, cards[i]);
                }
            }
            return cards;
        }
    
        /**
         * 去掉牌组中所有的顺子
         *
         * @param cards 牌组
         */
        private static int[] removeAllShun(int[] cards) {
            int[] res = Arrays.copyOf(cards, cards.length);
            for (int i = 0; i < cards.length - 2; i++) {
                if (cards[i] + 1 == cards[i + 1] && cards[i + 1] + 1 == cards[i + 2]) {
                    res = removeOne(res, cards[i]);
                    res = removeOne(res, cards[i + 1]);
                    res = removeOne(res, cards[i + 2]);
                    i += 2;
                }
            }
            return res;
        }
    
        /**
         * 获取去掉花色的牌的值
         *
         * @param card 原牌值
         * @return 去掉花色的牌的值
         */
        private static int getCardWithoutSuit(int card) {
            return card % 10;
        }
    
        /**
         * 将牌card加到牌组cards中
         *
         * @param cards 牌组
         * @param card  牌
         * @return 添加后的牌组
         */
        private static int[] add(int[] cards, int card) {
            int[] res = new int[cards.length + 1];
            System.arraycopy(cards, 0, res, 0, cards.length);
            res[res.length - 1] = card;
            return res;
        }
    
        /**
         * 在牌组中去掉一张牌
         *
         * @param cards 牌组
         * @param card  要去掉的牌
         * @return 去掉牌后的牌组
         */
        private static int[] removeOne(int[] cards, int card) {
            if (null == cards || cards.length <= 0) {
                return cards;
            }
            Arrays.sort(cards);
            int index = Arrays.binarySearch(cards, card);
            if (index >= 0) {
                int[] res = new int[cards.length - 1];
                int j = 0;
                for (int i = 0; i < cards.length; i++) {
                    if (i != index) {
                        res[j++] = cards[i];
                    }
                }
                return res;
            }
            return cards;
        }
    
    }
    

    测试用例


    /**
     * @author Yawei Xi
     * @date 2018-10-9
     */
    public class Test {
        public static void main(String[] args) {
            // 空牌组
            int[] a = {};
            // 一万、一万
            int[] b = {11, 11};
            // 一万、二万、三万、四万、四万
            int[] c = {11, 12, 13, 14, 14};
            // 一万、二万、三万、二条、三条、四条、四万、四万
            int[] d = {11, 12, 13, 32, 33, 34, 14, 14};
            // 一万、二万、三万、二条、三条、四条、东风、东风、东风、四万、四万
            int[] e = {11, 12, 13, 32, 33, 34, 50, 50, 50, 14, 14};
            // 一万、二万、三万、二条、三条、四条、东风、东风、东风、五万、五万、五万、四万、四万
            int[] f = {11, 12, 13, 32, 33, 34, 50, 50, 50, 15, 15, 15, 14, 14};
            // 一万、二万、三万、四万、四万、五万、六万、六万、六万、七万、八万、九万、九万、九万
            int[] g = {11, 12, 13, 14, 14, 15, 16, 16, 16, 17, 18, 19, 19, 19};
            // 一万、二万、三万、四万、四万、五万、六万、六万、六万、六万、七万、八万、九万、九万
            int[] h = {11, 12, 13, 14, 14, 15, 16, 16, 16, 16, 17, 18, 19, 19};
    
            System.out.println("a牌型是否胡:" + (MahjongCore.isHu(a) ? "胡" : "不胡"));
            System.out.println("b牌型是否胡:" + (MahjongCore.isHu(b) ? "胡" : "不胡"));
            System.out.println("c牌型是否胡:" + (MahjongCore.isHu(c) ? "胡" : "不胡"));
            System.out.println("d牌型是否胡:" + (MahjongCore.isHu(d) ? "胡" : "不胡"));
            System.out.println("e牌型是否胡:" + (MahjongCore.isHu(e) ? "胡" : "不胡"));
            System.out.println("f牌型是否胡:" + (MahjongCore.isHu(f) ? "胡" : "不胡"));
            System.out.println("g牌型是否胡:" + (MahjongCore.isHu(g) ? "胡" : "不胡"));
            System.out.println("h牌型是否胡:" + (MahjongCore.isHu(h) ? "胡" : "不胡"));
        }
    }
    

    测试结果


    a牌型是否胡:不胡
    b牌型是否胡:胡
    c牌型是否胡:胡
    d牌型是否胡:胡
    e牌型是否胡:胡
    f牌型是否胡:胡
    g牌型是否胡:不胡
    h牌型是否胡:不胡
    
  • 相关阅读:
    我是如何折腾.NET Resx资源文件的 当计算机中的资源已经足够多时,我们也要学会尽可能的借用
    当程序开发人员开始抛弃技术时,是否意味着噩梦的开始?抛弃了SQL Server 2000才发现客户的简单问题真的很难解决
    分享.NET ERP项目开发中应用到的重量级工具 选择合适的工具和资源,做项目效率高而且规范程度高
    Management Console ERP项目开发辅助工具 正确的方法+适当的工具使做项目的效率高而且问题少
    ERP系统管理员的工具箱 推荐几款优秀的数据比较同步工具 Data Compare and Sync tool
    亲自下载CSDN社区600万用户数据 设计两条编程题目考验你的.NET编程基础
    知识管理系统Data Solution研发日记之十六 保存服务器文档为本机PDF格式
    【转】好的学习方法
    iPhone开发学习笔记[7/50]在xcode里配置成功subversion
    iPhone开发学习笔记[4/50]表视图的使用
  • 原文地址:https://www.cnblogs.com/freelancy/p/9761274.html
Copyright © 2011-2022 走看看