麻将基本胡的算法——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牌型是否胡:不胡
原文地址:https://www.cnblogs.com/freelancy/p/9761274.html