麻将AI算法(下)

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/xiu2016/article/details/76522591

一)在无癞子牌的时候手牌能否胡

设计过程:首先判断玩家是否缺一门,能否胡手牌和对对胡(能否胡牌判读是否为顺子和一个对子)

	/**
	 * 手牌能否胡
	 * @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
					data.add(pai);
					huData.add(data);
				}
				allPai[yu][mod] = allPai[yu][mod] - 1;
				allPai[yu][0] = allPai[yu][0] - 1;
			}
		} else if (laiziNum == 2) {
			for (Integer pai1 : tingTable) {
				for (Integer pai2 : tingTable) {
					int yu1 = pai1 / 10 - 1;
					int mod1 = pai1 % 10;
					int yu2 = pai2 / 10 - 1;
					int mod2 = pai2 % 10;
					allPai[yu1][mod1] = allPai[yu1][mod1] + 1;
					allPai[yu2][mod2] = allPai[yu2][mod2] + 1;
					allPai[yu1][0] = allPai[yu1][0] + 1;
					allPai[yu2][0] = allPai[yu2][0] + 1;
					// ystem.out.println("pai1"+pai1+"pai2:"+pai2);
					if (pai1 == 16 && pai2 == 37) {
//						int i = 0;
					}
					if (fitHu(arrToList(allPai), show, laizi)) {
						List<Integer> data = new ArrayList<Integer>();
						data.add(pai1);
						data.add(pai2);
						huData.add(data);
					}
					allPai[yu1][mod1] = allPai[yu1][mod1] - 1;
					allPai[yu2][mod2] = allPai[yu2][mod2] - 1;
					allPai[yu1][0] = allPai[yu1][0] - 1;
					allPai[yu2][0] = allPai[yu2][0] - 1;
				}
			}
		} else if (laiziNum == 3) {
			for (Integer pai1 : tingTable) {
				for (Integer pai2 : tingTable) {
					for (Integer pai3 : tingTable) {
						int yu1 = pai1 / 10 - 1;
						int mod1 = pai1 % 10;
						int yu2 = pai2 / 10 - 1;
						int mod2 = pai2 % 10;
						int yu3 = pai3 / 10 - 1;
						int mod3 = pai3 % 10;
						allPai[yu1][mod1] = allPai[yu1][mod1] + 1;
						allPai[yu2][mod2] = allPai[yu2][mod2] + 1;
						allPai[yu3][mod3] = allPai[yu3][mod3] + 1;

						allPai[yu1][0] = allPai[yu1][0] + 1;
						allPai[yu2][0] = allPai[yu2][0] + 1;
						allPai[yu3][0] = allPai[yu3][0] + 1;
						if (fitHu(arrToList(allPai), show, laizi)) {
							List<Integer> data = new ArrayList<Integer>();
							data.add(pai1);
							data.add(pai2);
							data.add(pai3);
							huData.add(data);
						}
						allPai[yu1][mod1] = allPai[yu1][mod1] - 1;
						allPai[yu2][mod2] = allPai[yu2][mod2] - 1;
						allPai[yu3][mod3] = allPai[yu3][mod3] - 1;

						allPai[yu1][0] = allPai[yu1][0] - 1;
						allPai[yu2][0] = allPai[yu2][0] - 1;
						allPai[yu3][0] = allPai[yu3][0] - 1;
					}
				}
			}
		} else if (laiziNum == 4) {//四张癞子牌替换四张在听到的牌,看能否胡牌
			for (Integer pai1 : tingTable) {//替换的第一张听牌
				for (Integer pai2 : tingTable) {//替换的第二张
					for (Integer pai3 : tingTable) {//替换第三张
						for (Integer pai4 : tingTable) {//替换第四张
							int yu1 = pai1 / 10 - 1;
							int mod1 = pai1 % 10;
							int yu2 = pai2 / 10 - 1;
							int mod2 = pai2 % 10;
							int yu3 = pai3 / 10 - 1;
							int mod3 = pai3 % 10;
							int yu4 = pai4 / 10 - 1;
							int mod4 = pai4 % 10;
							allPai[yu1][mod1] = allPai[yu1][mod1] + 1;
							allPai[yu2][mod2] = allPai[yu2][mod2] + 1;
							allPai[yu3][mod3] = allPai[yu3][mod3] + 1;
							allPai[yu4][mod4] = allPai[yu4][mod4] + 1;

							allPai[yu1][0] = allPai[yu1][0] + 1;
							allPai[yu2][0] = allPai[yu2][0] + 1;
							allPai[yu3][0] = allPai[yu3][0] + 1;
							allPai[yu4][0] = allPai[yu4][0] + 1;
							if (fitHu(arrToList(allPai), show, laizi)) {
								List<Integer> data = new ArrayList<Integer>();
								data.add(pai1);
								data.add(pai2);
								data.add(pai3);
								data.add(pai4);
								huData.add(data);
							}
							allPai[yu1][mod1] = allPai[yu1][mod1] - 1;
							allPai[yu2][mod2] = allPai[yu2][mod2] - 1;
							allPai[yu3][mod3] = allPai[yu3][mod3] - 1;
							allPai[yu4][mod4] = allPai[yu4][mod4] - 1;

							allPai[yu1][0] = allPai[yu1][0] - 1;
							allPai[yu2][0] = allPai[yu2][0] - 1;
							allPai[yu3][0] = allPai[yu3][0] - 1;
							allPai[yu4][0] = allPai[yu4][0] - 1;
						}
					}
				}
			}
		}

		return huData;
	}

	/**把数组牌转为list牌集
	 * @param paiArr
	 */
	public static List<Integer> arrToList(int[][] paiArr) {
		List<Integer> paiList = new ArrayList<>();
		for (int i = 0; i < 3; i++) {
			for (int j = 0; j < 9; j++) {
				int paiNum = paiArr[i][j];//根据每一张牌的数量逆转
				if (paiNum <= 0) {
					continue;
				}
				for (int k = 0; k < paiArr[i][j]; k++) {
					paiList.add((i+1) * 10 + j);
				}
			}
		}
		return paiList;
	}
	/**
	 * 麻将缺什么牌 型完整
	 * 
	 * @param allPai
	 * @return
	 */
	public static List<Integer> quePai(int[][] allPai) {
		int pai = 0;
		List<Integer> tingTable = new ArrayList<>();
		for (int i = 1; i <= 3; i++) {
			List<Integer> duizi = new ArrayList<Integer>();
			for (int j = 1; j <= 9; j++) {//遍历每一张牌,统计每张牌组合牌型

				pai = 10 * i + j;
				int yu = pai / 10 - 1;
				int mod = pai % 10;
				// 是否有对子
				int size = allPai[yu][mod];//这种牌pai张数
				if (size == 0) {
					continue;
				}

				boolean hasShun = shunFilter(allPai, pai, tingTable);

				if (size == 2 && !hasShun) {//没有带顺序的牌 并且是一对的
					duizi.add(pai);
				}
				if (size == 2 && hasShun) {//有带顺序的牌 并且是一对的
					if (!tingTable.contains(pai)) {
						tingTable.add(pai);
					}
				}
				
				if (size == 2) {
					if (!tingTable.contains(pai)) {
						tingTable.add(pai);
					}
				}
				if (size == 3 && hasShun) {
					duizi.add(pai);
				}
			}
			if (duizi.size() > 1) {
				for (Integer data : duizi) {
					if (!tingTable.contains(data)) {
						tingTable.add(data);
					}
				}
			}
		}
		// 连续牌缺牌的整体判断
		for (int i = 1; i <= 3; i++) {
			Map<Integer, Integer> shun = new HashMap<Integer, Integer>();
			int max = 0;
			int start = 0;
			int yu = i - 1;
			for (int j = 1; j <= 9; j++) {
				int next = 1;
				start = j;
				for (int k = j; k <= 8; k++) {
					if (allPai[yu][k] > 0 && allPai[yu][k + 1] > 0) {
						next++;
					} else {
						break;
					}
				}
				if (next > 3) {
					shun.put(start, next);
				}
				if (next > max) {
					max = next;
					
				}
			}
			for (Map.Entry<Integer, Integer> entry : shun.entrySet()) {

				for (int k = 0; k < entry.getValue(); k++) {
					pai = 10 * i + entry.getKey() + k;
					if (!tingTable.contains(pai)) {
						tingTable.add(pai);
					}
				}
				if (entry.getKey() > 1) {
					pai = 10 * i + entry.getKey() - 1;
					if (!tingTable.contains(pai)) {
						tingTable.add(pai);
					}
				}
				int end = entry.getKey() + entry.getValue();
				if (end < 10) {
					pai = 10 * i + end;
					if (!tingTable.contains(pai)) {
						tingTable.add(pai);
					}
				}

			}
			shun.clear();
		}
		return tingTable;
	}
	
	/**带癞子的七小对的缺牌
	 * @param allPai 所有手牌(除碰杠牌)
	 * @param laizi  癞子牌
	 * @param laiziNum  癞子牌数量
	 * @return
	 */
	public static List<Integer> quePai2(int[][] allPai , int laizi ,int laiziNum) {

		int pai = 0;
		int duiziNum = 0;
		List<Integer> tingTable = new ArrayList<Integer>();
		List<Integer> singlePai = new ArrayList<Integer>();//单张牌
		List<Integer> threePai = new ArrayList<Integer>();//3张牌
		for (int i = 1; i <= 3; i++) {
			for (int j = 1; j <= 9; j++) {
				pai = 10 * i + j;
				int yu = pai / 10 - 1;
				int mod = pai % 10;
				// 是否有对子
				int size = allPai[yu][mod];
				if (size == 0) {
					continue;
				}
				if (size == 1) {
					singlePai.add(pai);
				}
				if (size == 2 ) {
					duiziNum ++;
				}
				if (size == 3) {//龙七对
					threePai.add(pai);
				}
			}
		}
		if (laiziNum == 1 && duiziNum == 6) {
			tingTable.addAll(singlePai);
		}else if (laiziNum == 2 && duiziNum == 5) {
			tingTable.addAll(singlePai);
		}else if (laiziNum == 3 && duiziNum == 4) {
			tingTable.addAll(singlePai);
		}else if (laiziNum == 4 && duiziNum == 3 ) {
			tingTable.addAll(singlePai);
		}
		if (threePai.size() == 1 && duiziNum == 5) {
			tingTable.addAll(threePai);
		}
		return tingTable;
	}
	
	/**
	 * 是否带顺序的牌及其听牌
	 * 
	 * @param allPai  手牌(不包含癞子牌)
	 * @param pai  模拟加入某张牌
	 * @param tingTable  听牌列表
	 * @return
	 */
	private static boolean shunFilter(int[][] allPai, int pai, List<Integer> tingTable) {
		int yu = pai / 10 - 1;//
		int paiNum = pai % 10;//牌号:1——9筒万条
		// 是否有对子
		int size = allPai[yu][paiNum];//某种牌数量
		boolean hasShun = false;
		// 先进性边张判断1-9,2-8,最后3——7,顺子的判断
		if (paiNum == 9) {
			if (allPai[yu][paiNum - 1] >= 1 && allPai[yu][paiNum - 2] >= 1) {
				hasShun = true;
				if (size >= 2 && allPai[yu][paiNum - 1] >= 2) {
					if (!tingTable.contains(pai - 2)) {
						tingTable.add(pai - 2);
					}
				}
				if (size >= 2 && allPai[yu][paiNum - 2] >= 2) {
					if (!tingTable.contains(pai - 1)) {
						tingTable.add(pai - 1);
					}
				}

			} else if (allPai[yu][paiNum - 1] >= 1) {
				if (!tingTable.contains(pai - 2)) {
					tingTable.add(pai - 2);
				}
				hasShun = true;
			} else if (allPai[yu][paiNum - 2] >= 1) {
				if (!tingTable.contains(pai - 1)) {
					tingTable.add(pai - 1);
				}

				if (size == 1) {
					if (!tingTable.contains(pai)) {
						tingTable.add(pai);
					}
				}

				hasShun = true;

			} else {
				if (size == 1) {
					if (!tingTable.contains(pai)) {
						tingTable.add(pai);
					}
				}
			}
		} else if (paiNum == 1) {
			if (allPai[yu][paiNum + 1] >= 1 && allPai[yu][paiNum + 2] >= 1) {
				hasShun = true;
				if (size >= 2 && allPai[yu][paiNum + 1] >= 2) {
					if (!tingTable.contains(pai + 2)) {
						tingTable.add(pai + 2);
					}
				}
				if (size >= 2 && allPai[yu][paiNum + 2] >= 2) {
					if (!tingTable.contains(pai + 1)) {
						tingTable.add(pai + 1);
					}
				}
			} else if (allPai[yu][paiNum + 1] >= 1) {
				if (!tingTable.contains(pai + 2)) {
					tingTable.add(pai + 2);
				}
				hasShun = true;
			} else if (allPai[yu][paiNum + 2] >= 1) {
				if (!tingTable.contains(pai + 1)) {
					tingTable.add(pai + 1);
				}
				if (size == 1) {
					if (!tingTable.contains(pai)) {
						tingTable.add(pai);
					}
				}
				hasShun = true;
			} else {
				if (size == 1) {
					if (!tingTable.contains(pai)) {
						tingTable.add(pai);
					}
				}
			}
		} else if (paiNum == 8) {
			if (allPai[yu][paiNum - 1] >= 1 && allPai[yu][paiNum - 2] >= 1) {
				hasShun = true;
				if (size >= 2 && allPai[yu][paiNum - 1] >= 2) {
					if (!tingTable.contains(pai - 2)) {
						tingTable.add(pai - 2);
					}
				}
				if (size >= 2 && allPai[yu][paiNum - 2] >= 2) {
					if (!tingTable.contains(pai - 1)) {
						tingTable.add(pai - 1);
					}
				}
			} else if (allPai[yu][paiNum - 1] >= 1 && allPai[yu][paiNum + 1] >= 1) {
				hasShun = true;
				if (size >= 2 && allPai[yu][paiNum - 1] >= 2) {
					if (!tingTable.contains(pai + 1)) {
						tingTable.add(pai + 1);
					}
				}
				if (size >= 2 && allPai[yu][paiNum + 1] >= 2) {
					if (!tingTable.contains(pai - 1)) {
						tingTable.add(pai - 1);
					}
				}
			} else if (allPai[yu][paiNum - 1] >= 1) {
				hasShun = true;
				if (!tingTable.contains(pai - 2)) {
					tingTable.add(pai - 2);
				}
				if (!tingTable.contains(pai + 1)) {
					tingTable.add(pai + 1);
				}

			} else if (allPai[yu][paiNum - 2] >= 1 || allPai[yu][paiNum + 1] >= 1) {
				hasShun = true;
				if (!tingTable.contains(pai - 1)) {
					tingTable.add(pai - 1);
				}
				if (size == 1) {
					if (!tingTable.contains(pai)) {
						tingTable.add(pai);
					}
				}
			} else {
				if (size == 1) {
					if (!tingTable.contains(pai)) {
						tingTable.add(pai);
					}
				}
			}
		} else if (paiNum == 2) {
			if (allPai[yu][paiNum + 1] >= 1 && allPai[yu][paiNum + 2] >= 1) {
				hasShun = true;
				if (size >= 2 && allPai[yu][paiNum + 1] >= 2) {
					if (!tingTable.contains(pai + 2)) {
						tingTable.add(pai + 2);
					}
				}
				if (size >= 2 && allPai[yu][paiNum + 2] >= 2) {
					if (!tingTable.contains(pai + 1)) {
						tingTable.add(pai + 1);
					}
				}
			} else if (allPai[yu][paiNum - 1] >= 1 && allPai[yu][paiNum + 1] >= 1) {
				hasShun = true;
				if (size >= 2 && allPai[yu][paiNum + 1] >= 2) {
					if (!tingTable.contains(pai - 1)) {
						tingTable.add(pai - 1);
					}
				}
				if (size >= 2 && allPai[yu][paiNum - 1] >= 2) {
					if (!tingTable.contains(pai + 1)) {
						tingTable.add(pai + 1);
					}
				}
			} else if (allPai[yu][paiNum + 1] >= 1) {
				hasShun = true;
				if (!tingTable.contains(pai + 2)) {
					tingTable.add(pai + 2);
				}
				if (!tingTable.contains(pai + 1)) {
					tingTable.add(pai + 1);
				}
			} else if (allPai[yu][paiNum + 2] >= 1 || allPai[yu][paiNum - 1] >= 1) {
				hasShun = true;
				if (!tingTable.contains(pai + 1)) {
					tingTable.add(pai + 1);
				}
				if (size == 1) {
					if (!tingTable.contains(pai)) {
						tingTable.add(pai);
					}
				}
			} else {
				if (size == 1) {
					if (!tingTable.contains(pai)) {
						tingTable.add(pai);
					}
				}
			}
		} else {
			if (allPai[yu][paiNum - 1] >= 1 && allPai[yu][paiNum + 1] >= 1) {
				hasShun = true;
				if (size >= 2 && allPai[yu][paiNum - 1] >= 2) {
					if (!tingTable.contains(pai + 1)) {
						tingTable.add(pai + 1);
					}
				}
				if (size >= 2 && allPai[yu][paiNum + 1] >= 2) {
					if (!tingTable.contains(pai - 1)) {
						tingTable.add(pai - 1);
					}
				}

			} else if (allPai[yu][paiNum - 1] >= 1 && allPai[yu][paiNum - 2] >= 1) {
				hasShun = true;
				if (size >= 2 && allPai[yu][paiNum - 1] >= 2) {
					if (!tingTable.contains(pai - 2)) {
						tingTable.add(pai - 2);
					}
				}
				if (size >= 2 && allPai[yu][paiNum - 2] >= 2) {
					if (!tingTable.contains(pai - 1)) {
						tingTable.add(pai - 1);
					}
				}
			} else if (allPai[yu][paiNum + 1] >= 1 && allPai[yu][paiNum + 2] >= 1) {
				hasShun = true;
				if (size >= 2 && allPai[yu][paiNum + 1] >= 2) {
					if (!tingTable.contains(pai + 2)) {
						tingTable.add(pai + 2);
					}
				}
				if (size >= 2 && allPai[yu][paiNum + 2] >= 2) {
					if (!tingTable.contains(pai + 1)) {
						tingTable.add(pai + 1);
					}
				}
			} else if (allPai[yu][paiNum - 1] >= 1) {
				hasShun = true;
				if (!tingTable.contains(pai + 1)) {
					tingTable.add(pai + 1);
				}
				if (!tingTable.contains(pai - 2)) {
					tingTable.add(pai - 2);
				}
			} else if (allPai[yu][paiNum + 1] >= 1) {
				hasShun = true;
				if (!tingTable.contains(pai + 2)) {
					tingTable.add(pai + 2);
				}
				if (!tingTable.contains(pai - 1)) {
					tingTable.add(pai - 1);
				}
			} else if (allPai[yu][paiNum - 2] >= 1) {
				if (!tingTable.contains(pai - 1)) {
					tingTable.add(pai - 1);
				}
				if (size == 1) {
					if (!tingTable.contains(pai)) {
						tingTable.add(pai);
					}
				}
			} else if (allPai[yu][paiNum + 2] >= 1) {
				if (!tingTable.contains(pai + 1)) {
					tingTable.add(pai + 1);
				}
				if (size == 1) {
					if (!tingTable.contains(pai)) {
						tingTable.add(pai);
					}
				}
			} else {
				if (size == 1) {
					if (!tingTable.contains(pai)) {
						tingTable.add(pai);
					}
				}
			}
		}
		return hasShun;
	}


