package GameControl;

import Constants.Constants;

import java.util.*;
import java.util.stream.IntStream;

public class ActionJudgment {
    //*****************单张********************//
    public static Map<Integer, CardInfo> getSingle(int numBase, int min, int levelCard, Player player) {
        Map<Integer, CardInfo> resultMap = new HashMap<Integer, CardInfo>();
        if (levelCard == min) {
            numBase = addSameValueCard(resultMap, numBase, 13, player.getPlayerNum(), Constants.single, getSingleArray(player.getCards()[13]));
            numBase = addSameValueCard(resultMap, numBase, 14, player.getPlayerNum(), Constants.single, getSingleArray(player.getCards()[14]));
        } else {
            for (int i = min + 1; i < player.getCards().length; ++i) {
                numBase = addSameValueCard(resultMap, numBase, i, player.getPlayerNum(), Constants.single, getSingleArray(player.getCards()[i]));
            }
            if (levelCard < min && min < 13) {
                numBase = addSameValueCard(resultMap, numBase, levelCard, player.getPlayerNum(), Constants.single, getSingleArray(player.getCards()[levelCard]));
            }
        }
        return resultMap;
    }

    private static int[] getSingleArray(int card) {
        int[] singleCards = new int[4];
        if (card != 0) {
            if ((card & 0x8) != 0) {
                singleCards[0] = 0x8;
            }
            if ((card & 0x4) != 0) {
                singleCards[1] = 0x4;
            }
            if ((card & 0x2) != 0) {
                singleCards[2] = 0x2;
            }
            if ((card & 0x1) != 0) {
                singleCards[3] = 0x1;
            }
        }
        return filterNonZero(singleCards);
    }

    //*****************************************//


    //*******************对子*******************//
    public static Map<Integer, CardInfo> getPair(int numBase, int min, int levelCard, Player player) {
        Map<Integer, CardInfo> resultMap = new HashMap<Integer, CardInfo>();
        if (levelCard == min) {
            numBase = addSameValueCard(resultMap, numBase, 13, player.getPlayerNum(), Constants.pair, getSameSuitPairArray(player.getCards()[13]));
            numBase = addSameValueCard(resultMap, numBase, 14, player.getPlayerNum(), Constants.pair, getSameSuitPairArray(player.getCards()[14]));
        } else {
            for (int i = min + 1; i < player.getCards().length; ++i) {
                numBase = addSameValueCard(resultMap, numBase, i, player.getPlayerNum(), Constants.pair, getSameSuitPairArray(player.getCards()[i]));
                numBase = addSameValueCard(resultMap, numBase, i, player.getPlayerNum(), Constants.pair, getDifferentSuitPairArray(player.getCards()[i]));
            }
            if (levelCard < min && min < 13) {
                numBase = addSameValueCard(resultMap, numBase, levelCard, player.getPlayerNum(), Constants.pair, getSameSuitPairArray(player.getCards()[levelCard]));
                numBase = addSameValueCard(resultMap, numBase, levelCard, player.getPlayerNum(), Constants.pair, getDifferentSuitPairArray(player.getCards()[levelCard]));
            }
        }
        return resultMap;
    }

    public static int[] getSameSuitPairArray(int card) {
        int[] pairs = new int[4];
        card = ((card >> 4) & card);
        if (card != 0) {
            if ((card & 0x8) != 0) {
                pairs[0] = 0x88;
            }
            if ((card & 0x4) != 0) {
                pairs[1] = 0x44;
            }
            if ((card & 0x2) != 0) {
                pairs[2] = 0x22;
            }
            if ((card & 0x1) != 0) {
                pairs[3] = 0x11;
            }
        }
        return filterNonZero(pairs);
    }

    public static int[] getDifferentSuitPairArray(int card) {
        int[] singleCards = getSingleArray(card);
        if (singleCards.length <= 1) {
            return new int[0];
        }
        int length = 0;
        switch (singleCards.length) {
            case 2:
                length = 1;
                break;
            case 3:
                length = 3;
                break;
            case 4:
                length = 6;
                break;
        }
        ;
        int[] result = new int[length];
        int pos = 0;
        for (int i = 0; i < singleCards.length - 1; ++i) {
            for (int j = i + 1; j < singleCards.length; ++j) {
                result[pos++] = (singleCards[i] | singleCards[j]);
            }
        }
        return result;
    }

    //**************************************//


    //******************三张******************//

    public static Map<Integer, CardInfo> getThree(int numBase, int min, int levelCard, Player player) {
        Map<Integer, CardInfo> resultMap = new HashMap<Integer, CardInfo>();
        if (levelCard == min) {
            return resultMap;
        } else {
            for (int i = min + 1; i < player.getCards().length; ++i) {
                numBase = addSameValueCard(resultMap, numBase, i, player.getPlayerNum(), Constants.three, getThreeArray(player.getCards()[i]));
            }
            if (levelCard < min && min < 13) {
                numBase = addSameValueCard(resultMap, numBase, levelCard, player.getPlayerNum(), Constants.three, getThreeArray(player.getCards()[levelCard]));
            }
        }
        return resultMap;
    }

    public static int[] getThreeArray(int card) {
        int[] singles = getSingleArray(card);
        //单张小于等于1不可能有三张
        if (singles.length <= 1) {
            return new int[0];
        }
        int[] sameSuitPairs = getSameSuitPairArray(card);
        int temp = 0;
        switch (singles.length) {
            case 3:
                temp = 1;
                break;
            case 4:
                temp = 4;
                break;
        }
        ;
        int length = sameSuitPairs.length * (singles.length - 1) + temp;
        int[] result = new int[length];
        int pos = 0;
        for (int pair : sameSuitPairs) {
            for (int single : singles) {
                if ((pair & single) == 0) {
                    result[pos++] = (pair | single);
                }
            }
        }
        //不同花色组合
        if (singles.length == 3) {
            result[pos] = (singles[0] | singles[1] | singles[2]);
        } else if (singles.length == 4) {
            result[pos++] = 0xe;
            result[pos++] = 0xd;
            result[pos++] = 0xb;
            result[pos] = 0x7;
        }
        return result;
    }

    //***********************************//

    //************************三带二******************//
    public static Map<Integer, CardInfo> getThreeWithTwo(int numBase, int min, int levelCard, Player player) {
        Map<Integer, CardInfo> resultMap = new HashMap<Integer, CardInfo>();
        if (levelCard == min) {
            return resultMap;
        } else {
            //得到所有对子
            List<int[]> allPairs = getAllPairs(player);
            allPairs.add(getSameSuitPairArray(player.getCards()[13]));
            allPairs.add(getSameSuitPairArray(player.getCards()[14]));
            //过滤掉逢人配对子
//            for(int i=0;i<allPairs.get(levelCard).length;++i){
//                if(allPairs.get(levelCard)[i]==0x11){
//                    allPairs.get(levelCard)[i]=0;
//                    allPairs.set(levelCard,filterNonZero(allPairs.get(levelCard)));
//                    break;
//                }
//            }
            int[] threes;
            for (int i = min + 1; i < 13; ++i) {
                threes = getThreeArray(player.getCards()[i]);
                numBase = addThreeWithTwo(resultMap, numBase, i, threes, allPairs, player.getPlayerNum());
            }
            if (levelCard < min) {
                threes = getThreeArray(player.getCards()[levelCard]);
                numBase = addThreeWithTwo(resultMap, numBase, levelCard, threes, allPairs, player.getPlayerNum());
            }
        }
        return resultMap;
    }

