麻将AI算法(下)

时间:2025-03-11 22:45:41
  • /**
  • * 加入一张赖子牌,判断该手牌能不能胡,返回胡牌集合
  • *
  • * @param allPai
  • * @return ()>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);//听的牌的集合
  • (laizi);
  • if (laiziNum > 0) {
  • for(int pai : list){
  • if (pai != laizi && !(pai)) {
  • (pai);
  • }
  • }
  • }
  • List<List<Integer>> huData = new ArrayList<List<Integer>>();//存放癞子牌的转换牌型
  • (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
  • (pai);
  • (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;
  • // ("pai1"+pai1+"pai2:"+pai2);
  • if (pai1 == 16 && pai2 == 37) {
  • // int i = 0;
  • }
  • if (fitHu(arrToList(allPai), show, laizi)) {
  • List<Integer> data = new ArrayList<Integer>();
  • (pai1);
  • (pai2);
  • (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>();
  • (pai1);
  • (pai2);
  • (pai3);
  • (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>();
  • (pai1);
  • (pai2);
  • (pai3);
  • (pai4);
  • (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++) {
  • ((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) {//没有带顺序的牌 并且是一对的
  • (pai);
  • }
  • if (size == 2 && hasShun) {//有带顺序的牌 并且是一对的
  • if (!(pai)) {
  • (pai);
  • }
  • }
  • if (size == 2) {
  • if (!(pai)) {
  • (pai);
  • }
  • }
  • if (size == 3 && hasShun) {
  • (pai);
  • }
  • }
  • if (() > 1) {
  • for (Integer data : duizi) {
  • if (!(data)) {
  • (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) {
  • (start, next);
  • }
  • if (next > max) {
  • max = next;
  • }
  • }
  • for (<Integer, Integer> entry : ()) {
  • for (int k = 0; k < (); k++) {
  • pai = 10 * i + () + k;
  • if (!(pai)) {
  • (pai);
  • }
  • }
  • if (() > 1) {
  • pai = 10 * i + () - 1;
  • if (!(pai)) {
  • (pai);
  • }
  • }
  • int end = () + ();
  • if (end < 10) {
  • pai = 10 * i + end;
  • if (!(pai)) {
  • (pai);
  • }
  • }
  • }
  • ();
  • }
  • 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) {
  • (pai);
  • }
  • if (size == 2 ) {
  • duiziNum ++;
  • }
  • if (size == 3) {//龙七对
  • (pai);
  • }
  • }
  • }
  • if (laiziNum == 1 && duiziNum == 6) {
  • (singlePai);
  • }else if (laiziNum == 2 && duiziNum == 5) {
  • (singlePai);
  • }else if (laiziNum == 3 && duiziNum == 4) {
  • (singlePai);
  • }else if (laiziNum == 4 && duiziNum == 3 ) {
  • (singlePai);
  • }
  • if (() == 1 && duiziNum == 5) {
  • (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 (!(pai - 2)) {
  • (pai - 2);
  • }
  • }
  • if (size >= 2 && allPai[yu][paiNum - 2] >= 2) {
  • if (!(pai - 1)) {
  • (pai - 1);
  • }
  • }
  • } else if (allPai[yu][paiNum - 1] >= 1) {
  • if (!(pai - 2)) {
  • (pai - 2);
  • }
  • hasShun = true;
  • } else if (allPai[yu][paiNum - 2] >= 1) {
  • if (!(pai - 1)) {
  • (pai - 1);
  • }
  • if (size == 1) {
  • if (!(pai)) {
  • (pai);
  • }
  • }
  • hasShun = true;
  • } else {
  • if (size == 1) {
  • if (!(pai)) {
  • (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 (!(pai + 2)) {
  • (pai + 2);
  • }
  • }
  • if (size >= 2 && allPai[yu][paiNum + 2] >= 2) {
  • if (!(pai + 1)) {
  • (pai + 1);
  • }
  • }
  • } else if (allPai[yu][paiNum + 1] >= 1) {
  • if (!(pai + 2)) {
  • (pai + 2);
  • }
  • hasShun = true;
  • } else if (allPai[yu][paiNum + 2] >= 1) {
  • if (!(pai + 1)) {
  • (pai + 1);
  • }
  • if (size == 1) {
  • if (!(pai)) {
  • (pai);
  • }
  • }
  • hasShun = true;
  • } else {
  • if (size == 1) {
  • if (!(pai)) {
  • (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 (!(pai - 2)) {
  • (pai - 2);
  • }
  • }
  • if (size >= 2 && allPai[yu][paiNum - 2] >= 2) {
  • if (!(pai - 1)) {
  • (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 (!(pai + 1)) {
  • (pai + 1);
  • }
  • }
  • if (size >= 2 && allPai[yu][paiNum + 1] >= 2) {
  • if (!(pai - 1)) {
  • (pai - 1);
  • }
  • }
  • } else if (allPai[yu][paiNum - 1] >= 1) {
  • hasShun = true;
  • if (!(pai - 2)) {
  • (pai - 2);
  • }
  • if (!(pai + 1)) {
  • (pai + 1);
  • }
  • } else if (allPai[yu][paiNum - 2] >= 1 || allPai[yu][paiNum + 1] >= 1) {
  • hasShun = true;
  • if (!(pai - 1)) {
  • (pai - 1);
  • }
  • if (size == 1) {
  • if (!(pai)) {
  • (pai);
  • }
  • }
  • } else {
  • if (size == 1) {
  • if (!(pai)) {
  • (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 (!(pai + 2)) {
  • (pai + 2);
  • }
  • }
  • if (size >= 2 && allPai[yu][paiNum + 2] >= 2) {
  • if (!(pai + 1)) {
  • (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 (!(pai - 1)) {
  • (pai - 1);
  • }
  • }
  • if (size >= 2 && allPai[yu][paiNum - 1] >= 2) {
  • if (!(pai + 1)) {
  • (pai + 1);
  • }
  • }
  • } else if (allPai[yu][paiNum + 1] >= 1) {
  • hasShun = true;
  • if (!(pai + 2)) {
  • (pai + 2);
  • }
  • if (!(pai + 1)) {
  • (pai + 1);
  • }
  • } else if (allPai[yu][paiNum + 2] >= 1 || allPai[yu][paiNum - 1] >= 1) {
  • hasShun = true;
  • if (!(pai + 1)) {
  • (pai + 1);
  • }
  • if (size == 1) {
  • if (!(pai)) {
  • (pai);
  • }
  • }
  • } else {
  • if (size == 1) {
  • if (!(pai)) {
  • (pai);
  • }
  • }
  • }
  • } else {
  • if (allPai[yu][paiNum - 1] >= 1 && allPai[yu][paiNum + 1] >= 1) {
  • hasShun = true;
  • if (size >= 2 && allPai[yu][paiNum - 1] >= 2) {
  • if (!(pai + 1)) {
  • (pai + 1);
  • }
  • }
  • if (size >= 2 && allPai[yu][paiNum + 1] >= 2) {
  • if (!(pai - 1)) {
  • (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 (!(pai - 2)) {
  • (pai - 2);
  • }
  • }
  • if (size >= 2 && allPai[yu][paiNum - 2] >= 2) {
  • if (!(pai - 1)) {
  • (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 (!(pai + 2)) {
  • (pai + 2);
  • }
  • }
  • if (size >= 2 && allPai[yu][paiNum + 2] >= 2) {
  • if (!(pai + 1)) {
  • (pai + 1);
  • }
  • }
  • } else if (allPai[yu][paiNum - 1] >= 1) {
  • hasShun = true;
  • if (!(pai + 1)) {
  • (pai + 1);
  • }
  • if (!(pai - 2)) {
  • (pai - 2);
  • }
  • } else if (allPai[yu][paiNum + 1] >= 1) {
  • hasShun = true;
  • if (!(pai + 2)) {
  • (pai + 2);
  • }
  • if (!(pai - 1)) {
  • (pai - 1);
  • }
  • } else if (allPai[yu][paiNum - 2] >= 1) {
  • if (!(pai - 1)) {
  • (pai - 1);
  • }
  • if (size == 1) {
  • if (!(pai)) {
  • (pai);
  • }
  • }
  • } else if (allPai[yu][paiNum + 2] >= 1) {
  • if (!(pai + 1)) {
  • (pai + 1);
  • }
  • if (size == 1) {
  • if (!(pai)) {
  • (pai);
  • }
  • }
  • } else {
  • if (size == 1) {
  • if (!(pai)) {
  • (pai);
  • }
  • }
  • }
  • }
  • return hasShun;
  • }