四)有癞子时候的飞碰飞杠飞补杠

1)飞杠

	/**
	 * 能否飞杠
	 * @param laizinum  癞子牌
	 * @param lastPai 最后牌桌出的牌
	 * @param memberShouPai  玩家手牌
	 * @return
	 */
	public static boolean canFreeGang(int laizinum, int lastPai, List<Integer> memberShouPai) {
		int free = laizinum;
		if (free == lastPai) {
			return false;
		}
		int[][] memberPai = changeToArr(memberShouPai);
		// 已有该张牌的数量
		int yetNum = memberPai[lastPai / 10 - 1][lastPai % 10];
		int freeNum = memberPai[free / 10 - 1][free % 10];
		if (freeNum > 0 && yetNum >= 2) {
			return true;
		}
		return false;
	}

2)飞碰、飞暗杠、飞补杠

    /**
     * 判断玩家能否飞碰
     * @param targetPai
     * @param handPais
     * @param laiZi
     * @return
     */
    public boolean canFreePeng(Integer targetPai, List<Integer> handPais, Integer laiZi) {
        
    	boolean isCanPeng = false;
    	 int[][] memberPai = changeToArr(handPais);
    	// 已有癞子牌的数量
        int freeNum = memberPai[laiZi / 10 - 1][laiZi % 10];
    	
        //筒-万-条
        for (int i = 0; i < 3; i++) {
            for (int j = 1; j < 10; j++) {
            	int pai = 10 * (i + 1) + j;
            	if (pai >= laiZi ) {
                    continue;
                }
                int count = memberPai[i][j];
                if (count >= 1 && freeNum >= 1) { //1癞子+ >=1同类型牌
                	isCanPeng = true;
                    break;
                } 
            }
        }
        
        return isCanPeng;
    } 
    
	/**
     * 判断玩家能否飞暗杠
     * @param targetPai
     * @param handPais
     * @return
     */
    public boolean canFreeAnGang(Integer targetPai, List<Integer> handPais, Integer laiZi) {
        
    	boolean isCanAnGang = false;
    	handPais.add(targetPai);
    	 int[][] memberPai = changeToArr(handPais);
    	// 已有癞子牌的数量
        int freeNum = memberPai[laiZi / 10 - 1][laiZi % 10];
    	
        //筒-万-条-风
        for (int i = 0; i < 4; i++) {
            for (int j = 1; j < 10; j++) {
            	int pai = 10 * (i + 1) + j;
            	if (pai >= laiZi ) {
                    continue;
                }
                int count = memberPai[i][j];
                if (count >= 3 && freeNum >= 1) { //1癞子+ >=3同类型牌
                    isCanAnGang = true;
                    break;
                } 
            }
        }
        return isCanAnGang;
    } 
    
    /**
     * 判断玩家能否飞补杠
     * 
     * @param targetPai
     *            目标牌
     * @param paiMap
     *            碰杠牌集合
     * @return
     */
    public boolean canFreeExtraGang(Integer targetPai, List<Integer> handPais,Integer laiZi, List<List<Integer>> showPais) {
    	boolean isCanGang = false;
    	//玩家手牌中加入目标牌后判断能否补杠
    	handPais.add(targetPai);
    	 int[][] memberPai = changeToArr(handPais);
    	// 已有癞子牌的数量
        int laiZiNum = memberPai[laiZi / 10 - 1][laiZi % 10];
        for (List<Integer> data : showPais) {
        	if (data.size() != 3) {
                continue;
            }
            if (data.size() == 3) {
                if (data.contains(laiZi)) {//碰牌中已包含癞子牌,加一个同类型牌
                    int yetNum = memberPai[data.get(1) / 10 - 1][data.get(1) % 10];
                    if (yetNum >= 1) {
                    	isCanGang = true;
                    	break;
                    }
                }else {//碰牌中未包含癞子牌,则添加一个癞子牌
                	 if (laiZiNum >= 1) {
                     	isCanGang = true;
                     	break;
                     }
				}
            }
        }
        
        return isCanGang;
    }