    private static int addThreeWithTwo(Map<Integer, CardInfo> resultMap, int numBase, int threeLoc, int[] threes, List<int[]> allPairs, int playerNum) {
        int[] pairs;
        for (int three : threes) {
            //分两段遍历所有对子
            for (int k = 0; k < threeLoc; ++k) {
                pairs = allPairs.get(k);
                for (int p : pairs) {
                    int[] playedCard = new int[threeLoc - k + 1];
                    playedCard[0] = p;
                    playedCard[threeLoc - k] = three;
                    resultMap.put(numBase++, CardInfo.buildCardInfo(Constants.threeWithTwo, playedCard, k, playerNum, new int[]{threeLoc, k}));
                }
            }
            for (int k = threeLoc + 1; k < 15; ++k) {
                pairs = allPairs.get(k);
                for (int p : pairs) {
                    int[] playedCard = new int[k - threeLoc + 1];
                    playedCard[0] = three;
                    playedCard[k - threeLoc] = p;
                    resultMap.put(numBase++, CardInfo.buildCardInfo(Constants.threeWithTwo, playedCard, threeLoc, playerNum, new int[]{threeLoc, k}));
                }
            }
        }
        return numBase;
    }
    //**********************************************//

    //***********************钢板******************//
    //这个min指的是钢板中较大的那一张
    public static Map<Integer, CardInfo> getTwoThree(int numBase, int min, Player player) {
        Map<Integer, CardInfo> resultMap = new HashMap<Integer, CardInfo>();
        int[] minThree;
        int[] maxThree;
        //A和2组合
        if (min == -1) {
            minThree = getThreeArray(player.getCards()[12]);
            maxThree = getThreeArray(player.getCards()[0]);
            if (minThree.length > 0 && maxThree.length > 0) {
                for (int minT : minThree) {
                    for (int maxT : maxThree) {
                        int[] card = new int[13];
                        card[0] = maxT;
                        card[12] = minT;
                        resultMap.put(numBase++, CardInfo.buildCardInfo(Constants.twoThree, card, 0, player.getPlayerNum(), new int[]{12}));
                    }
                }
            }
            ++min;
        }

        for (int i = min; i < 12; ++i) {
            minThree = getThreeArray(player.getCards()[i]);
            if (minThree.length > 0) {
                maxThree = getThreeArray(player.getCards()[i + 1]);
                if (maxThree.length > 0) {
                    for (int minT : minThree) {
                        for (int maxT : maxThree) {
                            int[] card = new int[2];
                            card[0] = minT;
                            card[1] = maxT;
                            resultMap.put(numBase++, CardInfo.buildCardInfo(Constants.twoThree, card, i, player.getPlayerNum(), new int[]{i}));
                        }
                    }
                } else {
                    ++i;
                }
            }
        }
        return resultMap;
    }

    //*******************************************//

    //**********************三连对**********************//
    //min表示连对中间的大小
    public static Map<Integer, CardInfo> getThreePair(int numBase, int min, Player player) {
        Map<Integer, CardInfo> resultMap = new HashMap<Integer, CardInfo>();
        List<int[]> allPairs = getAllPairs(player);
        if (min == -1) {
            //判断A23连对
            if (allPairs.get(12).length > 0 && allPairs.get(0).length > 0 && allPairs.get(1).length > 0) {
                for (int a : allPairs.get(12)) {
                    for (int two : allPairs.get(0)) {
                        for (int three : allPairs.get(1)) {
                            int[] playedCard = new int[13];
                            playedCard[12] = a;
                            playedCard[0] = two;
                            playedCard[1] = three;
                            resultMap.put(numBase++, CardInfo.buildCardInfo(Constants.threePairs, playedCard, 0, player.getPlayerNum(), new int[]{12}));
                        }
                    }
                }
            }
            ++min;
        }

        for (int i = min; i < 11; ++i) {
            if (allPairs.get(i).length > 0 && allPairs.get(i + 1).length > 0 && allPairs.get(i + 2).length > 0) {
                for (int s : allPairs.get(i)) {
                    for (int m : allPairs.get(i + 1)) {
                        for (int l : allPairs.get(i + 2)) {
                            int[] playedCard = new int[3];
                            playedCard[0] = s;
                            playedCard[1] = m;
                            playedCard[2] = l;
                            resultMap.put(numBase++, CardInfo.buildCardInfo(Constants.threePairs, playedCard, i, player.getPlayerNum(), new int[]{i}));
                        }
                    }
                }
            }
        }

        return resultMap;
    }

    //***********************************************//


    //***************************顺子****************//
    public static Map<Integer, CardInfo> getStraight(int numBase, int min, Player player) {
        Map<Integer, CardInfo> resultMap = new HashMap<Integer, CardInfo>();
        List<int[]> allSingles = new ArrayList<>();
        for (int i = 0; i < 13; ++i) {
            allSingles.add(getSingleArray(player.getCards()[i]));
        }

        if (min == -1) {
            if (allSingles.get(12).length > 0 && allSingles.get(0).length > 0
                    && allSingles.get(1).length > 0 && allSingles.get(2).length > 0
                    && allSingles.get(3).length > 0) {
                for (int a : allSingles.get(12)) {
                    for (int two : allSingles.get(0)) {
                        for (int three : allSingles.get(1)) {
                            for (int four : allSingles.get(2)) {
                                for (int five : allSingles.get(3)) {
                                    if ((a & two & three & four & five) != 0) {
                                        continue;
                                    }
                                    int[] playedCard = new int[13];
                                    playedCard[12] = a;
                                    playedCard[0] = two;
                                    playedCard[1] = three;
                                    playedCard[2] = four;
                                    playedCard[3] = five;
                                    resultMap.put(numBase++, CardInfo.buildCardInfo(Constants.straight, playedCard, 0, player.getPlayerNum(), new int[]{12}));
                                }
                            }
                        }
                    }
                }
            }
            ++min;
        }

        for (int i = min; i < 9; ++i) {
            if (allSingles.get(i).length > 0 && allSingles.get(i + 1).length > 0
                    && allSingles.get(i + 2).length > 0 && allSingles.get(i + 3).length > 0
                    && allSingles.get(i + 4).length > 0) {
                for (int one : allSingles.get(i)) {
                    for (int two : allSingles.get(i + 1)) {
                        for (int three : allSingles.get(i + 2)) {
                            for (int four : allSingles.get(i + 3)) {
                                for (int five : allSingles.get(i + 4)) {
                                    if ((one & two & three & four & five) != 0) {
                                        continue;
                                    }
                                    int[] playedCard = new int[5];
                                    playedCard[0] = one;
                                    playedCard[1] = two;
                                    playedCard[2] = three;
                                    playedCard[3] = four;
                                    playedCard[4] = five;
                                    resultMap.put(numBase++, CardInfo.buildCardInfo(Constants.straight, playedCard, i, player.getPlayerNum(), new int[]{i}));
                                }
                            }
                        }
                    }
                }
            }
        }
        return resultMap;
    }

    //************************************************//


    //***************************同花顺*********************//
    //min是第二小的那张
    public static Map<Integer, CardInfo> getStraightFlush(int numBase, int min, Player player) {
        Map<Integer, CardInfo> resultMap = new HashMap<Integer, CardInfo>();
        int[] cards = player.getCards();
        if (min == -1) {
            int flag = (cards[12] & cards[0] & cards[1] & cards[2] & cards[3]);
            if (flag != 0) {
                int[] straightFlushs = getSingleArray(flag);
                for (int straightFlush : straightFlushs) {
                    int[] playedCard = new int[13];
                    playedCard[12] = straightFlush;
                    playedCard[0] = straightFlush;
                    playedCard[1] = straightFlush;
                    playedCard[2] = straightFlush;
                    playedCard[3] = straightFlush;
                    resultMap.put(numBase++, CardInfo.buildCardInfo(Constants.straightFlush, playedCard, 0, player.getPlayerNum(), new int[]{12}));
                }
            }
            ++min;
        }

        for (int i = min; i < 9; ++i) {
            int flag = (cards[i] & cards[i + 1] & cards[i + 2] & cards[i + 3] & cards[i + 4]);
            if (flag != 0) {
                int[] straightFlushs = getSingleArray(flag);
                for (int straightFlush : straightFlushs) {
                    int[] playedCard = new int[5];
                    playedCard[0] = straightFlush;
                    playedCard[1] = straightFlush;
                    playedCard[2] = straightFlush;
                    playedCard[3] = straightFlush;
                    playedCard[4] = straightFlush;
                    resultMap.put(numBase++, CardInfo.buildCardInfo(Constants.straightFlush, playedCard, i, player.getPlayerNum(), new int[]{i}));
                }
            }
        }
        return resultMap;
    }
    //************************************************//

