# 麻将AI算法（下）

	/**
* 手牌能否胡
* @param paiList  所有手牌
* @param show   碰杠牌堆
* @param laiZi  癞子牌
* @return
*/
public static boolean fitHu(List<Integer> paiList, List<Integer> show, Integer laiZi){
boolean huPai=false;

List<Integer> allPai = new ArrayList<>(paiList);
if (!isQueYiMen(allPai,laiZi)) {//判断是否缺一门
return huPai;
}

int[][] memberPai = changeToArr(paiList);
if (huPai(memberPai)) {//能否胡牌
huPai = true;
} else {
if (show == null || show.size() == 0) {
if (duiduiHu(memberPai)){//特殊-对对胡
huPai = true;
}
}
}
return huPai;
}

/**
* 胡手牌
*
* @param allPai
* @return
*/
public static boolean huPai(int[][] allPai) {

int duiZi = 0;// 哪一组牌中存在对子
int yuShu = 0;
boolean duiZiExisted = false;
for (int i = 0; i < 3; i++) {//allPai[i][0] ——某种类型（筒、万、条）牌的数量
yuShu = allPai[i][0] % 3;
if (yuShu == 1) {
return false;
}
if (yuShu == 2) {
if (duiZiExisted) {
return false;
}
duiZi = i;
duiZiExisted = true;
}
}

for (int i = 0; i < 3; i++) {
if (i != duiZi) {
int[] temp = new int[10];
for (int j = 0; j <= 9; j++) {
temp[j] = allPai[i][j];
}
if (!analyze(temp, i == 3)) {
return false;
}
}
}

boolean success = false;
for (int j = 1; j <= 9; j++) {
if (allPai[duiZi][j] >= 2) {
allPai[duiZi][j] = allPai[duiZi][j] - 2;
allPai[duiZi][0] = allPai[duiZi][0] - 2;

int[] temp = new int[10];
for (int k = 0; k <= 9; k++) {
temp[k] = allPai[duiZi][k];
}
if (analyze(temp, duiZi == 3)) {
success = true;
}
allPai[duiZi][j] = allPai[duiZi][j] + 2;
allPai[duiZi][0] = allPai[duiZi][0] + 2;
if (success) {
break;
}
}
}
return success;
}

/**
* 分析每一种牌是否符合
* @param aKindPai
* @param ziPai
* @return
*/
public static boolean analyze(int[] aKindPai, boolean ziPai) {
if (aKindPai[0] == 0) {
return true;
}
int index = 0;
for (int i = 1; i <= 9; i++) {
if (aKindPai[i] != 0) {
index = i;
break;
}
}
boolean result = false;
if (aKindPai[index] >= 3) {
aKindPai[index] = aKindPai[index] - 3;
aKindPai[0] = aKindPai[0] - 3;

result = analyze(aKindPai, ziPai);//回调处理
aKindPai[index] = aKindPai[index] + 3;
aKindPai[0] = aKindPai[0] + 3;
return result;
}

if (!ziPai && index < 8 && aKindPai[index + 1] > 0
&& aKindPai[index + 2] > 0) {
aKindPai[index] = aKindPai[index] - 1;
aKindPai[index + 1] = aKindPai[index + 1] - 1;
aKindPai[index + 2] = aKindPai[index + 2] - 1;
aKindPai[0] = aKindPai[0] - 3;

result = analyze(aKindPai, ziPai);
aKindPai[index] = aKindPai[index] + 1;
aKindPai[index + 1] = aKindPai[index + 1] + 1;
aKindPai[index + 2] = aKindPai[index + 2] + 1;
aKindPai[0] = aKindPai[0] + 3;
return result;
}
return false;
}



	public static void main(String[] args) {
List<Integer> initPais = new ArrayList<>();

List<Integer> show = new ArrayList<>();

Integer laiZi = 32;
boolean canHu = fitHu(initPais, show, laiZi);
System.out.println("canHu?  " + canHu);
}

	/**
* 加入一张赖子牌，判断该手牌能不能胡，返回胡牌集合
*
* @param allPai
* @return huData.size()>0则表示可以胡牌
*/
public static List<List<Integer>> huLaizi(List<Integer> list, Integer laizi, List<Integer> show) {
int[][] allPai = changeToArr(list);
int laiziNum = allPai[laizi / 10 - 1][laizi % 10];//癞子牌数量
allPai[laizi / 10 - 1][laizi % 10] = 0;
allPai[laizi / 10 - 1][0] = allPai[laizi / 10 - 1][0] - laiziNum;//这种牌去掉癞子牌以后剩余牌数量
List<Integer> tingTable = quePai(allPai);//听的牌的集合
if (laiziNum > 0) {
for(int pai : list){
if (pai != laizi && !tingTable.contains(pai)) {
}
}
}
List<List<Integer>> huData = new ArrayList<List<Integer>>();//存放癞子牌的转换牌型
if (laiziNum == 1) {
for (Integer pai : tingTable) {//遍历听牌集合，用一张癞子牌替换判断此时可否胡
int yu = pai / 10 - 1;
int mod = pai % 10;
allPai[yu][mod] = allPai[yu][mod] + 1;
allPai[yu][0] = allPai[yu][0] + 1;
if (fitHu(arrToList(allPai), show, laizi)) {//所有的牌和展示的牌符合胡
List<Integer> data = new ArrayList<Integer>();//癞子牌替换到可以胡牌的牌，如11-13,听牌12,癞子牌替换为12
d
• 3
点赞
• 14
收藏
觉得还不错? 一键收藏
• 4
评论
04-13 7113
08-23
04-19 7978
04-30 5071
06-13
03-28
08-31

### “相关推荐”对你有帮助么？

• 非常没帮助
• 没帮助
• 一般
• 有帮助
• 非常有帮助

1.余额是钱包充值的虚拟货币，按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载，可以购买VIP、付费专栏及课程。