五)听牌

1)玩家听什么牌可以胡

	/**
	 * 无赖子牌时听牌
	 * @param allPai
	 * @param show
	 * @param laiZi
	 * @return
	 */
	public static List<Integer> tingPai(int[][] allPai, List<Integer> show, Integer laiZi) {

		int pai = 0;
		List<Integer> tingTable = new ArrayList<>();
		int[][] readyAllPai = allPai;

		for (int i = 1; i <= 3; i++) {
			for (int j = 1; j <= 9; j++) {

				pai = 10 * i + j;
				boolean bool = false;
				if (readyAllPai[i - 1][j] < 4) {// 已经是一杠牌了不处理
					readyAllPai[i - 1][0] = readyAllPai[i - 1][0] + 1;
					readyAllPai[i - 1][j] = readyAllPai[i - 1][j] + 1;
					bool = true;
				}// 遍历添加一张 看是否符合胡牌条件
				if (fitHu(arrToList(readyAllPai),show,laiZi)) {
					tingTable.add(pai);
				}
				if (bool) {
					readyAllPai[i - 1][0] = readyAllPai[i - 1][0] - 1;
					readyAllPai[i - 1][j] = readyAllPai[i - 1][j] - 1;
				}
			}
		}
		return tingTable;
	}
	


	/**
	 * 有癞子牌时检查听牌
	 * 
	 * @param paiList 手牌
	 * @param laiZi 癞子
	 * @param show 碰杠牌
	 * @return
	 */
	public static List<Integer> tingPai2(List<Integer> paiList, int laiZi, List<Integer> show) {
		// 复制
		List<Integer> tingTable = new ArrayList<>();
		List<Integer> shouPai = new ArrayList<Integer>();
		shouPai.addAll(paiList);
		// list转hashmap(hm是用来判断一条杠)
		HashMap<Integer, Integer> hm = new HashMap<Integer, Integer>();
		for (Integer integer : shouPai) {
			if (hm.get(integer) == null) {
				hm.put(integer, 1);
			} else {
				hm.put(hm.get(integer), hm.get(integer) + 1);
			}
		}
		int pai = 0;// 添加的牌
		for (int i = 1; i <= 3; i++) {
			for (int j = 1; j <= 9; j++) {
				boolean bool = false;
				pai = Integer.parseInt(i + "" + j);
				if (hm.get(pai) == null || hm.get(pai) < 4) {
					shouPai.add(pai);
					bool = true;
				}
				if (huLaizi(shouPai, laiZi, show).size() > 0) {
					tingTable.add(pai);
				}
				if (bool) {
					shouPai.remove(shouPai.size() - 1);
				}

			}
		}
		return tingTable;		
	}











展开阅读全文

没有更多推荐了,返回首页