    //**************************炸弹************************//
    public static Map<Integer, CardInfo> getBomb(int numBase, int bombNum, int min, int levelCard, Player player) {
        Map<Integer, CardInfo> resultMap = new HashMap<Integer, CardInfo>();
        //从2开始找大于bombNum的炸弹
        for (int i = 0; i < 13; ++i) {
            int numOfCard = numOfSameSuitCards(player.getCards()[i]);
            switch (bombNum) {
                case -1:
                    numBase = addSameValueCard(resultMap, numBase, i, player.getPlayerNum(), Constants.bomb, getFourBombArray(player.getCards()[i], numOfCard));
                case 4:
                    numBase = addSameValueCard(resultMap, numBase, i, player.getPlayerNum(), Constants.bomb, getFiveBombArray(player.getCards()[i], numOfCard));
                case 5:
                    numBase = addSameValueCard(resultMap, numBase, i, player.getPlayerNum(), Constants.bomb, getSixBombArray(player.getCards()[i], numOfCard));
                case 6:
                    numBase = addSameValueCard(resultMap, numBase, i, player.getPlayerNum(), Constants.bomb, getSevenBombArray(player.getCards()[i], numOfCard));
                case 7:
                    if (numOfCard == 8) {
                        resultMap.put(numBase++, CardInfo.buildCardInfo(Constants.bomb, new int[]{0xff}, i, player.getPlayerNum(), new int[]{i}));
                    }
            }
        }
        //-1则所有的炸弹都找了，不必再继续
        if (bombNum != -1) {
            if (min == levelCard) {
                return resultMap;
            } else {
                int numOfCard;
                for (int i = min + 1; i < 13; ++i) {
                    numOfCard = numOfSameSuitCards(player.getCards()[i]);
                    numBase = addBomb(resultMap, numBase, i, player.getPlayerNum(), player.getCards()[i], numOfCard, bombNum);
                }
                if (levelCard < min) {
                    numOfCard = numOfSameSuitCards(player.getCards()[levelCard]);
                    numBase = addBomb(resultMap, numBase, levelCard, player.getPlayerNum(), player.getCards()[levelCard], numOfCard, bombNum);
                }
            }
        }
        return resultMap;
    }

    private static int addBomb(Map<Integer, CardInfo> resultMap, int numBase, int cardLoc, int playerNum, int card, int numOfCard, int bombNum) {
        switch (bombNum) {
            case 4:
                numBase = addSameValueCard(resultMap, numBase, cardLoc, playerNum, Constants.bomb, getFourBombArray(card, numOfCard));
                break;
            case 5:
                numBase = addSameValueCard(resultMap, numBase, cardLoc, playerNum, Constants.bomb, getFiveBombArray(card, numOfCard));
                break;
            case 6:
                numBase = addSameValueCard(resultMap, numBase, cardLoc, playerNum, Constants.bomb, getSixBombArray(card, numOfCard));
                break;
            case 7:
                numBase = addSameValueCard(resultMap, numBase, cardLoc, playerNum, Constants.bomb, getSevenBombArray(card, numOfCard));
                break;
            case 8:
                if (numOfCard == 8) {
                    resultMap.put(numBase++, CardInfo.buildCardInfo(Constants.bomb, new int[]{0xff}, cardLoc, playerNum, new int[]{cardLoc}));
                }
                break;
        }
        return numBase;
    }

    public static int[] getFourBombArray(int card, int numOfCard) {
        int[] result = new int[20];
        int pos = 0;
        if (numOfCard >= 4) {
            if ((card & 0xf) == 0xf) {
                result[pos++] = 0xf;
            }
            int[] sameSuitPair = getSameSuitPairArray(card);
            int[] differentPair = getDifferentSuitPairArray(card);
            if (sameSuitPair.length > 1) {
                for (int i = 0; i < sameSuitPair.length - 1; ++i) {
                    for (int j = i + 1; j < sameSuitPair.length; ++j) {
                        result[pos++] = (sameSuitPair[i] | sameSuitPair[j]);
                    }
                }
            }
            if (sameSuitPair.length >= 1 && differentPair.length >= 3) {
                for (int sPair : sameSuitPair) {
                    for (int dPair : differentPair) {
                        if ((sPair & dPair) == 0) {
                            result[pos++] = (sPair | dPair);
                        }
                    }
                }
            }
            return filterNonZero(result);
        } else {
            return new int[0];
        }
    }

    public static int[] getFiveBombArray(int card, int numOfCard) {
        if (numOfCard >= 5) {
            int[] result = new int[20];
            int pos = 0;
            //四不同+1张 即 一对+三张
            if ((card & 0xf) == 0xf) {
                int[] upSingles = getSingleArray((card >> 4));
                for (int single : upSingles) {
                    result[pos++] = (0xf | (single << 4));
                }
            }
            //俩对相同+1张 (优化，不遍历所有单张)
            int[] sameSuitPair = getSameSuitPairArray(card);
            if (sameSuitPair.length > 1) {
                int[] singles = getSingleArray(card);
                for (int i = 0; i < sameSuitPair.length - 1; ++i) {
                    for (int j = i + 1; j < sameSuitPair.length; ++j) {
                        for (int single : singles) {
                            if (((sameSuitPair[i] | sameSuitPair[j]) & single) == 0) {
                                result[pos++] = (sameSuitPair[i] | sameSuitPair[j] | single);
                            }
                        }

                    }
                }
            }
            return filterNonZero(result);
        } else {
            return new int[0];
        }
    }

    public static int[] getSixBombArray(int card, int numOfCard) {
        if (numOfCard == 6) {
            int[] result = new int[1];
            result[0] = card;
            return result;
        } else if (numOfCard == 7) {
            int[] result = new int[4];
            result[0] = (0xe | (0xf0 & card));
            result[1] = (0xd | (0xf0 & card));
            result[2] = (0xb | (0xf0 & card));
            result[3] = (0x7 | (0xf0 & card));
            return result;
        } else if (numOfCard == 8) {
            int[] result = new int[10];
            result[0] = 0xfc;
            result[1] = 0xfa;
            result[2] = 0xf6;
            result[3] = 0xf9;
            result[4] = 0xf5;
            result[5] = 0xf3;
            result[6] = 0xee;
            result[7] = 0xdd;
            result[8] = 0xbb;
            result[9] = 0x77;
            return result;
        } else {
            return new int[0];
        }
    }

    public static int[] getSevenBombArray(int card, int numOfCard) {
        if (numOfCard == 7) {
            int[] result = new int[1];
            result[0] = card;
            return result;
        } else if (numOfCard == 8) {
            int[] result = new int[4];
            result[0] = 0xef;
            result[1] = 0xdf;
            result[2] = 0xbf;
            result[3] = 0x7f;
            return result;
        } else {
            return new int[0];
        }
    }

    //**************************************************//

    //*********************四王炸************************//
    public static Map<Integer, CardInfo> getFourKings(int numBase, Player player) {
        Map<Integer, CardInfo> resultMap = new HashMap<Integer, CardInfo>();
        int[] playedCard = new int[2];
        if (player.getCards()[13] == 0x11 && player.getCards()[14] == 0x11) {
            playedCard[0] = 0x11;
            playedCard[1] = 0x11;
            resultMap.put(numBase, CardInfo.buildCardInfo(Constants.fourKings, playedCard, 13, player.getPlayerNum(), new int[]{13}));
        }
        return resultMap;
    }
    //************************************************//

