麻将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);
		allPai.addAll(show);
		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<>();
		initPais.add(11);
		initPais.add(11);
		
		initPais.add(13);
		initPais.add(14);
		initPais.add(15);
		
		initPais.add(16);
		initPais.add(17);
		initPais.add(18);
		
		List<Integer> show = new ArrayList<>();
		show.add(19);//碰牌 9万
		show.add(19);
		show.add(19);
		show.add(21);//杠牌 1条
		show.add(21);
		show.add(21);
		show.add(21);
		
		Integer laiZi = 32;
		boolean canHu = fitHu(initPais, show, laiZi);
		System.out.println("canHu?  " + canHu);
	}

结果   canHu ?  true


三)手牌中有癞子牌时


	/**
	 * 加入一张赖子牌,判断该手牌能不能胡,返回胡牌集合
	 *
	 * @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);//听的牌的集合
		tingTable.add(laizi);
		if (laiziNum > 0) {
			for(int pai : list){
				if (pai != laizi && !tingTable.contains(pai)) {
					tingTable.add(pai);
				}
			}
		}
		List<List<Integer>> huData = new ArrayList<List<Integer>>();//存放癞子牌的转换牌型
		tingTable.addAll(quePai2(allPai, laizi, laiziNum));//带癞子的七小对的缺牌
		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
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值