算法思想
胡的条件
- 必须有一对将(两个相同的牌)
- 除了将,其余牌必须为顺子或刻子
算法(精简版)
- 提取所有将牌
- 去除所有刻子
- 去除所有顺子
- 没有牌了,胡;还有牌,不胡
算法(完整版)
- 提取所有将牌(如果要胡,将牌是必须存在的,而且将牌可能会有多种)
- 取一对将牌,如果没有将牌了,则表示不能胡
- 将手牌去除选取的将牌
- 将剩余的手牌去除所有的刻子,去除所有的刻子后如果手牌没有了,则胡;手牌还有,则继续第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牌型是否胡:不胡