    //*********************逢人配组合*********************//
    public static Map<Integer, CardInfo> getPairWithWild(int numBase, int min, int wildNum, int levelCard, Player player) {
        Map<Integer, CardInfo> resultMap = new HashMap<Integer, CardInfo>();
        if (levelCard == min || wildNum < 1) {
            return resultMap;
        } else {
            for (int i = min + 1; i < levelCard; ++i) {
                int[] singleArray = getSingleArray(player.getCards()[i]);
                for (int single : singleArray) {
                    int[] playedCard = new int[levelCard - i + 1];
                    playedCard[0] = single;
                    playedCard[levelCard - i] = 0x1;
                    resultMap.put(numBase++, CardInfo.buildCardInfo(Constants.pair, playedCard, i, player.getPlayerNum(), new int[]{i}));
                }
            }
            for (int i = (Math.max(levelCard, min)) + 1; i < 13; ++i) {
                int[] singleArray = getSingleArray(player.getCards()[i]);
                for (int single : singleArray) {
                    int[] playedCard = new int[i - levelCard + 1];
                    playedCard[0] = 0x1;
                    playedCard[i - levelCard] = single;
                    resultMap.put(numBase++, CardInfo.buildCardInfo(Constants.pair, playedCard, levelCard, player.getPlayerNum(), new int[]{i}));
                }
            }
        }
        return resultMap;
    }

    public static Map<Integer, CardInfo> getThreeWithWild(int numBase, int min, int wildNum, int levelCard, Player player) {
        Map<Integer, CardInfo> resultMap = new HashMap<Integer, CardInfo>();
        if (levelCard == min || wildNum < 1) {
            return resultMap;
        }
        switch (wildNum) {
            case 2:
                for (int i = min + 1; i < levelCard; ++i) {
                    int[] singleArray = getSingleArray(player.getCards()[i]);
                    for (int single : singleArray) {
                        int[] playedCard = new int[levelCard - i + 1];
                        playedCard[0] = single;
                        playedCard[levelCard - i] = 0x11;
                        resultMap.put(numBase++, CardInfo.buildCardInfo(Constants.three, playedCard, i, player.getPlayerNum(), new int[]{i}));
                    }
                }
                for (int i = (Math.max(levelCard, min)) + 1; i < 13; ++i) {
                    int[] singleArray = getSingleArray(player.getCards()[i]);
                    for (int single : singleArray) {
                        int[] playedCard = new int[i - levelCard + 1];
                        playedCard[0] = 0x11;
                        playedCard[i - levelCard] = single;
                        resultMap.put(numBase++, CardInfo.buildCardInfo(Constants.three, playedCard, levelCard, player.getPlayerNum(), new int[]{i}));
                    }
                }
            case 1:
                for (int i = min + 1; i < levelCard; ++i) {
                    int[] pairArray = spliceArray(getSameSuitPairArray(player.getCards()[i]), getDifferentSuitPairArray(player.getCards()[i]));
                    for (int pair : pairArray) {
                        int[] playedCard = new int[levelCard - i + 1];
                        playedCard[0] = pair;
                        playedCard[levelCard - i] = 0x1;
                        resultMap.put(numBase++, CardInfo.buildCardInfo(Constants.three, playedCard, i, player.getPlayerNum(), new int[]{i}));
                    }

                }
                for (int i = (Math.max(levelCard, min)) + 1; i < 13; ++i) {
                    int[] pairArray = spliceArray(getSameSuitPairArray(player.getCards()[i]), getDifferentSuitPairArray(player.getCards()[i]));
                    for (int pair : pairArray) {
                        int[] playedCard = new int[i - levelCard + 1];
                        playedCard[0] = 0x1;
                        playedCard[i - levelCard] = pair;
                        resultMap.put(numBase++, CardInfo.buildCardInfo(Constants.three, playedCard, levelCard, player.getPlayerNum(), new int[]{i}));
                    }
                }
        }
        return resultMap;
    }

    //????优化
    public static Map<Integer, CardInfo> getBombWithWild(int numBase, int bombNum, int min, int wildNum, int levelCard, Player player) {
        Map<Integer, CardInfo> resultMap = new HashMap<Integer, CardInfo>();
        if (wildNum < 1) {
            return resultMap;
        }
        //加入比bombNum高的炸弹
        for (int i = 0; i < levelCard; ++i) {
            numBase = addBombThanBombNum(resultMap, numBase, i, player.getPlayerNum(), i, 0, levelCard - i, levelCard - i + 1, bombNum, player.getCards()[i], wildNum);
        }
        for (int i = levelCard + 1; i < 13; ++i) {
            numBase = addBombThanBombNum(resultMap, numBase, levelCard, player.getPlayerNum(), i, i - levelCard, 0, i - levelCard + 1, bombNum, player.getCards()[i], wildNum);
        }
        if (bombNum == -1) {
            return resultMap;
        }
        //加入和bombNum相同但比min大的炸弹
        if (min == levelCard) {
            return resultMap;
        } else {
            for (int i = min + 1; i < 13; ++i) {
                if (i < levelCard) {
                    numBase = addBombAsBombNum(resultMap, numBase, i, player.getPlayerNum(), i, 0, levelCard - i, levelCard - i + 1, bombNum, player.getCards()[i], wildNum);
                } else if (i > levelCard) {
                    numBase = addBombAsBombNum(resultMap, numBase, levelCard, player.getPlayerNum(), i, i - levelCard, 0, i - levelCard + 1, bombNum, player.getCards()[i], wildNum);
                }
            }
        }
        return resultMap;
    }

    private static int addBombThanBombNum(Map<Integer, CardInfo> resultMap, int numBase, int cardLoc, int playerNum, int cardPoint, int bombPos, int wildPos, int length, int bombNum, int card, int wildNum) {
        int numOfCard = numOfSameSuitCards(card);
        switch (bombNum) {
            case -1:
                switch (wildNum) {
                    case 2:
                        for (int two : spliceArray(getSameSuitPairArray(card), getDifferentSuitPairArray(card))) {
                            numBase = addWildBomb(resultMap, numBase, bombPos, wildPos, length, 0x11, two, cardLoc, playerNum, cardPoint);
                        }
                    case 1:
                        for (int three : getThreeArray(card)) {
                            numBase = addWildBomb(resultMap, numBase, bombPos, wildPos, length, 0x1, three, cardLoc, playerNum, cardPoint);
                        }
                }
            case 4:
                switch (wildNum) {
                    case 2:
                        for (int three : getThreeArray(card)) {
                            numBase = addWildBomb(resultMap, numBase, bombPos, wildPos, length, 0x11, three, cardLoc, playerNum, cardPoint);
                        }
                    case 1:
                        for (int four : getFourBombArray(card, numOfCard)) {
                            numBase = addWildBomb(resultMap, numBase, bombPos, wildPos, length, 0x1, four, cardLoc, playerNum, cardPoint);
                        }
                }
            case 5:
                switch (wildNum) {
                    case 2:
                        for (int four : getFourBombArray(card, numOfCard)) {
                            numBase = addWildBomb(resultMap, numBase, bombPos, wildPos, length, 0x11, four, cardLoc, playerNum, cardPoint);
                        }
                    case 1:
                        for (int five : getFiveBombArray(card, numOfCard)) {
                            numBase = addWildBomb(resultMap, numBase, bombPos, wildPos, length, 0x1, five, cardLoc, playerNum, cardPoint);
                        }
                }
            case 6:
                switch (wildNum) {
                    case 2:
                        for (int five : getFiveBombArray(card, numOfCard)) {
                            numBase = addWildBomb(resultMap, numBase, bombPos, wildPos, length, 0x11, five, cardLoc, playerNum, cardPoint);
                        }
                    case 1:
                        for (int six : getSixBombArray(card, numOfCard)) {
                            numBase = addWildBomb(resultMap, numBase, bombPos, wildPos, length, 0x1, six, cardLoc, playerNum, cardPoint);
                        }
                }
            case 7:
                switch (wildNum) {
                    case 2:
                        for (int six : getSixBombArray(card, numOfCard)) {
                            numBase = addWildBomb(resultMap, numBase, bombPos, wildPos, length, 0x11, six, cardLoc, playerNum, cardPoint);
                        }
                    case 1:
                        for (int seven : getSevenBombArray(card, numOfCard)) {
                            numBase = addWildBomb(resultMap, numBase, bombPos, wildPos, length, 0x1, seven, cardLoc, playerNum, cardPoint);
                        }
                }
            case 8:
                switch (wildNum) {
                    case 2:
                        for (int seven : getSevenBombArray(card, numOfCard)) {
                            numBase = addWildBomb(resultMap, numBase, bombPos, wildPos, length, 0x11, seven, cardLoc, playerNum, cardPoint);
                        }
                    case 1:
                        if (card == 0xff) {
                            numBase = addWildBomb(resultMap, numBase, bombPos, wildPos, length, 0x1, 0xff, cardLoc, playerNum, cardPoint);
                        }
                }
            case 9:
                if (wildNum == 2 && card == 0xff) {
                    numBase = addWildBomb(resultMap, numBase, bombPos, wildPos, length, 0x11, 0xff, cardLoc, playerNum, cardPoint);
                }
        }
        return numBase;
    }

