import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.stream.IntStream; public class CanHu { /** * 牌数组,索引=牌id,值=牌数量 */ int[] paiArr; /** * 剩余牌的数量,只有全部拆完才算胡 */ int lastNum; /** * 是否自摸 */ boolean isZiMo; /** * 进牌id */ int fromPaiId; /** * 对子的类型 */ public static final int SHUNZI = 1, HUNDUN = 2, KAN = 3, TI = 4, DUIZI = 5, S2710 = 6; /** * 占的二进制位数 */ public static final int bitType = 3, bitPai = 5; /** * 占的二进制字节 */ public static final int byteType = 0x7, bytePai = 0x1F;//16进制分别代表7和31 /** * 保存所有可以胡的牌型 */ List duiList = new ArrayList(); /** * 所有可以胡牌型用到的癞子保存在这里 */ List laiZiList = new ArrayList(); /** * 牌对应的id,字牌:小一=1...小十=10,大壹=11...大拾=20,王(癞子)=21 */ public static final int MAX_PAI_CNT = 22; public static final int WANG = 21; public static final int DA_SHI = 20; public static final int XIAO_YI = 1; public CanHu(int[] paiArr, int fromPaiId, boolean isZiMo) { this.paiArr = paiArr; this.fromPaiId = fromPaiId; this.isZiMo = isZiMo; lastNum = IntStream.of(paiArr).sum(); } public void takeOffAll() { long dui = 0; // 手里有3张以上相同的不可以拆 for (int i = XIAO_YI; i <= DA_SHI; i++) { if (paiArr[i] >= 3 && i != fromPaiId) { dui = pushDui(dui, i, paiArr[i] == 3 ? KAN : TI); lastNum -= paiArr[i]; paiArr[i] = 0; } } takeOffAll(XIAO_YI, dui); } public void takeOffAll(int paiId, long dui) { System.out.println("takeOffAll参数 lastNum "+lastNum+" dui "+dui+" paiId "+paiId); // 剩余3张以内的 0是拆完了可以胡 1不能胡 2刚好是个将就可以胡 if (lastNum < 3) { if (lastNum == 0) { // 能胡 System.out.println("这种方式能胡 "+dui); duiList.add(dui); // 保存癞子代替的牌 int laizi = 0; for (int i = XIAO_YI; i <= DA_SHI; i++) { for (int j = paiArr[i]; j < 0; j++) { laizi = laizi << bitPai | i; } } laiZiList.add(laizi); } else if (lastNum == 2) { // 剩余2张能否做将 takeOffJiang(dui); } return; } for (int i = paiId; i <= DA_SHI; i++) { System.out.println("????===111 "+" i "+i+" dui "+dui); // 4张相同的 takeOffSame(i, 4, TI, dui); System.out.println("????===111 "+" i "+i+" dui "+dui); // 3张相同的 takeOffSame(i, 3, KAN, dui); System.out.println("????===111 "+" i "+i+" dui "+dui); // 2710 takeOff2710(i, dui); System.out.println("????===111 "+" i "+i+" dui "+dui); // 拆顺子 takeOff123(i, dui); System.out.println("????===111 "+" i "+i+" dui "+dui); // 拆混对 takeOffHunDui(i, dui); System.out.println("????===111 "+" i "+i+" dui "+dui); } } public void takeOffJiang(long dui) { System.out.println("拆分将,剩余2张能否做将 dui "+dui); int wangNum = paiArr[WANG]; int paiNum = 2 - wangNum; paiArr[WANG] = 0; for (int i = XIAO_YI; i <= DA_SHI; i++) { if (paiArr[i] == paiNum) { paiArr[i] -= 2; lastNum -= 2; takeOffAll(MAX_PAI_CNT, pushDui(dui, i, DUIZI)); paiArr[i] += 2; lastNum += 2; } } paiArr[WANG] += wangNum; } public void takeOffSame(int i, int cnt, int type, long dui) { System.out.println("拆分相同的, "+" i "+i+" cnt "+cnt+" type "+type+" dui "+dui); if (paiArr[i] + paiArr[WANG] >= cnt) { int needWang = cnt - paiArr[i]; if (needWang > 0) { paiArr[WANG] -= needWang; } paiArr[i] -= cnt; lastNum -= cnt; takeOffAll(i, pushDui(dui, i, type)); lastNum += cnt; paiArr[i] += cnt; if (needWang > 0) { paiArr[WANG] += needWang; } } } public void takeOff123(int i, long dui) { System.out.println("拆分普通顺子 "+" i "+i+" dui "+dui); // 处理边界的问题,9 10 11变成顺子的问题 int border = (i - 1) % 10; if (border > 7) { return; } int i1 = i + 1; int i2 = i + 2; takeOffSingle(i, i1, i2, SHUNZI, dui); } public void takeOff2710(int i, long dui) { // 只有是2的时候才组合2710 if (i % 10 != 2) { return; } int i1 = i + 5; int i2 = i + 8; System.out.println("takeOff2710 "+" i "+i+" i1 "+i1+" i2 "+i2+" S2710 "+S2710+" dui "+dui); takeOffSingle(i, i1, i2, S2710, dui); } public void takeOffSingle(int i, int i1, int i2, int type, long dui) { int needWang = 0; if (paiArr[i] < 1) needWang++; if (paiArr[i1] < 1) needWang++; if (paiArr[i2] < 1) needWang++; System.out.println("takeOffSingle111 "+" needWang "+needWang+" this.paiArr[this.WANG] "+paiArr[WANG]+" WANG "+this.WANG+" dui "+dui+" i "+i+" i1 "+i1+" i2 "+i2); if (paiArr[WANG] >= needWang) { paiArr[WANG] -= needWang; paiArr[i]--; paiArr[i1]--; paiArr[i2]--; lastNum -= 3; System.out.println("takeOffSingle222 "+" needWang "+needWang+" this.paiArr[this.WANG] "+paiArr[WANG]+" this.WANG "+WANG+" dui "+dui+" i "+i+" type "+type); takeOffAll(i, pushDui(dui, i, type)); lastNum += 3; paiArr[i]++; paiArr[i1]++; paiArr[i2]++; paiArr[WANG] += needWang; } } public void takeOffHunDui(int i, int relatePai, long dui) { System.out.println("拆分混对(绞牌)222 "+" i "+i+" relatePai "+relatePai+" dui "+dui); paiArr[i] -= 2; paiArr[relatePai]--; lastNum -= 3; takeOffAll(i, pushDui(dui, i, HUNDUN)); lastNum += 3; paiArr[i] += 2; paiArr[relatePai]++; } public void takeOffHunDui(int i, long dui) { System.out.println("拆分混对(绞牌) "+" i "+i+" dui "+dui); int relatePai = i > 10 ? i - 10 : i + 10; if (paiArr[i] >= 1 && paiArr[relatePai] >= 1) { if (paiArr[i] >= 2) { takeOffHunDui(i, relatePai, dui); } else if (paiArr[WANG] >= 1) { paiArr[WANG]--; takeOffHunDui(i, relatePai, dui); paiArr[WANG]++; } } } public static long pushDui(long dui, int paiId, int type) { // return (dui << bitType | type) << bitPai | paiId; System.out.println("pushDui "+" dui "+dui+" paiId " + paiId+" type " + type+" bitType "+bitType+" bitPai "+bitPai); String typeStr = ""+type+"("; if(type == 1) typeStr += "顺子"; else if(type == 2) typeStr += "混对"; else if(type == 3) typeStr += "坎"; else if(type == 4) typeStr += "提"; else if(type == 5) typeStr += "对子"; else if(type == 6) typeStr += "27十"; typeStr += ")"; long res = (dui << bitType | type) << bitPai | paiId; System.out.println("pushDui res "+res+" dui "+dui+" paiId "+paiId+" type "+typeStr+" bitType "+bitType+" bitPai "+bitPai); return res; } public static List popDui(long dui) { int paiId = (int) (dui & bytePai); int type = (int) (dui >>> bitPai & byteType); System.out.println("popDui000 dui "+dui+" bitPai "+bitPai+" bytePai "+bytePai+" byteType "+byteType); System.out.println("popDui111 type "+type+" paiId "+paiId); switch (type) { case TI: return Arrays.asList(paiId, paiId, paiId, paiId); case KAN: return Arrays.asList(paiId, paiId, paiId); case SHUNZI: return Arrays.asList(paiId, paiId + 1, paiId + 2); case S2710: return Arrays.asList(paiId, paiId + 5, paiId + 8); case HUNDUN: int relatePai = paiId > 10 ? paiId - 10 : paiId + 10; return Arrays.asList(paiId, paiId, relatePai); case DUIZI: return Arrays.asList(paiId, paiId); } return Arrays.asList(); } public static void main(String[] args) { // int arr[]={0, 0, 2, 0, 4, 0, 0, 3, 0, 0, 0, 4, 2, 0, 0, 0, 0, 1, 0, 1, 1, 3}; // int map[]= {0, 0, 0, 0, 0, 0, 1, 1, 3, 1, 0, 0, 0, 0, 1, 0, 3, 0, 1, 0, 2, 2}; // int[] map1={1,1,1,21,21}; // int[] map1={14,11,1,10,11,14,21,10,3,16,21,21,16,2,14,11,7,16}; // int[] map1={1,2,3,3,3,13,3,4,5}; // int[] map1={1,2,3,3,3,13}; // int[] map1={15,15,21,21,21}; // int[] map1={6,6,6,8,9,10}; // int[] map1={9,9,9,9,6,6,11,12,13,18,19,20,21,21,21,21}; // int[] map1 = { 1, 2, 3, 4, 11, 12, 13, 14, 14 ,21,21,21}; // int[] map1 = { 1, 2, 3, 4, 1, 4, 11, 12, 13, 14, 11, 14 }; // int[] map1 = { 7, 5, 17, 14, 20, 1, 21, 3, 20, 21, 3, 15, 19, 1, 18, 5, 12, 6, 21, 21, 16 }; // int[] map1 = { 1, 1, 2, 2, 3, 3, 11, 11, 12, 12, 13, 13, 21, 21, 21, 21 }; // int[] map1 = { 1, 1, 2, 2, 3, 3, 11, 11, 12, 12, 13, 13, 20, 20, 20, 20 }; //int[] map1 = { 1, 1, 2, 2, 3, 3, 11, 11, 12, 12, 13, 13, 20, 20, 20, 17,18,19 }; //int[] map1 = {19,19,19,9,9,9,12,17,20,1,2,3,4,5,6,7,14,14,15,15,8 }; // int[] map1 = {9,9,9,12,17,20,1,2,3,4,5,6,7,14,14,8,8 }; System.out.println("???????? "+((1769152804 << 3 | 6) << 5 | 12)); int[] map1 = {1,2,3,4,5,6,7,8,9,9,9,12,14,14,15,15,17,19,19,19,20}; System.out.println("map1-> " + map1.length +" : "+ Arrays.toString(map1)); int[] map = new int[MAX_PAI_CNT];//[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] System.out.println("map初始值 " + map.length +" : " + Arrays.toString(map)); for (int i = 0; i < map1.length; i++) { // System.out.println("map->" + map[i]); map[map1[i]]++;//为了统计每个牌值的张数 // System.out.println("map->============= " + map[i]); } System.out.println("map-> " + map.length +" : " + Arrays.toString(map)); // int[] map = { 0, 0, 0, 1, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2 }; CanHu hu = new CanHu(map, 0, true); long t = System.currentTimeMillis();//1723081942670 System.out.println("t-> " + t); hu.takeOffAll(); System.out.println("|耗时->" + (System.currentTimeMillis() - t) + "|hu.duiList.size()结果->" + hu.duiList.size()); System.out.println("下面是hu.duiList "+byteType +" "+bytePai); System.out.println(hu.duiList); System.out.println("下面是???111"); hu.duiList.stream().map(dui -> { System.out.println("这是 dui "+dui); ArrayList> duilist = new ArrayList>(); while (dui > 0) { System.out.println("这是000 dui "+dui+" bitPai "+bitPai+" bitType "+bitType); duilist.add(popDui(dui)); System.out.println("这是111 dui "+dui+" bitPai "+bitPai+" bitType "+bitType); dui >>>= (bitPai + bitType); System.out.println("这是222 dui "+dui+" bitPai "+bitPai+" bitType "+bitType); } return duilist; }).forEach(System.out::println); System.out.println("下面是???222"); hu.laiZiList.forEach(laizi -> { while (laizi > 0) { System.out.print((laizi & bytePai) + "|====="); laizi >>>= bitPai; } System.out.println("下面是???333"); System.out.println("-----"); }); System.out.println("下面是???444 "+hu.pushDui(1769152804,12,6)+" "+hu.pushDui(1931551948,12,6)); System.out.println("???????? "+((1769152804 << 3 | 6) << 5 | 12)); System.out.println("下面是???666 "+hu.pushDui(1769152804,12,6)+" "+hu.pushDui(1931551948,12,6)); } }