    private static int addBombAsBombNum(Map<Integer, CardInfo> resultMap, int numBase, int cardLoc, int playerNum, int cardPoint, int bombPos, int wildPos, int length, int bombNum, int card, int wildNum) {
        int numOfCard = numOfSameSuitCards(card);
        switch (wildNum) {
            case 2:
                switch (bombNum) {
                    case 4:
                        for (int two : spliceArray(getSameSuitPairArray(card), getDifferentSuitPairArray(card))) {
                            numBase = addWildBomb(resultMap, numBase, bombPos, wildPos, length, 0x11, two, cardLoc, playerNum, cardPoint);
                        }
                        break;
                    case 5:
                        for (int three : getThreeArray(card)) {
                            numBase = addWildBomb(resultMap, numBase, bombPos, wildPos, length, 0x11, three, cardLoc, playerNum, cardPoint);
                        }
                        break;
                    case 6:
                        for (int four : getFourBombArray(card, numOfCard)) {
                            numBase = addWildBomb(resultMap, numBase, bombPos, wildPos, length, 0x11, four, cardLoc, playerNum, cardPoint);
                        }
                        break;
                    case 7:
                        for (int five : getFiveBombArray(card, numOfCard)) {
                            numBase = addWildBomb(resultMap, numBase, bombPos, wildPos, length, 0x11, five, cardLoc, playerNum, cardPoint);
                        }
                        break;
                    case 8:
                        for (int six : getSixBombArray(card, numOfCard)) {
                            numBase = addWildBomb(resultMap, numBase, bombPos, wildPos, length, 0x11, six, cardLoc, playerNum, cardPoint);
                        }
                        break;
                    case 9:
                        for (int seven : getSevenBombArray(card, numOfCard)) {
                            numBase = addWildBomb(resultMap, numBase, bombPos, wildPos, length, 0x11, seven, cardLoc, playerNum, cardPoint);
                        }
                        break;
                    case 10:
                        if (card == 0xff) {
                            numBase = addWildBomb(resultMap, numBase, bombPos, wildPos, length, 0x11, 0xff, cardLoc, playerNum, cardPoint);
                        }
                }
            case 1:
                switch (bombNum) {
                    case 4:
                        for (int three : getThreeArray(card)) {
                            numBase = addWildBomb(resultMap, numBase, bombPos, wildPos, length, 0x1, three, cardLoc, playerNum, cardPoint);
                        }
                        break;
                    case 5:
                        for (int four : getFourBombArray(card, numOfCard)) {
                            numBase = addWildBomb(resultMap, numBase, bombPos, wildPos, length, 0x1, four, cardLoc, playerNum, cardPoint);
                        }
                        break;
                    case 6:
                        for (int five : getFiveBombArray(card, numOfCard)) {
                            numBase = addWildBomb(resultMap, numBase, bombPos, wildPos, length, 0x1, five, cardLoc, playerNum, cardPoint);
                        }
                        break;
                    case 7:
                        for (int six : getSixBombArray(card, numOfCard)) {
                            numBase = addWildBomb(resultMap, numBase, bombPos, wildPos, length, 0x1, six, cardLoc, playerNum, cardPoint);
                        }
                        break;
                    case 8:
                        for (int seven : getSevenBombArray(card, numOfCard)) {
                            numBase = addWildBomb(resultMap, numBase, bombPos, wildPos, length, 0x1, seven, cardLoc, playerNum, cardPoint);
                        }
                        break;
                    case 9:
                        if (card == 0xff) {
                            numBase = addWildBomb(resultMap, numBase, bombPos, wildPos, length, 0x1, 0xff, cardLoc, playerNum, cardPoint);
                        }
                }
        }
        return numBase;
    }

    private static int addWildBomb(Map<Integer, CardInfo> resultMap, int numBase, int bombPos, int wildPos, int length, int wild, int bomb, int cardLoc, int playerNum, int cardPoint) {
        int[] playedCard = new int[length];
        playedCard[bombPos] = bomb;
        playedCard[wildPos] = wild;
        resultMap.put(numBase++, CardInfo.buildCardInfo(Constants.bomb, playedCard, cardLoc, playerNum, new int[]{cardPoint}));
        return numBase;
    }

    public static Map<Integer, CardInfo> getTwoThreeWithWild(int numBase, int min, int wildNum, int levelCard, Player player) {
        Map<Integer, CardInfo> resultMap = new HashMap<Integer, CardInfo>();

        if (wildNum < 1) {
            return resultMap;
        }
        int[] cards = player.getCards();
        int recordLevelCard = cards[levelCard];
        cards[levelCard] &= 0xee;
        List<int[]> threeList = new ArrayList<>();
        List<int[]> pairList = new ArrayList<>();
        List<int[]> singleList = new ArrayList<>();
        for (int card : cards) {
            threeList.add(getThreeArray(card));
            pairList.add(spliceArray(getSameSuitPairArray(card), getDifferentSuitPairArray(card)));
            singleList.add(getSingleArray(card));
        }
        if (min == -1) {
            switch (wildNum) {
                case 2:
                    numBase = addTwoThreeWithWild(resultMap, numBase, player.getPlayerNum(), pairList.get(12), pairList.get(0), levelCard, 0x11, -1);
                    numBase = addTwoThreeWithWild(resultMap, numBase, player.getPlayerNum(), threeList.get(12), singleList.get(0), levelCard, 0x11, -1);
                    numBase = addTwoThreeWithWild(resultMap, numBase, player.getPlayerNum(), singleList.get(12), threeList.get(0), levelCard, 0x11, -1);
                case 1:
                    numBase = addTwoThreeWithWild(resultMap, numBase, player.getPlayerNum(), threeList.get(12), pairList.get(0), levelCard, 0x1, -1);
                    numBase = addTwoThreeWithWild(resultMap, numBase, player.getPlayerNum(), pairList.get(12), threeList.get(0), levelCard, 0x1, -1);
            }
            ++min;
        }
        switch (wildNum) {
            case 2:
                for (int i = min; i < 12; ++i) {
                    numBase = addTwoThreeWithWild(resultMap, numBase, player.getPlayerNum(), pairList.get(i), pairList.get(i + 1), levelCard, 0x11, i);
                    numBase = addTwoThreeWithWild(resultMap, numBase, player.getPlayerNum(), threeList.get(i), singleList.get(i + 1), levelCard, 0x11, i);
                    numBase = addTwoThreeWithWild(resultMap, numBase, player.getPlayerNum(), singleList.get(i), threeList.get(i + 1), levelCard, 0x11, i);
                }
            case 1:
                for (int i = min; i < 12; ++i) {
                    numBase = addTwoThreeWithWild(resultMap, numBase, player.getPlayerNum(), threeList.get(i), pairList.get(i + 1), levelCard, 0x1, i);
                    numBase = addTwoThreeWithWild(resultMap, numBase, player.getPlayerNum(), pairList.get(i), threeList.get(i + 1), levelCard, 0x1, i);
                }
        }

        cards[levelCard] = recordLevelCard;
        return resultMap;
    }

    private static int addTwoThreeWithWild(Map<Integer, CardInfo> resultMap, int numBase, int playerNum, int[] onePair, int[] twoPair, int levelCard, int wild, int startPos) {
        if (onePair.length > 0 && twoPair.length > 0) {
            for (int one : onePair) {
                for (int two : twoPair) {
                    int[] playedCard = new int[13];
                    playedCard[startPos + 1] = two;
                    startPos = startPos == -1 ? 12 : startPos;
                    playedCard[startPos] = one;
                    playedCard[levelCard] |= wild;
                    resultMap.put(numBase++, CardInfo.buildCardInfo(Constants.twoThree, playedCard, 0, playerNum, new int[]{startPos}));
                    startPos = startPos == 12 ? -1 : startPos;
                }
            }
        }
        return numBase;
    }

    public static Map<Integer, CardInfo> getThreeWithTwoWithWild(int numBase, int min, int wildNum, int levelCard, Player player) {
        Map<Integer, CardInfo> resultMap = new HashMap<Integer, CardInfo>();

        if (wildNum < 1) {
            return resultMap;
        }
        int[] cards = player.getCards();
        int recordLevelCard = cards[levelCard];
        int levelCardTemp;
        if (wildNum == 2) {
            levelCardTemp = (cards[levelCard] & 0xef);
        } else {
            levelCardTemp = (cards[levelCard] & 0xfe);
        }
        int[] levelCardPair = spliceArray(getSameSuitPairArray(levelCardTemp), getDifferentSuitPairArray(levelCardTemp));
        int[] levelCardThree = getThreeArray(levelCardTemp);
        cards[levelCard] &= 0xee;
        List<int[]> threeList = new ArrayList<>();
        List<int[]> pairList = new ArrayList<>();
        List<int[]> singleList = new ArrayList<>();
        for (int i = 0; i < 13; ++i) {
            threeList.add(getThreeArray(cards[i]));
            pairList.add(spliceArray(getSameSuitPairArray(cards[i]), getDifferentSuitPairArray(cards[i])));
            singleList.add(getSingleArray(cards[i]));
        }
        List<int[]> pairListWithKing = new ArrayList<>(pairList);
        pairListWithKing.add(getSameSuitPairArray(cards[13]));
        pairListWithKing.add(getSameSuitPairArray(cards[14]));
        switch (wildNum) {
            case 2:
                if (min != levelCard) {
                    for (int i = min + 1; i < 13; ++i) {
                        if (pairList.get(i).length > 0) {
                            for (int j = 0; j < 13; ++j) {
                                if (j != i && singleList.get(j).length > 0) {
                                    numBase = addThreeWithTwoWithWild(resultMap, numBase, player.getPlayerNum(), pairList.get(i), singleList.get(j), levelCard, 0x11, i, j);
                                }
                            }
                        }

                        if (singleList.get(i).length > 0) {
                            for (int j = 0; j < 15; ++j) {
                                if (j != i && pairListWithKing.get(j).length > 0) {
                                    numBase = addThreeWithTwoWithWild(resultMap, numBase, player.getPlayerNum(), singleList.get(i), pairListWithKing.get(j), levelCard, 0x11, i, j);
                                }
                            }
                        }
                    }
                }
            case 1:
                int wildN = wildNum == 2 ? 0x10 : 0x1;
                if (min != levelCard) {
                    for (int i = min + 1; i < 13; ++i) {
                        if (pairList.get(i).length > 0) {
                            for (int j = 0; j < 15; ++j) {
                                if (j != i && pairListWithKing.get(j).length > 0) {
                                    if (j == levelCard) {
                                        pairListWithKing.set(j, levelCardPair);
                                    }
                                    numBase = addThreeWithTwoWithWild(resultMap, numBase, player.getPlayerNum(), pairList.get(i), pairListWithKing.get(j), levelCard, wildN, i, j);

                                }
                            }
                        }
                        if (threeList.get(i).length > 0) {
                            for (int j = 0; j < 13; ++j) {
                                if (j != i && singleList.get(j).length > 0) {
                                    if (i == levelCard) {
                                        threeList.set(i, levelCardThree);
                                    }
                                    numBase = addThreeWithTwoWithWild(resultMap, numBase, player.getPlayerNum(), threeList.get(i), singleList.get(j), levelCard, wildN, i, j);

                                }
                            }
                        }
                    }
                }
                if (min > levelCard) {
                    if (levelCardThree.length > 0) {
                        for (int j = 0; j < 13; ++j) {
                            if (j != levelCard && singleList.get(j).length > 0) {
                                numBase = addThreeWithTwoWithWild(resultMap, numBase, player.getPlayerNum(), levelCardThree, singleList.get(j), levelCard, wildN, levelCard, j);
                            }
                        }
                    }
                }
        }
        cards[levelCard] = recordLevelCard;
        return resultMap;
    }

    private static int addThreeWithTwoWithWild(Map<Integer, CardInfo> resultMap, int numBase, int playerNum, int[] threeArray, int[] pairArray, int levelCard, int wild, int threePos, int pairPos) {
        if (threeArray.length > 0 && pairArray.length > 0) {
            for (int one : threeArray) {
                for (int two : pairArray) {
                    int[] playedCard = new int[15];
                    playedCard[threePos] = one;
                    playedCard[pairPos] = two;
                    playedCard[levelCard] |= wild;
                    resultMap.put(numBase++, CardInfo.buildCardInfo(Constants.threeWithTwo, playedCard, 0, playerNum, new int[]{threePos, pairPos}));
                }
            }
        }
        return numBase;
    }

    public static Map<Integer, CardInfo> getThreePairWithWild(int numBase, int min, int wildNum, int levelCard, Player player) {
        Map<Integer, CardInfo> resultMap = new HashMap<Integer, CardInfo>();
        if (wildNum < 1) {
            return resultMap;
        }
        List<int[]> pairList = new ArrayList<>();
        List<int[]> singleList = new ArrayList<>();
        int[] cards = player.getCards();
        int recordLevelCard = cards[levelCard];
        cards[levelCard] &= 0xee;
        for (int card : cards) {
            pairList.add(spliceArray(getSameSuitPairArray(card), getDifferentSuitPairArray(card)));
            singleList.add(getSingleArray(card));
        }
        if (min == -1) {
            switch (wildNum) {
                case 2:
                    numBase = addThreePairWithWild(resultMap, numBase, player.getPlayerNum(), pairList.get(12), singleList.get(0), singleList.get(1), levelCard, 0x11, -1);
                    numBase = addThreePairWithWild(resultMap, numBase, player.getPlayerNum(), singleList.get(12), pairList.get(0), singleList.get(1), levelCard, 0x11, -1);
                    numBase = addThreePairWithWild(resultMap, numBase, player.getPlayerNum(), singleList.get(12), singleList.get(0), pairList.get(1), levelCard, 0x11, -1);
                    numBase = addThreePairWithWild(resultMap, numBase, player.getPlayerNum(), pairList.get(12), pairList.get(0), new int[]{0}, levelCard, 0x11, -1);
                    numBase = addThreePairWithWild(resultMap, numBase, player.getPlayerNum(), new int[]{0}, pairList.get(0), pairList.get(1), levelCard, 0x11, -1);
                    numBase = addThreePairWithWild(resultMap, numBase, player.getPlayerNum(), pairList.get(12), new int[]{0}, pairList.get(1), levelCard, 0x11, -1);

                case 1:
                    numBase = addThreePairWithWild(resultMap, numBase, player.getPlayerNum(), pairList.get(12), pairList.get(0), singleList.get(1), levelCard, 0x1, -1);
                    numBase = addThreePairWithWild(resultMap, numBase, player.getPlayerNum(), pairList.get(12), singleList.get(0), pairList.get(1), levelCard, 0x1, -1);
                    numBase = addThreePairWithWild(resultMap, numBase, player.getPlayerNum(), singleList.get(12), pairList.get(0), pairList.get(1), levelCard, 0x1, -1);

            }
            ++min;
        }

        switch (wildNum) {
            case 2:
                for (int i = min; i < 11; ++i) {
                    numBase = addThreePairWithWild(resultMap, numBase, player.getPlayerNum(), pairList.get(i), singleList.get(i + 1), singleList.get(i + 2), levelCard, 0x11, i);
                    numBase = addThreePairWithWild(resultMap, numBase, player.getPlayerNum(), singleList.get(i), pairList.get(i + 1), singleList.get(i + 2), levelCard, 0x11, i);
                    numBase = addThreePairWithWild(resultMap, numBase, player.getPlayerNum(), singleList.get(i), singleList.get(i + 1), pairList.get(i + 2), levelCard, 0x11, i);
                    numBase = addThreePairWithWild(resultMap, numBase, player.getPlayerNum(), pairList.get(i), pairList.get(i + 1), new int[]{0}, levelCard, 0x11, i);
                    numBase = addThreePairWithWild(resultMap, numBase, player.getPlayerNum(), new int[]{0}, pairList.get(i + 1), pairList.get(i + 2), levelCard, 0x11, i);
                    numBase = addThreePairWithWild(resultMap, numBase, player.getPlayerNum(), pairList.get(i), new int[]{0}, pairList.get(i + 2), levelCard, 0x11, i);
                }
            case 1:
                for (int i = min; i < 11; ++i) {
                    numBase = addThreePairWithWild(resultMap, numBase, player.getPlayerNum(), pairList.get(i), pairList.get(i + 1), singleList.get(i + 2), levelCard, 0x1, i);
                    numBase = addThreePairWithWild(resultMap, numBase, player.getPlayerNum(), pairList.get(i), singleList.get(i + 1), pairList.get(i + 2), levelCard, 0x1, i);
                    numBase = addThreePairWithWild(resultMap, numBase, player.getPlayerNum(), singleList.get(i), pairList.get(i + 1), pairList.get(i + 2), levelCard, 0x1, i);
                }
        }
        cards[levelCard] = recordLevelCard;
        return resultMap;
    }

    private static int addThreePairWithWild(Map<Integer, CardInfo> resultMap, int numBase, int playerNum, int[] onePair, int[] twoPair, int[] threePair, int levelCard, int wild, int startPos) {
        if (onePair.length > 0 && twoPair.length > 0 && threePair.length > 0) {
            for (int one : onePair) {
                for (int two : twoPair) {
                    for (int three : threePair) {
                        int[] playedCard = new int[13];
                        playedCard[startPos + 1] = two;
                        playedCard[startPos + 2] = three;
                        startPos = startPos == -1 ? 12 : startPos;
                        playedCard[startPos] = one;
                        playedCard[levelCard] |= wild;
                        resultMap.put(numBase++, CardInfo.buildCardInfo(Constants.threePairs, playedCard, 0, playerNum, new int[]{startPos}));
                        startPos = startPos == 12 ? -1 : startPos;
                    }
                }
            }
        }
        return numBase;
    }

    public static Map<Integer, CardInfo> getStraightFlushWithWild(int numBase, int min, int wildNum, int levelCard, Player player) {
        Map<Integer, CardInfo> resultMap = new HashMap<Integer, CardInfo>();
        if (wildNum < 1) {
            return resultMap;
        }
        int[] cards = player.getCards();
        //清去逢人配
        int recordLevelCard = cards[levelCard];
        cards[levelCard] &= 0xee;
        if (min == -1) {
            for (int j = -1; j < 4; ++j) {
                int wildPos = j == -1 ? 12 : j;
                int temp1 = cards[wildPos];
                cards[wildPos] = 0xff;
                int flag = (cards[0] & cards[1] & cards[2] & cards[3] & cards[12]);
                if (flag != 0) {
                    int[] straightFlush = getSingleArray(flag);
                    for (int straight : straightFlush) {
                        int[] playedCard = new int[13];
                        for (int k = 0; k < 4; ++k) {
                            playedCard[k] = straight;
                        }
                        playedCard[12] = straight;
                        playedCard[wildPos] = 0;
                        playedCard[levelCard] |= 0x1;
                        resultMap.put(numBase++, CardInfo.buildCardInfo(Constants.straightFlush, playedCard, 0, player.getPlayerNum(), new int[]{12}));
                    }
                }
                if (wildNum == 2) {
                    for (int k = j + 1; k < 4; ++k) {
                        int temp2 = cards[k];
                        cards[k] = 0xff;
                        flag = (cards[0] & cards[1] & cards[2] & cards[3] & cards[12]);
                        if (flag != 0) {
                            int[] straightFlush = getSingleArray(flag);
                            for (int straight : straightFlush) {
                                int[] playedCard = new int[13];
                                for (int l = 0; l < 4; ++l) {
                                    playedCard[l] = straight;
                                }
                                playedCard[12] = straight;
                                playedCard[wildPos] = 0;
                                playedCard[k] = 0;
                                playedCard[levelCard] |= 0x11;
                                resultMap.put(numBase++, CardInfo.buildCardInfo(Constants.straightFlush, playedCard, 0, player.getPlayerNum(), new int[]{12}));
                            }
                        }
                        cards[k] = temp2;
                    }
                }
                cards[wildPos] = temp1;
            }
            ++min;
        }
        for (int i = min; i < 9; ++i) {
            for (int j = i; j < i + 5; ++j) {
                int temp1 = cards[j];
                cards[j] = 0xff;
                int flag = (cards[i] & cards[i + 1] & cards[i + 2] & cards[i + 3] & cards[i + 4]);
                if (flag != 0) {
                    int[] straightFlush = getSingleArray(flag);
                    for (int straight : straightFlush) {
                        int[] playedCard = new int[13];
                        for (int k = i; k < i + 5; ++k) {
                            playedCard[k] = straight;
                        }
                        playedCard[j] = 0;
                        playedCard[levelCard] |= 0x1;
                        resultMap.put(numBase++, CardInfo.buildCardInfo(Constants.straightFlush, playedCard, 0, player.getPlayerNum(), new int[]{i}));
                    }
                }
                if (wildNum == 2) {
                    for (int k = j + 1; k < i + 5; ++k) {
                        int temp2 = cards[k];
                        cards[k] = 0xff;
                        flag = (cards[i] & cards[i + 1] & cards[i + 2] & cards[i + 3] & cards[i + 4]);
                        if (flag != 0) {
                            int[] straightFlush = getSingleArray(flag);
                            for (int straight : straightFlush) {
                                int[] playedCard = new int[13];
                                for (int l = i; l < i + 5; ++l) {
                                    playedCard[l] = straight;
                                }
                                playedCard[j] = 0;
                                playedCard[k] = 0;
                                playedCard[levelCard] |= 0x11;
                                resultMap.put(numBase++, CardInfo.buildCardInfo(Constants.straightFlush, playedCard, 0, player.getPlayerNum(), new int[]{i}));
                            }
                        }
                        cards[k] = temp2;
                    }
                }
                cards[j] = temp1;
            }
        }
        cards[levelCard] = recordLevelCard;
        return resultMap;
    }

    public static Map<Integer, CardInfo> getStraightWithWild(int numBase, int min, int wildNum, int levelCard, Player player) {
        Map<Integer, CardInfo> resultMap = new HashMap<Integer, CardInfo>();
        if (wildNum < 1) {
            return resultMap;
        }
        int[] replaceArray = new int[]{1};
        int[] cards = player.getCards();
        int recordLevelCard = cards[levelCard];
        cards[levelCard] &= (0xee);
        List<int[]> singleList = new ArrayList<>();
        for (int card : cards) {
            singleList.add(getSingleArray(card));
        }
        if (min == -1) {
            for (int j = -1; j < 4; ++j) {
                int wildPos = j == -1 ? 12 : j;
                int[] temp1 = singleList.get(wildPos);
                singleList.set(wildPos, replaceArray);
                if (singleList.get(12).length > 0 &&
                        singleList.get(0).length > 0 &&
                        singleList.get(1).length > 0 &&
                        singleList.get(2).length > 0 &&
                        singleList.get(3).length > 0) {
                    for (int one : singleList.get(12)) {
                        for (int two : singleList.get(0)) {
                            for (int three : singleList.get(1)) {
                                for (int four : singleList.get(2)) {
                                    for (int five : singleList.get(3)) {
                                        int[] playedCard = new int[13];
                                        //过滤掉可同花顺顺子
                                        if ((one & two & three & four & five) != 0) {
                                            continue;
                                        }
                                        playedCard[12] = one;
                                        playedCard[0] = two;
                                        playedCard[1] = three;
                                        playedCard[2] = four;
                                        playedCard[3] = five;
                                        playedCard[wildPos] = 0;
                                        playedCard[levelCard] |= 0x1;
                                        resultMap.put(numBase++, CardInfo.buildCardInfo(Constants.straight, playedCard, 0, player.getPlayerNum(), new int[]{12}));
                                    }
                                }
                            }
                        }
                    }
                }

                if (wildNum == 2) {
                    for (int k = j + 1; k < 4; ++k) {
                        int[] temp2 = singleList.get(k);
                        singleList.set(k, replaceArray);
                        if (singleList.get(12).length > 0 &&
                                singleList.get(0).length > 0 &&
                                singleList.get(1).length > 0 &&
                                singleList.get(2).length > 0 &&
                                singleList.get(3).length > 0) {
                            for (int one : singleList.get(12)) {
                                for (int two : singleList.get(0)) {
                                    for (int three : singleList.get(1)) {
                                        for (int four : singleList.get(2)) {
                                            for (int five : singleList.get(3)) {
                                                if ((one & two & three & four & five) != 0) {
                                                    continue;
                                                }
                                                int[] playedCard = new int[13];
                                                playedCard[12] = one;
                                                playedCard[0] = two;
                                                playedCard[1] = three;
                                                playedCard[2] = four;
                                                playedCard[3] = five;
                                                playedCard[wildPos] = 0;
                                                playedCard[k] = 0;
                                                playedCard[levelCard] |= 0x11;
                                                resultMap.put(numBase++, CardInfo.buildCardInfo(Constants.straight, playedCard, 0, player.getPlayerNum(), new int[]{12}));
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        singleList.set(k, temp2);
                    }
                }
                singleList.set(wildPos, temp1);
            }

            ++min;
        }

        for (int i = min; i < 9; ++i) {
            for (int j = i; j < i + 5; ++j) {
                int[] temp1 = singleList.get(j);
                singleList.set(j, replaceArray);
                if (singleList.get(i).length > 0 &&
                        singleList.get(i + 1).length > 0 &&
                        singleList.get(i + 2).length > 0 &&
                        singleList.get(i + 3).length > 0 &&
                        singleList.get(i + 4).length > 0) {
                    for (int one : singleList.get(i)) {
                        for (int two : singleList.get(i + 1)) {
                            for (int three : singleList.get(i + 2)) {
                                for (int four : singleList.get(i + 3)) {
                                    for (int five : singleList.get(i + 4)) {
                                        if ((one & two & three & four & five) != 0) {
                                            continue;
                                        }
                                        int[] playedCard = new int[13];
                                        playedCard[i] = one;
                                        playedCard[i + 1] = two;
                                        playedCard[i + 2] = three;
                                        playedCard[i + 3] = four;
                                        playedCard[i + 4] = five;
                                        playedCard[j] = 0;
                                        playedCard[levelCard] |= 0x1;
                                        resultMap.put(numBase++, CardInfo.buildCardInfo(Constants.straight, playedCard, 0, player.getPlayerNum(), new int[]{i}));
                                    }
                                }
                            }
                        }
                    }
                }

                if (wildNum == 2) {
                    for (int k = j + 1; k < i + 5; ++k) {
                        int[] temp2 = singleList.get(k);
                        singleList.set(k, replaceArray);
                        if (singleList.get(i).length > 0 &&
                                singleList.get(i + 1).length > 0 &&
                                singleList.get(i + 2).length > 0 &&
                                singleList.get(i + 3).length > 0 &&
                                singleList.get(i + 4).length > 0) {
                            for (int one : singleList.get(i)) {
                                for (int two : singleList.get(i + 1)) {
                                    for (int three : singleList.get(i + 2)) {
                                        for (int four : singleList.get(i + 3)) {
                                            for (int five : singleList.get(i + 4)) {
                                                if ((one & two & three & four & five) != 0) {
                                                    continue;
                                                }
                                                int[] playedCard = new int[13];
                                                playedCard[i] = one;
                                                playedCard[i + 1] = two;
                                                playedCard[i + 2] = three;
                                                playedCard[i + 3] = four;
                                                playedCard[i + 4] = five;
                                                playedCard[j] = 0;
                                                playedCard[k] = 0;
                                                playedCard[levelCard] |= 0x11;
                                                resultMap.put(numBase++, CardInfo.buildCardInfo(Constants.straight, playedCard, 0, player.getPlayerNum(), new int[]{i}));
                                            }
                                        }
                                    }
                                }
                            }
                        }
                        singleList.set(k, temp2);
                    }
                }
                singleList.set(j, temp1);
            }
        }
        cards[levelCard] = recordLevelCard;
        return resultMap;
    }


    //**************************************************//

    public static int[] filterNonZero(int[] array) {
        int count = 0;
        for (int a : array) {
            if (a != 0) {
                ++count;
            }
        }
        int[] result = new int[count];
        count = 0;
        for (int a : array) {
            if (a != 0) {
                result[count++] = a;
            }
        }
        return result;
    }

    public static int addSameValueCard(Map<Integer, CardInfo> resultMap, int numBase, int cardLoc, int playerNum, int type, int[] cards) {
        for (int card : cards) {
            resultMap.put(numBase++, CardInfo.buildCardInfo(type, new int[]{card}, cardLoc, playerNum, new int[]{cardLoc}));
        }
        return numBase;
    }

    //计算int中1的个数
    public static int numOfSameSuitCards(int card) {
        int count = 0;
        while (card != 0) {
            card &= (card - 1);
            ++count;
        }
        return count;
    }

    //得到王之外的对子
    public static List<int[]> getAllPairs(Player player) {
        List<int[]> allPairs = new ArrayList<>();
        int[] sameSuitPair;
        int[] differentSuitPair;
        for (int i = 0; i < 13; ++i) {
            sameSuitPair = getSameSuitPairArray(player.getCards()[i]);
            differentSuitPair = getDifferentSuitPairArray(player.getCards()[i]);
            allPairs.add(IntStream.concat(Arrays.stream(sameSuitPair), Arrays.stream(differentSuitPair)).toArray());
        }
        return allPairs;
    }

    public static int[] spliceArray(int[] array1, int[] array2) {
        int[] result = new int[array1.length + array2.length];
        int index = 0;
        for (int num : array1) {
            result[index++] = num;
        }
        for (int num : array2) {
            result[index++] = num;
        }
        return result;
    }


}
