package taurus.util;

import com.taurus.core.entity.ITArray;
import com.taurus.core.entity.ITObject;
import hunan.HuNanPaoDeKuai;

import java.util.*;
import java.util.stream.Collectors;

public class test {

    /**
     * 跑得快出牌策略
     */
    public static ITArray intelligentPaoDeKuaiOutCard(List<CardObj> cardInhand, ITObject card_list, Map<Integer, List<Integer>> seatRemainHistory) {
        System.out.println("机器人手牌 cardInhand: " + cardInhand);
        System.out.println("card_list: " + card_list);
        System.out.println("机器人座位号 8888888888888888888888888888  " + HuNanPaoDeKuai.seat);
        int seat = HuNanPaoDeKuai.seat;

        List<CardObj> sortedHand = new ArrayList<>(cardInhand);
        Collections.sort(sortedHand);
        List<CardObj> playCards;

        boolean isFirstTurn = card_list == null || !card_list.containsKey("card_list") ||
                card_list.getTArray("card_list").size() == 0;

        if (isFirstTurn) {
            System.out.println("进入自己先出牌-----------");
            playCards = intelligentFirstPlayWithRemainConsideration(sortedHand, seatRemainHistory);
        } else {
            ITArray opponentCardsArray = card_list.getTArray("card_list");
            List<CardObj> opponentCards = CardUtil.toList(opponentCardsArray);

            int minCard = card_list.getInt("min_card");
            int len = card_list.getInt("len");
            int type = card_list.getInt("type");

            //座位号还是自己的情况 这里座位号是对面的了 还进入了
            if (HuNanPaoDeKuai.seat == HuNanPaoDeKuai.guangboseat) {
                Map<Integer, Integer> otherSeatsLastRemain = getOtherSeatsLastRemain(seat, seatRemainHistory);
                boolean hasAnyEqualOne = otherSeatsLastRemain.values().stream().anyMatch(value -> value == 1);
                if (hasAnyEqualOne) {
                    System.out.println("进入对面只剩下一张牌");
                    // 优先出对子
                    List<CardObj> pair = findAnyPair(cardInhand);
                    System.out.println("检测到对手只剩一张牌，优先出对子压制111" + pair);
                    if (pair.size() == 2) {
                        System.out.println("推荐出牌: " + pair + " (对子压制)");
                        return CardUtil.toTArray(pair);
                    } else {
                        // 没有对子，出最大单牌
                        System.out.println("检测到对手只剩一张牌 没有对子，出最大单牌");
                        CardObj maxSingleCard = findMaxSingleCard(cardInhand);
                        return CardUtil.toTArray1(maxSingleCard);
                    }
                } else {
                    System.out.println("机器人跑得快座位号 88888888888888    "  + HuNanPaoDeKuai.seat);
                    System.out.println("广播座位号 9999999999    "  + HuNanPaoDeKuai.guangboseat);

                    //座位号出问题了
                    playCards = intelligentFirstPlayWithRemainConsideration(sortedHand, seatRemainHistory);
                    return CardUtil.toTArray(playCards);
                }
            }

            Map<Integer, Integer> otherSeatsLastRemain = getOtherSeatsLastRemain(seat, seatRemainHistory);
            boolean hasAnyEqualOne = otherSeatsLastRemain.values().stream().anyMatch(value -> value == 1);

            if (hasAnyEqualOne && type == 1) {
                System.out.println("进入对面只剩下一张牌，出最大单牌");
                CardObj maxSingleCard = findMaxSingleCard(cardInhand);
                return CardUtil.toTArray1(maxSingleCard);
            } else {
                playCards = intelligentResponsePlayWithRemainConsideration(sortedHand, minCard, len, opponentCards, type);
                return CardUtil.toTArray(playCards);
            }
        }
        return CardUtil.toTArray(playCards);
    }

    /**
     * 深度分析手牌结构
     */
    private static HandAnalysis analyzeHandStructure(List<CardObj> handCards) {
        HandAnalysis analysis = new HandAnalysis();
        analysis.valueCount = getValueCount(handCards);

        // 基础统计
        analysis.smallSingleCount = countSmallSingles(handCards, analysis.valueCount);
        analysis.bigCardCount = countBigCards(analysis.valueCount);
        analysis.pairCount = countPairs(analysis.valueCount);
        analysis.trioCount = countTrios(analysis.valueCount);
        analysis.bombCount = countBombs(analysis.valueCount);

        // 顺子分析
        analysis.maxStraightLength = findMaxStraightLength(handCards);

        // 连对分析
        analysis.maxConsecutivePairs = findMaxConsecutivePairs(handCards);

        // 控制牌分析
        analysis.hasControlCards = analysis.bigCardCount > 0;

        // 收集所有可能的出牌
        analysis.allPossiblePlays = collectAllPossibleFirstPlays(handCards);

        // 设置特征标签
        setAnalysisFeatures(analysis);

        return analysis;
    }

    /**
     * 首轮出牌
     */
    private static List<CardObj> intelligentFirstPlayWithRemainConsideration(List<CardObj> handCards, Map<Integer, List<Integer>> seatRemainHistory) {
        if (handCards.isEmpty()) return new ArrayList<>();

        // === 飞机优先出牌 ===
        System.out.println("=== 检测飞机牌型 ===");
        List<CardObj> airplanePlay = findAndPlayAirplane(handCards);
        if (!airplanePlay.isEmpty()) {
            System.out.println("推荐飞机出牌: " + airplanePlay + " (类型:飞机带四张)");
            return airplanePlay;
        }


        // 4-8张手牌特殊处理
        if (handCards.size() >= 4 && handCards.size() <= 8) {
            System.out.println("=== 4-8张手牌快速出完策略 ===");
            List<CardObj> quickWinPlay = findQuickWinPlay(handCards);
            if (!quickWinPlay.isEmpty()) {
                System.out.println("推荐快速出牌: " + quickWinPlay + " (类型:" + getPlayType(quickWinPlay) + ")");
                return quickWinPlay;
            }
        }

        // 特殊处理：手牌很少时的策略
        if (handCards.size() <= 3) {
            //如果对面只剩下一张牌，并且自己剩下的牌里有对子优先打对子
            List<CardObj> bestCard = findBestCardToPlay(handCards, seatRemainHistory);
            //如果没有对子出最大的单牌
            if (bestCard.isEmpty()) {
                System.out.println("没有对子出最大的单牌");
                List<CardObj> pair = findAnyPair(handCards);
                if (pair.isEmpty()) {
                    CardObj maxCard = findMaxCard(handCards);
                    return Collections.singletonList(maxCard);
                }
                return pair;
            }
            return bestCard;
        }

        if (handCards.size() == 15) {
            Map<Integer, Integer> valueCount = getValueCount(handCards);
            // 找出所有的三张
            List<Integer> trioValues = valueCount.entrySet().stream()
                    .filter(entry -> entry.getValue() == 3)  // 严格等于3，确保是完整的三张
                    .map(Map.Entry::getKey)
                    .sorted()
                    .collect(Collectors.toList());

            // 需要正好3个三张才能形成三个三带结构
            if (trioValues.size() != 3) {
                System.out.println("三张数量不是3个，不构成完美三个三带结构");

                // 修复：分析大牌分布，避免首轮全出大牌
                HandAnalysis analysis = analyzeHandStructure(handCards);
                List<CardObj> bestFirstPlay = selectBestFirstPlayWithBigCardProtection(handCards, analysis);

                System.out.println("=== 分析结果 ===");
                System.out.println("牌型特征: " + analysis.features.get("feature"));
                System.out.println("小单牌: " + analysis.smallSingleCount + ", 大牌: " + analysis.bigCardCount +
                        ", 对子: " + analysis.pairCount + ", 顺子长度: " + analysis.maxStraightLength);
                System.out.println("推荐首出: " + bestFirstPlay + " (类型:" + getPlayType(bestFirstPlay) + ")");
                return bestFirstPlay;
            }

            return tryPlayTrioWithOne(handCards, valueCount);
        }

        // 修复：分析大牌分布，避免首轮全出大牌
        HandAnalysis analysis = analyzeHandStructure(handCards);
        List<CardObj> bestFirstPlay = selectBestFirstPlayWithBigCardProtection(handCards, analysis);

        System.out.println("=== 分析结果 ===");
        System.out.println("牌型特征: " + analysis.features.get("feature"));
        System.out.println("小单牌: " + analysis.smallSingleCount + ", 大牌: " + analysis.bigCardCount +
                ", 对子: " + analysis.pairCount + ", 顺子长度: " + analysis.maxStraightLength);
        System.out.println("推荐首出: " + bestFirstPlay + " (类型:" + getPlayType(bestFirstPlay) + ")");

        return bestFirstPlay;
    }


    /**
     * 计算单牌的孤立程度分数（越高越孤立）
     */
    private static int calculateIsolationScore(Map<Integer, Integer> valueCount, int value) {
        int score = 0;

        // 基础分：自身是单张
        if (valueCount.getOrDefault(value, 0) == 1) {
            score += 10;
        }

        // 前后都没有牌加分
        if (valueCount.getOrDefault(value - 1, 0) == 0) score += 5;
        if (valueCount.getOrDefault(value + 1, 0) == 0) score += 5;

        // 前后2格都没有牌额外加分
        if (valueCount.getOrDefault(value - 2, 0) == 0) score += 2;
        if (valueCount.getOrDefault(value + 2, 0) == 0) score += 2;

        return score;
    }


    /**
     * 检测并构建飞机出牌（优先带小单牌或小对子，尽量不拆牌）
     */
    private static List<CardObj> findAndPlayAirplane(List<CardObj> handCards) {
        Map<Integer, Integer> valueCount = getValueCount(handCards);

        // 找出所有三张的牌值
        List<Integer> trioValues = valueCount.entrySet().stream()
                .filter(entry -> entry.getValue() >= 3)  // 至少3张
                .map(Map.Entry::getKey)
                .sorted()
                .collect(Collectors.toList());

        if (trioValues.size() < 2) {
            return new ArrayList<>(); // 不够两个三张，无法形成飞机
        }

        // 寻找连续的三张（飞机）
        List<List<Integer>> airplaneChains = new ArrayList<>();
        List<Integer> currentChain = new ArrayList<>();

        for (int i = 0; i < trioValues.size(); i++) {
            if (currentChain.isEmpty()) {
                currentChain.add(trioValues.get(i));
            } else {
                int lastValue = currentChain.get(currentChain.size() - 1);
                int currentValue = trioValues.get(i);

                if (currentValue == lastValue + 1) {
                    currentChain.add(currentValue);
                } else {
                    if (currentChain.size() >= 2) {
                        airplaneChains.add(new ArrayList<>(currentChain));
                    }
                    currentChain.clear();
                    currentChain.add(currentValue);
                }
            }
        }

        if (currentChain.size() >= 2) {
            airplaneChains.add(new ArrayList<>(currentChain));
        }

        if (airplaneChains.isEmpty()) {
            return new ArrayList<>(); // 没有连续的飞机
        }

        // 选择最长的飞机链
        List<Integer> bestAirplane = airplaneChains.stream()
                .max(Comparator.comparingInt(List::size))
                .orElse(airplaneChains.get(0));

        System.out.println("找到飞机链: " + bestAirplane + " (长度:" + bestAirplane.size() + ")");

        // 构建飞机主体（所有三张）
        List<CardObj> airplane = new ArrayList<>();
        for (int value : bestAirplane) {
            List<CardObj> trio = handCards.stream()
                    .filter(card -> card.cardMod == value)
                    .limit(3)
                    .collect(Collectors.toList());
            airplane.addAll(trio);
        }

        // 使用智能策略寻找带牌（考虑出完后的手牌结构）
        List<CardObj> carryCards = findBestCarryCardsForAirplane(handCards, bestAirplane, valueCount);

        int requiredCarryCount = bestAirplane.size() * 2;

        if (carryCards.size() >= requiredCarryCount) {
            airplane.addAll(carryCards.subList(0, requiredCarryCount));
            System.out.println("形成飞机带" + requiredCarryCount + "张: " +
                    airplane.stream().map(card -> card.cardMod).collect(Collectors.toList()));
            return airplane;
        } else {
            System.out.println("飞机带牌不足，需要" + requiredCarryCount + "张，实际只有" + carryCards.size() + "张");
            return new ArrayList<>();
        }
    }

    /**
     * 为飞机寻找最佳带牌（优先带小单牌或小对子，尽量不拆牌）
     */
    private static List<CardObj> findBestCarryCardsForAirplane(List<CardObj> handCards, List<Integer> airplaneValues,
                                                               Map<Integer, Integer> valueCount) {
        List<CardObj> carryCards = new ArrayList<>();
        int requiredCarryCount = airplaneValues.size() * 2;

        // 复制手牌并移除飞机主体
        List<CardObj> availableCards = new ArrayList<>(handCards);
        for (int value : airplaneValues) {
            availableCards.removeIf(card -> card.cardMod == value);
        }

        System.out.println("可用带牌: " + availableCards.stream()
                .map(card -> card.cardMod)
                .sorted()
                .collect(Collectors.toList()));

        // 分析各种带牌方案对剩余手牌的影响
        List<CarryOption> options = analyzeAllCarryOptions(availableCards, requiredCarryCount);

        // 选择最优方案
        CarryOption bestOption = selectBestCarryOption(options);

        if (bestOption != null) {
            System.out.println("最优带牌方案: " + bestOption.carryCards.stream()
                    .map(card -> card.cardMod)
                    .collect(Collectors.toList()) +
                    ", 剩余手数: " + bestOption.remainingTurns +
                    ", 剩余牌型: " + bestOption.remainingPattern);
            return bestOption.carryCards;
        }

        // 如果没有找到合适方案，使用保守策略
        return findConservativeCarryCards(availableCards, requiredCarryCount);
    }


    /**
     * 分析所有可能的带牌方案
     */
    private static List<CarryOption> analyzeAllCarryOptions(List<CardObj> availableCards, int requiredCount) {
        List<CarryOption> options = new ArrayList<>();
        // 生成所有可能的带牌组合
        List<List<CardObj>> allCombinations = generateCarryCombinations(availableCards, requiredCount);

        for (List<CardObj> combination : allCombinations) {
            // 计算剩余手牌
            List<CardObj> remainingCards = new ArrayList<>(availableCards);
            remainingCards.removeAll(combination);

            // 分析剩余手牌
            RemainAnalysis analysis = analyzeRemainingHand(remainingCards);

            CarryOption option = new CarryOption();
            option.carryCards = combination;
            option.remainingCards = remainingCards;
            option.remainingTurns = analysis.estimatedTurns;
            option.remainingPattern = analysis.bestPattern;
            option.score = calculateCarryOptionScore(analysis, combination);

            options.add(option);
        }

        return options;
    }

    /**
     * 生成所有可能的带牌组合
     */
    private static List<List<CardObj>> generateCarryCombinations(List<CardObj> availableCards, int requiredCount) {
        List<List<CardObj>> combinations = new ArrayList<>();

        if (availableCards.size() > 8) {
            return generateHeuristicCarryCombinations(availableCards, requiredCount);
        }

        // 生成所有组合
        generateCombinationsRecursive(availableCards, requiredCount, 0, new ArrayList<>(), combinations);
        return combinations;
    }

    /**
     * 递归生成组合
     */
    private static void generateCombinationsRecursive(List<CardObj> availableCards, int requiredCount,
                                                      int startIndex, List<CardObj> current,
                                                      List<List<CardObj>> combinations) {
        if (current.size() == requiredCount) {
            combinations.add(new ArrayList<>(current));
            return;
        }

        for (int i = startIndex; i < availableCards.size(); i++) {
            current.add(availableCards.get(i));
            generateCombinationsRecursive(availableCards, requiredCount, i + 1, current, combinations);
            current.remove(current.size() - 1);
        }
    }

    /**
     * 启发式方法生成带牌组合（避免组合爆炸）
     */
    private static List<List<CardObj>> generateHeuristicCarryCombinations(List<CardObj> availableCards, int requiredCount) {
        List<List<CardObj>> combinations = new ArrayList<>();
        Map<Integer, Integer> valueCount = getValueCount(availableCards);

        // 策略1：优先使用完整对子的组合
        List<Integer> allPairs = valueCount.entrySet().stream()
                .filter(entry -> entry.getValue() >= 2)
                .map(Map.Entry::getKey)
                .sorted()
                .collect(Collectors.toList());

        // 生成以对子为主的组合
        for (int i = 0; i < Math.min(3, allPairs.size()); i++) {
            int pairValue = allPairs.get(i);
            List<CardObj> pair = availableCards.stream()
                    .filter(card -> card.cardMod == pairValue)
                    .limit(2)
                    .collect(Collectors.toList());

            if (pair.size() == 2) {
                // 对子 + 单牌组合
                List<CardObj> remainingCards = new ArrayList<>(availableCards);
                remainingCards.removeAll(pair);

                if (requiredCount == 4) {
                    // 需要再找2张单牌
                    List<CardObj> singles = getAvailableSingles(remainingCards).stream()
                            .filter(card -> card.cardMod <= 10)
                            .limit(2)
                            .collect(Collectors.toList());

                    if (singles.size() == 2) {
                        List<CardObj> combination = new ArrayList<>(pair);
                        combination.addAll(singles);
                        combinations.add(combination);
                    }
                }
            }
        }

        // 策略2：单牌组合（优先小单牌）
        if (combinations.isEmpty()) {
            List<CardObj> smallSingles = availableCards.stream()
                    .filter(card -> valueCount.getOrDefault(card.cardMod, 0) == 1) // 真单牌
                    .filter(card -> card.cardMod <= 10)
                    .sorted(Comparator.comparingInt(card -> card.cardMod))
                    .limit(requiredCount)
                    .collect(Collectors.toList());

            if (smallSingles.size() == requiredCount) {
                combinations.add(smallSingles);
            }
        }

        // 策略3：混合组合（对子+单牌）
        if (combinations.isEmpty()) {
            // 找一个对子
            Optional<Integer> pairOpt = allPairs.stream().findFirst();
            if (pairOpt.isPresent()) {
                int pairValue = pairOpt.get();
                List<CardObj> pair = availableCards.stream()
                        .filter(card -> card.cardMod == pairValue)
                        .limit(2)
                        .collect(Collectors.toList());

                if (pair.size() == 2) {
                    List<CardObj> remainingCards = new ArrayList<>(availableCards);
                    remainingCards.removeAll(pair);

                    // 找需要的单牌
                    List<CardObj> neededSingles = remainingCards.stream()
                            .filter(card -> card.cardMod != pairValue)
                            .sorted(Comparator.comparingInt(card -> card.cardMod))
                            .limit(requiredCount - 2)
                            .collect(Collectors.toList());

                    if (neededSingles.size() == requiredCount - 2) {
                        List<CardObj> combination = new ArrayList<>(pair);
                        combination.addAll(neededSingles);
                        combinations.add(combination);
                    }
                }
            }
        }

        // 策略4：纯单牌组合（任意单牌）
        if (combinations.isEmpty()) {
            List<CardObj> anySingles = availableCards.stream()
                    .sorted(Comparator.comparingInt(card -> card.cardMod))
                    .limit(requiredCount)
                    .collect(Collectors.toList());
            combinations.add(anySingles);
        }

        // 策略5：考虑保留顺子的特殊组合
        List<List<CardObj>> straightPreservingCombinations = generateStraightPreservingCombinations(availableCards, requiredCount);
        combinations.addAll(straightPreservingCombinations);

        return combinations;
    }

    /**
     * 生成保留顺子的带牌组合
     */
    private static List<List<CardObj>> generateStraightPreservingCombinations(List<CardObj> availableCards, int requiredCount) {
        List<List<CardObj>> combinations = new ArrayList<>();
        List<Integer> values = availableCards.stream()
                .map(card -> card.cardMod)
                .distinct()
                .sorted()
                .collect(Collectors.toList());

        System.out.println("分析顺子保留策略，可用牌值: " + values);

        // 找出所有可能的顺子
        for (int length = 5; length <= values.size(); length++) {
            for (int start = 0; start <= values.size() - length; start++) {
                List<Integer> potentialStraight = values.subList(start, start + length);
                if (isConsecutive(potentialStraight, 0, potentialStraight.size())) {
                    System.out.println("发现顺子: " + potentialStraight);

                    // 尝试从顺子外取带牌，保留这个顺子
                    Set<Integer> straightSet = new HashSet<>(potentialStraight);
                    List<CardObj> outsideCards = availableCards.stream()
                            .filter(card -> !straightSet.contains(card.cardMod))
                            .collect(Collectors.toList());

                    System.out.println("顺子外牌: " + outsideCards.stream()
                            .map(card -> card.cardMod)
                            .collect(Collectors.toList()));

                    if (outsideCards.size() >= requiredCount) {
                        // 顺子外有足够的牌，完美！
                        List<CardObj> combination = outsideCards.stream()
                                .sorted(Comparator.comparingInt(card -> card.cardMod))
                                .limit(requiredCount)
                                .collect(Collectors.toList());
                        combinations.add(combination);
                        System.out.println("完美方案: 从顺子外取牌 " + combination.stream()
                                .map(card -> card.cardMod)
                                .collect(Collectors.toList()));
                    } else if (outsideCards.size() > 0) {
                        // 顺子外不够，需要从顺子中取少量牌，但要尽量保持顺子完整
                        int neededFromStraight = requiredCount - outsideCards.size();

                        // 从顺子的"间隙"位置取牌，尽量不破坏顺子连续性
                        List<CardObj> bestStraightCards = getBestCardsFromStraight(availableCards, potentialStraight, neededFromStraight);

                        if (bestStraightCards.size() == neededFromStraight) {
                            List<CardObj> combination = new ArrayList<>(outsideCards);
                            combination.addAll(bestStraightCards);
                            combinations.add(combination);
                            System.out.println("较好方案: 顺子外" + outsideCards.size() + "张 + 顺子内" + neededFromStraight + "张 = " +
                                    combination.stream().map(card -> card.cardMod).collect(Collectors.toList()));
                        }
                    }
                }
            }
        }

        return combinations;
    }

    /**
     * 从顺子中取最合适的牌（尽量保持顺子完整性）
     */
    private static List<CardObj> getBestCardsFromStraight(List<CardObj> availableCards, List<Integer> straight, int neededCount) {
        List<CardObj> selected = new ArrayList<>();

        // 策略：优先取顺子两端的牌，或者取有重复值的牌
        Map<Integer, Integer> valueCount = getValueCount(availableCards);

        // 先找有重复值的牌（对子、三张等）
        for (int value : straight) {
            if (valueCount.getOrDefault(value, 0) > 1 && selected.size() < neededCount) {
                CardObj card = availableCards.stream()
                        .filter(c -> c.cardMod == value)
                        .findFirst()
                        .orElse(null);
                if (card != null) {
                    selected.add(card);
                }
            }
        }

        // 如果还不够，从顺子两端取
        if (selected.size() < neededCount) {
            // 从左端取
            for (int i = 0; i < straight.size() && selected.size() < neededCount; i++) {
                int value = straight.get(i);
                if (!selected.stream().anyMatch(card -> card.cardMod == value)) {
                    CardObj card = availableCards.stream()
                            .filter(c -> c.cardMod == value)
                            .findFirst()
                            .orElse(null);
                    if (card != null) {
                        selected.add(card);
                    }
                }
            }
        }

        // 如果还不够，从右端取
        if (selected.size() < neededCount) {
            for (int i = straight.size() - 1; i >= 0 && selected.size() < neededCount; i--) {
                int value = straight.get(i);
                if (!selected.stream().anyMatch(card -> card.cardMod == value)) {
                    CardObj card = availableCards.stream()
                            .filter(c -> c.cardMod == value)
                            .findFirst()
                            .orElse(null);
                    if (card != null) {
                        selected.add(card);
                    }
                }
            }
        }

        return selected;
    }

    /**
     * 计算带牌方案分数（优化版）
     */
    private static int calculateCarryOptionScore(RemainAnalysis analysis, List<CardObj> carryCards) {
        int score = 0;

        // 剩余手数越少分数越高（最重要）
        score += (10 - analysis.estimatedTurns) * 100;

        // 如果剩余牌能一次性出完，大幅加分
        if (analysis.estimatedTurns == 1) {
            score += 500;
        }

        // 如果剩余牌是顺子，大幅加分
        if (analysis.bestPattern.contains("顺子")) {
            score += 300;
        }

        // 如果剩余牌是连对，加分
        if (analysis.bestPattern.contains("连对")) {
            score += 200;
        }

        // 带牌中单牌数量越少越好（避免拆对子）
        Map<Integer, Integer> carryCount = getValueCount(carryCards);
        long singleCarryCount = carryCount.values().stream().filter(c -> c == 1).count();
        score -= singleCarryCount * 20;

        // 带牌中对子数量越多越好
        long pairCarryCount = carryCount.values().stream().filter(c -> c == 2).count();
        score += pairCarryCount * 25;

        // 优先带小牌
        int maxCarryValue = carryCards.stream().mapToInt(c -> c.cardMod).max().orElse(0);
        if (maxCarryValue <= 10) {
            score += 15;
        }

        System.out.println("方案评分: 带牌=" + carryCards.stream().map(c -> c.cardMod).collect(Collectors.toList()) +
                ", 剩余手数=" + analysis.estimatedTurns + ", 牌型=" + analysis.bestPattern + ", 分数=" + score);

        return score;
    }

    /**
     * 分析剩余手牌（优化版）
     */
    private static RemainAnalysis analyzeRemainingHand(List<CardObj> remainingCards) {
        RemainAnalysis analysis = new RemainAnalysis();

        if (remainingCards.isEmpty()) {
            analysis.estimatedTurns = 0;
            analysis.bestPattern = "出完";
            return analysis;
        }

        // 检查是否能形成顺子
        List<List<CardObj>> straights = findStraightsAbove(remainingCards, -1, remainingCards.size());
        if (!straights.isEmpty()) {
            analysis.estimatedTurns = 1;
            analysis.bestPattern = "顺子出完";
            return analysis;
        }

        // 检查是否能形成连对
        if (remainingCards.size() % 2 == 0) {
            List<List<CardObj>> consecutivePairs = findConsecutivePairsAbove(remainingCards, -1, remainingCards.size() / 2);
            if (!consecutivePairs.isEmpty()) {
                analysis.estimatedTurns = 1;
                analysis.bestPattern = "连对出完";
                return analysis;
            }
        }

        // 检查单次出完
        if (canPlayInOneTurn(remainingCards)) {
            analysis.estimatedTurns = 1;
            analysis.bestPattern = "一次性出完";
            return analysis;
        }

        // 估算手数
        analysis.estimatedTurns = estimateTurnsForRemaining(remainingCards, getValueCount(remainingCards));
        analysis.bestPattern = getBestPattern(remainingCards);

        return analysis;
    }


    /**
     * 检查是否能一次性出完
     */
    private static boolean canPlayInOneTurn(List<CardObj> cards) {
        int type = getPlayType(cards);
        return type != -1; // 如果能识别出牌型，就能一次性出完
    }

    /**
     * 估算剩余手牌需要的手数
     */
    private static int estimateTurnsForRemaining(List<CardObj> cards, Map<Integer, Integer> count) {
        int turns = 0;

        // 统计各种牌型
        int singles = 0;
        int pairs = 0;
        int trios = 0;
        int bombs = 0;

        for (int cardCount : count.values()) {
            switch (cardCount) {
                case 1:
                    singles++;
                    break;
                case 2:
                    pairs++;
                    break;
                case 3:
                    trios++;
                    break;
                case 4:
                    bombs++;
                    break;
            }
        }

        // 炸弹
        turns += bombs;

        // 三带
        int trioTurns = trios;
        if (trios > 0 && singles + pairs >= trios) {
            // 三带可以带牌
            trioTurns = trios;
        }
        turns += trioTurns;

        // 对子
        int pairTurns = pairs;
        turns += pairTurns;

        // 单牌（减去被三带带走的）
        int remainingSingles = Math.max(0, singles - trios);
        turns += remainingSingles;

        return Math.max(1, turns);
    }

    /**
     * 获取最佳剩余牌型
     */
    private static String getBestPattern(List<CardObj> cards) {
        if (cards.size() >= 5) {
            List<List<CardObj>> straights = findStraightsAbove(cards, -1, 5);
            if (!straights.isEmpty()) return "有顺子";

            List<List<CardObj>> consecutivePairs = findConsecutivePairsAbove(cards, -1, 2);
            if (!consecutivePairs.isEmpty()) return "有连对";
        }

        Map<Integer, Integer> count = getValueCount(cards);
        if (count.values().stream().anyMatch(c -> c >= 2)) {
            return "有对子";
        }

        return "多单牌";
    }


    /**
     * 选择最优带牌方案
     */
    private static CarryOption selectBestCarryOption(List<CarryOption> options) {
        return options.stream()
                .max(Comparator.comparingInt(option -> option.score))
                .orElse(null);
    }

    /**
     * 保守策略（当智能分析失败时使用）
     */
    private static List<CardObj> findConservativeCarryCards(List<CardObj> availableCards, int requiredCount) {
        List<CardObj> carryCards = new ArrayList<>();

        // 优先使用小对子
        List<Integer> smallPairs = getAvailableSmallPairs(availableCards);
        for (int pairValue : smallPairs) {
            if (carryCards.size() + 2 <= requiredCount) {
                List<CardObj> pair = availableCards.stream()
                        .filter(card -> card.cardMod == pairValue)
                        .limit(2)
                        .collect(Collectors.toList());
                if (pair.size() == 2) {
                    carryCards.addAll(pair);
                    availableCards.removeAll(pair);
                }
            }
        }

        // 然后使用小单牌
        if (carryCards.size() < requiredCount) {
            List<CardObj> singles = getAvailableSingles(availableCards).stream()
                    .filter(card -> card.cardMod <= 10)
                    .collect(Collectors.toList());
            for (CardObj single : singles) {
                if (carryCards.size() < requiredCount) {
                    carryCards.add(single);
                    availableCards.remove(single);
                }
            }
        }

        // 最后使用任意牌
        if (carryCards.size() < requiredCount) {
            List<CardObj> allCards = new ArrayList<>(availableCards);
            allCards.sort(Comparator.comparingInt(card -> card.cardMod));
            for (CardObj card : allCards) {
                if (carryCards.size() < requiredCount) {
                    carryCards.add(card);
                }
            }
        }

        return carryCards;
    }

    // 辅助类
    static class CarryOption {
        List<CardObj> carryCards;
        List<CardObj> remainingCards;
        int remainingTurns;
        String remainingPattern;
        int score;
    }

    static class RemainAnalysis {
        int estimatedTurns;
        String bestPattern;
    }


    // 辅助方法：获取当前可用的单牌
    private static List<CardObj> getAvailableSingles(List<CardObj> cards) {
        Map<Integer, Integer> count = getValueCount(cards);
        return cards.stream()
                .filter(card -> count.getOrDefault(card.cardMod, 0) == 1)
                .sorted(Comparator.comparingInt(card -> card.cardMod))
                .collect(Collectors.toList());
    }

    // 辅助方法：获取当前可用的小对子
    private static List<Integer> getAvailableSmallPairs(List<CardObj> cards) {
        Map<Integer, Integer> count = getValueCount(cards);
        return count.entrySet().stream()
                .filter(entry -> entry.getValue() == 2)
                .filter(entry -> entry.getKey() <= 10)
                .map(Map.Entry::getKey)
                .sorted()
                .collect(Collectors.toList());
    }

    // 辅助方法：获取当前所有对子
    private static List<Integer> getAllAvailablePairs(List<CardObj> cards) {
        Map<Integer, Integer> count = getValueCount(cards);
        return count.entrySet().stream()
                .filter(entry -> entry.getValue() >= 2)
                .map(Map.Entry::getKey)
                .sorted()
                .collect(Collectors.toList());
    }

    /**
     * 寻找能一次性或接近一次性出完的牌型 (7-9张专用)
     */
    private static List<CardObj> findQuickWinPlay(List<CardObj> handCards) {
        List<CardObj> sortedHand = new ArrayList<>(handCards);
        Collections.sort(sortedHand);
        Map<Integer, Integer> valueCount = getValueCount(handCards);

        List<CardObj> cardObjs = tryPlayTrioWithOne(handCards, valueCount);
        if (!cardObjs.isEmpty()) {
            System.out.println("7-9张专用  ++ 先出三带");
            return cardObjs;
        }

        List<CardObj> chainPair = findChainPair(handCards);
        if (!chainPair.isEmpty()) {
            System.out.println("7-9张专用  ++ 先出连对");
            return chainPair;
        }

        List<CardObj> play = tryPlayStraight(handCards);
        if (!play.isEmpty()) {
            System.out.println("7-9张专用  ++ 先出顺子");
            return play;
        }
        return findControlPlayForQuickWin(handCards);
    }

    private static List<CardObj> findChainPair(List<CardObj> handCards) {
        if (handCards.size() < 4) {
            return new ArrayList<>();
        }

        Map<Integer, Integer> valueCount = getValueCount(handCards);
        List<Integer> pairValues = valueCount.entrySet().stream()
                .filter(entry -> entry.getValue() >= 2)
                .map(Map.Entry::getKey)
                .filter(value -> value < 15)
                .sorted()
                .collect(Collectors.toList());

        if (pairValues.size() < 2) {
            return new ArrayList<>();
        }

        // 寻找所有连对
        List<List<Integer>> allChains = new ArrayList<>();
        List<Integer> currentChain = new ArrayList<>();

        for (int i = 0; i < pairValues.size(); i++) {
            if (currentChain.isEmpty()) {
                currentChain.add(pairValues.get(i));
            } else {
                int lastValue = currentChain.get(currentChain.size() - 1);
                int currentValue = pairValues.get(i);

                if (currentValue == lastValue + 1) {
                    currentChain.add(currentValue);
                } else {
                    if (currentChain.size() >= 2) {
                        allChains.add(new ArrayList<>(currentChain));
                    }
                    currentChain.clear();
                    currentChain.add(currentValue);
                }
            }
        }

        if (currentChain.size() >= 2) {
            allChains.add(new ArrayList<>(currentChain));
        }

        if (allChains.isEmpty()) {
            return new ArrayList<>();
        }

        // 优先选择最长的连对
        List<Integer> bestChain = allChains.stream()
                .max(Comparator.<List<Integer>>comparingInt(List::size))
                .orElse(allChains.get(0)); // 如果没有最长的，就取第一个找到的

        // 构建牌列表
        List<CardObj> result = new ArrayList<>();
        for (int value : bestChain) {
            result.addAll(getPairByValue(handCards, value));
        }

        return result;
    }


    private static List<CardObj> tryPlayStraight(List<CardObj> handCards) {
        final int MIN_STRAIGHT_VALUE = 3;
        final int MAX_STRAIGHT_VALUE = 14;

        List<Integer> distinctValues = handCards.stream()
                .map(c -> c.cardMod)
                .filter(value -> value >= MIN_STRAIGHT_VALUE && value <= MAX_STRAIGHT_VALUE)
                .distinct()
                .sorted()
                .collect(Collectors.toList());

        System.out.println("可用的顺子值: " + distinctValues);

        // 如果可用牌值少于5张，直接返回
        if (distinctValues.size() < 5) {
            return new ArrayList<>();
        }
        int maxPossibleLength = Math.min(distinctValues.size(), 12); // 最多12张

        for (int length = maxPossibleLength; length >= 5; length--) {
            for (int i = 0; i <= distinctValues.size() - length; i++) {
                if (isConsecutive(distinctValues, i, length)) {
                    List<Integer> straightValues = distinctValues.subList(i, i + length);
                    System.out.println("找到" + length + "张顺子: " + straightValues);
                    return buildStraight(handCards, straightValues);
                }
            }
        }

        return new ArrayList<>();
    }

    /**
     * 检查是否能一次性出完
     */
    private static List<CardObj> findOneShotPlay(List<CardObj> handCards) {
        int handSize = handCards.size();

        // 检查顺子
        if (handSize >= 5) {
            for (int len = handSize; len >= 5; len--) {
                List<List<CardObj>> straights = findStraightsAbove(handCards, -1, len);
                if (!straights.isEmpty()) {
                    // 正好等于手牌数量的顺子
                    for (List<CardObj> straight : straights) {
                        if (straight.size() == handSize) {
                            return straight;
                        }
                    }
                }
            }
        }

        // 检查连对
        if (handSize >= 4 && handSize % 2 == 0) {
            int pairCount = handSize / 2;
            List<List<CardObj>> consecutivePairs = findConsecutivePairsAbove(handCards, -1, pairCount);
            if (!consecutivePairs.isEmpty()) {
                return consecutivePairs.get(0);
            }
        }

        // 检查炸弹+单牌组合
        Map<Integer, Integer> valueCount = getValueCount(handCards);
        for (Map.Entry<Integer, Integer> entry : valueCount.entrySet()) {
            if (entry.getValue() == 4 && handSize == 6) {
                // 四带二
                List<CardObj> bomb = handCards.stream()
                        .filter(card -> card.cardMod == entry.getKey())
                        .limit(4)
                        .collect(Collectors.toList());

                List<CardObj> otherCards = handCards.stream()
                        .filter(card -> card.cardMod != entry.getKey())
                        .collect(Collectors.toList());

                if (otherCards.size() >= 2) {
                    List<CardObj> result = new ArrayList<>(bomb);
                    result.addAll(otherCards.subList(0, 2));
                    return result;
                }
            }
        }

        return new ArrayList<>();
    }

    /**
     * 寻找顺子组合出牌
     */
    private static List<CardObj> findStraightComboPlay(List<CardObj> handCards) {
        int handSize = handCards.size();

        // 尝试各种顺子长度
        for (int straightLen = 5; straightLen <= Math.min(8, handSize - 1); straightLen++) {
            List<List<CardObj>> straights = findStraightsAbove(handCards, -1, straightLen);

            for (List<CardObj> straight : straights) {
                List<CardObj> remainHand = removeCards(handCards, straight);
                int remainSize = remainHand.size();

                // 剩余牌很少，容易处理
                if (remainSize <= 3) {
                    // 检查剩余牌是否都是大牌或者能形成控制
                    boolean remainIsGood = isRemainHandGood(remainHand);
                    if (remainIsGood) {
                        System.out.println("顺子" + straightLen + "张 + 剩余" + remainSize + "张好牌");
                        return straight;
                    }
                }

                // 剩余牌能形成对子或三张
                if (remainSize == 2 || remainSize == 3) {
                    Map<Integer, Integer> remainCount = getValueCount(remainHand);
                    boolean isPairOrTrio = remainCount.values().stream().allMatch(count -> count == remainSize);
                    if (isPairOrTrio) {
                        System.out.println("顺子" + straightLen + "张 + 对子/三张");
                        return straight;
                    }
                }
            }
        }

        return new ArrayList<>();
    }

    /**
     * 寻找连对组合出牌
     */
    private static List<CardObj> findConsecutivePairComboPlay(List<CardObj> handCards) {
        int handSize = handCards.size();

        for (int pairCount = 2; pairCount <= 4; pairCount++) {
            int requiredCards = pairCount * 2;
            if (requiredCards > handSize) continue;

            List<List<CardObj>> consecutivePairs = findConsecutivePairsAbove(handCards, -1, pairCount);

            for (List<CardObj> pairs : consecutivePairs) {
                List<CardObj> remainHand = removeCards(handCards, pairs);
                int remainSize = remainHand.size();

                // 剩余牌处理逻辑
                if (remainSize <= 3 && isRemainHandGood(remainHand)) {
                    System.out.println(pairCount + "连对 + 剩余" + remainSize + "张好牌");
                    return pairs;
                }

                // 剩余牌能形成顺子
                if (remainSize >= 5) {
                    List<List<CardObj>> remainStraights = findStraightsAbove(remainHand, -1, remainSize);
                    if (!remainStraights.isEmpty()) {
                        System.out.println(pairCount + "连对 + " + remainSize + "顺子");
                        return pairs;
                    }
                }
            }
        }

        return new ArrayList<>();
    }

    /**
     * 寻找三带类组合出牌
     */
    private static List<CardObj> findTrioComboPlay(List<CardObj> handCards) {
        Map<Integer, Integer> valueCount = getValueCount(handCards);
        int handSize = handCards.size();

        // 查找三张
        List<Integer> trioValues = valueCount.entrySet().stream()
                .filter(entry -> entry.getValue() == 3)
                .map(Map.Entry::getKey)
                .collect(Collectors.toList());

        for (int trioValue : trioValues) {
            List<CardObj> trio = handCards.stream()
                    .filter(card -> card.cardMod == trioValue)
                    .limit(3)
                    .collect(Collectors.toList());

            List<CardObj> remainAfterTrio = removeCards(handCards, trio);


            // 三带二
            if (handSize == 5 && remainAfterTrio.size() == 2) {
                Map<Integer, Integer> remainCount = getValueCount(remainAfterTrio);
                if (remainCount.size() == 1) { // 是对子
                    List<CardObj> result = new ArrayList<>(trio);
                    result.addAll(remainAfterTrio);
                    return result;
                }
            }
        }

        return new ArrayList<>();
    }

    /**
     * 为快速出完寻找控制性出牌
     */
    private static List<CardObj> findControlPlayForQuickWin(List<CardObj> handCards) {
        return Collections.singletonList(findMediumCardForQuickWin(handCards));
    }

    /**
     * 检查剩余手牌质量
     */
    private static boolean isRemainHandGood(List<CardObj> remainHand) {
        if (remainHand.isEmpty()) return true;

        // 剩余都是大牌
        boolean allBigCards = remainHand.stream().allMatch(card -> card.cardMod >= 13);
        if (allBigCards) return true;

        // 剩余牌能形成对子或三张
        Map<Integer, Integer> remainCount = getValueCount(remainHand);
        if (remainCount.size() == 1) return true; // 全是同值牌

        // 剩余牌值接近，容易组合
        int maxValue = remainHand.stream().mapToInt(c -> c.cardMod).max().orElse(0);
        int minValue = remainHand.stream().mapToInt(c -> c.cardMod).min().orElse(0);
        if (maxValue - minValue <= 2) return true;

        return false;
    }


    private static List<CardObj> findControlPair(List<CardObj> handCards) {
        Map<Integer, Integer> valueCount = getValueCount(handCards);

        // 1. 先找出所有对子，按牌值分组
        List<Integer> allPairs = valueCount.entrySet().stream()
                .filter(entry -> entry.getValue() >= 2)
                .map(Map.Entry::getKey)
                .sorted()
                .collect(Collectors.toList());

        if (allPairs.isEmpty()) {
            return new ArrayList<>();
        }

        return getPairByValue(handCards, allPairs.get(0));
    }

    private static boolean hasControlAfterPlay(List<CardObj> handCards, int playPairValue, Map<Integer, Integer> valueCount) {
        // 模拟出掉这个对子后，是否还有控制牌
        Map<Integer, Integer> tempCount = new HashMap<>(valueCount);
        tempCount.put(playPairValue, tempCount.get(playPairValue) - 2);

        // 检查是否还有：
        // a) 更大的对子
        return tempCount.entrySet().stream()
                .anyMatch(entry -> entry.getValue() >= 2 && entry.getKey() > playPairValue);
    }


    private static List<CardObj> getPairByValue(List<CardObj> handCards, int value) {
        return handCards.stream()
                .filter(card -> card.cardMod == value)
                .limit(2)
                .collect(Collectors.toList());
    }

    /**
     * 为快速出完寻找中等牌值
     */
    private static CardObj findMediumCardForQuickWin(List<CardObj> handCards) {
        List<CardObj> sortedHand = new ArrayList<>(handCards);
        Collections.sort(sortedHand);


//        // 优先选择9-J之间的牌
//        List<CardObj> optimalCards = sortedHand.stream()
//                .filter(card -> card.cardMod >= 9 && card.cardMod <= 11)
//                .collect(Collectors.toList());
//
//        if (!optimalCards.isEmpty()) {
//            return optimalCards.get(optimalCards.size() / 2); // 取中间值
//        }
//
//        // 次选7-Q之间的牌
//        List<CardObj> fallbackCards = sortedHand.stream()
//                .filter(card -> card.cardMod >= 7 && card.cardMod <= 12)
//                .collect(Collectors.toList());
//
//        if (!fallbackCards.isEmpty()) {
//            return fallbackCards.get(fallbackCards.size() / 2);
//        }
//
        // 默认取中间位置的牌
        int middleIndex = sortedHand.size() / 2;
        return sortedHand.get(middleIndex);
    }


    private static List<CardObj> tryPlayTrioWithOne(List<CardObj> handCards, Map<Integer, Integer> valueCount) {
        System.out.println("三张牌型");
        // 先按牌值排序（从小到大）
        handCards.sort(Comparator.comparingInt(c -> c.cardMod));

        // 查找最小的三张
        for (CardObj card : handCards) {
            if (valueCount.getOrDefault(card.cardMod, 0) >= 3) {
                List<CardObj> trio = handCards.stream()
                        .filter(c -> c.cardMod == card.cardMod)
                        .limit(3)
                        .collect(Collectors.toList());

                // 寻找两张带牌，优先不破坏对子和顺子牌型
                List<CardObj> sideCards = findBestSideCardsForTrio(handCards, card.cardMod, valueCount);

                if (sideCards.size() >= 2) {
                    List<CardObj> result = new ArrayList<>(trio);
                    result.addAll(sideCards.subList(0, 2));
                    System.out.println("全是三张牌型" + result);

                    return result;
                }
            }
        }
        return new ArrayList<>();
    }

    private static List<CardObj> findBestSideCardsForTrio(List<CardObj> handCards, int trioValue,
                                                          Map<Integer, Integer> valueCount) {
        List<CardObj> candidateCards = new ArrayList<>();


        // 收集所有不是三张牌本身的牌，并且不破坏其他三张牌
        for (CardObj card : handCards) {
            if (card.cardMod != trioValue) {
                // 检查这张牌是否属于其他三张牌（不拆散其他三张）
                if (valueCount.getOrDefault(card.cardMod, 0) < 3) {
                    candidateCards.add(card);
                }
            }
        }


        // 按优先级选择带牌策略
        List<CardObj> bestChoice = new ArrayList<>();


        // 策略1：优先选择单张牌（不破坏对子和三张）
        List<CardObj> singleCards = findSingleCards(candidateCards, valueCount);
        if (singleCards.size() >= 2) {
            return singleCards.subList(0, Math.min(2, singleCards.size()));
        }

        // 策略2：选择最小的对子（如果只剩一个对子，拆开带）
        List<CardObj> pairCards = findSmallestPair(candidateCards, valueCount);
        if (!pairCards.isEmpty()) {
            if (pairCards.size() >= 2) {
                return pairCards.subList(0, 2); // 带整个对子
            } else {
                bestChoice.add(pairCards.get(0)); // 先带一张
            }
        }

        // 策略3：如果还不够，选择其他单张（仍然不破坏三张）
        for (CardObj card : candidateCards) {
            if (bestChoice.size() < 2 && !bestChoice.contains(card)) {
                // 再次确认不破坏三张牌
                if (valueCount.getOrDefault(card.cardMod, 0) < 3) {
                    bestChoice.add(card);
                }
            }
        }

        return bestChoice;
    }

    /**
     * 查找最小的对子（不破坏三张牌）
     */
    private static List<CardObj> findSmallestPair(List<CardObj> cards, Map<Integer, Integer> valueCount) {
        List<CardObj> pairCards = new ArrayList<>();

        // 找出最小的对子（且不属于三张）
        for (CardObj card : cards) {
            if (valueCount.getOrDefault(card.cardMod, 0) == 2) { // 严格等于2，不是三张
                List<CardObj> pair = cards.stream()
                        .filter(c -> c.cardMod == card.cardMod)
                        .limit(2)
                        .collect(Collectors.toList());

                // 如果这个对子还没被加入，且比当前选择更小
                if (pairCards.isEmpty() ||
                        (pair.size() >= 2 && pair.get(0).cardMod < pairCards.get(0).cardMod)) {
                    pairCards = pair;
                }
            }
        }

        return pairCards;
    }

    /**
     * 查找单张牌（不破坏三张牌）
     */
    private static List<CardObj> findSingleCards(List<CardObj> cards, Map<Integer, Integer> valueCount) {
        List<CardObj> singleCards = new ArrayList<>();

        // 找出真正的单张牌（没有其他同值的牌，且不属于三张）
        for (CardObj card : cards) {
            if (valueCount.getOrDefault(card.cardMod, 0) == 1) {
                singleCards.add(card);
            }
        }

        // 按牌值排序
        singleCards.sort(Comparator.comparingInt(c -> c.cardMod));
        return singleCards;
    }

    /**
     * 找最大单牌
     */
    private static CardObj findMaxCard(List<CardObj> handCards) {
        return handCards.stream()
                .max(Comparator.comparingInt(c -> c.cardMod))
                .orElse(handCards.get(0));
    }


    /**
     * 选择最佳首出牌（保护大牌）
     */
    private static List<CardObj> selectBestFirstPlayWithBigCardProtection(List<CardObj> handCards, HandAnalysis analysis) {
        List<PlayOptionWithRemain> candidates = new ArrayList<>();

        // 为每个可能的首出牌分析后续影响
        for (List<CardObj> play : analysis.allPossiblePlays) {
            int playType = getPlayType(play);

            // 首轮禁止出炸弹
            if (playType == Config.TYPE_ZHA) {
                System.out.println("首轮跳过炸弹: " + play);
                continue;
            }

            // 首轮禁止出包含过多大牌的牌型
            if (containsTooManyBigCardsInFirstRound(play)) {
                System.out.println("首轮跳过多大牌组合: " + play);
                continue;
            }

            List<CardObj> remainHand = removeCards(handCards, play);
            RemainHandAnalysis remainAnalysis = analyzeRemainHand(remainHand);

            PlayOption option = new PlayOption(play, playType);
            PlayOptionWithRemain optionWithRemain = new PlayOptionWithRemain(option, remainHand, remainAnalysis);

            // 基于整体牌型特征评分（修复炸弹评分）
            calculateFirstRoundScore(optionWithRemain, analysis, handCards);
            candidates.add(optionWithRemain);
        }

        // 选择最优候选
        return selectBestCandidate(candidates, analysis, handCards);
    }

    /**
     * 首轮专用评分（禁止炸弹和过大牌型）
     */
    private static void calculateFirstRoundScore(PlayOptionWithRemain option, HandAnalysis analysis, List<CardObj> originalHand) {
        int score = 0;
        int playType = option.type;

        // 1. 首轮绝对禁止炸弹
        if (playType == Config.TYPE_ZHA) {
            score -= 10000;
            option.totalScore = score;
            return;
        }

        // 2. 禁止拆炸弹
        if (isBreakingBomb(option.cards, originalHand)) {
            score -= 1000;
            option.totalScore = score;
            return;
        }

        // 3. 首轮限制大牌使用
        if (containsTooManyBigCardsInFirstRound(option.cards)) {
            score -= 500;
        }

        // 4. 根据牌型特征动态评分
        score += evaluateFirstRoundByHandStructure(option, analysis, originalHand);

        // 5. 剩余手牌质量
        score += option.analysis.remainScore;

        // 6. 出牌数量考虑
        score += Math.min(option.cards.size() * 5, 20); // 限制最大加分

        option.totalScore = score;
    }

    /**
     * 首轮大牌限制检查
     */
    private static boolean containsTooManyBigCardsInFirstRound(List<CardObj> cards) {
        long bigCardCount = cards.stream()
                .filter(card -> card.cardMod >= 10)
                .count();

        // 首轮限制：不能超过总牌数的1/3是大牌
        return bigCardCount >= (cards.size() + 2) / 3;
    }

    /**
     * 首轮专用结构评估
     */
    private static int evaluateFirstRoundByHandStructure(PlayOptionWithRemain option, HandAnalysis analysis, List<CardObj> originalHand) {
        int score = 0;
        int playType = option.type;
        int handSize = originalHand.size();

        // === 首轮核心策略：出小牌保留控制力 ===

        // 特征1: 多小单牌 → 优先出能带走小牌的牌型
        if (analysis.smallSingleCount >= 3) {
            if (playType == Config.TYPE_3_1 || playType == Config.TYPE_SHUNZI) {
                score += 25;
            }
            if (playType == Config.TYPE_DANPAI && isSmallCard(option.cards.get(0))) {
                score += 20; // 首轮出小单牌积极处理
            }
        }

        // 特征2: 长顺子/连对 → 优先出中等长度的组合
        if (analysis.maxStraightLength >= 6 && playType == Config.TYPE_SHUNZI) {
            int length = option.cards.size();
            if (length >= 5 && length <= 7) {
                score += 14; // 中等长度顺子优先
            }
        }

        if (analysis.maxConsecutivePairs >= 3 && playType == Config.TYPE_LIANDUI) {
            int pairCount = option.cards.size() / 2;
            if (pairCount >= 2 && pairCount <= 3) {
                score += 18; // 中等连对优先
            }
        }

        // 特征3: 首轮避免使用大牌（除非手牌很少）
        if (handSize > 6) {
            int maxPlayValue = option.cards.stream().mapToInt(c -> c.cardMod).max().orElse(0);
            if (maxPlayValue >= 14) { // A, 2
                score -= 15;
            } else if (maxPlayValue >= 13) { // K
                score -= 8;
            }
        }

        // 特征4: 对子多 → 优先出小对子
        if (analysis.pairCount >= 4 && playType == Config.TYPE_DUIZI) {
            int maxValue = option.cards.stream().mapToInt(c -> c.cardMod).max().orElse(0);
            if (maxValue <= 10) { // 小对子加分
                score += 15;
            }
        }


        // 策略1: 优先处理难以组合的牌
        if (playType == Config.TYPE_DANPAI && isSmallCard(option.cards.get(0))) {
            score += 10; // 首轮积极出小单牌
        }


        if (playType == Config.TYPE_3_1) {
            // 检查三带一是否带的是小牌
            CardObj singleCard = findSingleCardInTrioWithOne(option.cards);
            if (singleCard != null && isSmallCard(singleCard)) {
                score += 15; // 三带小牌优先
            }
        }

        return score;
    }

    /**
     * 在三带一中找到单牌
     */
    private static CardObj findSingleCardInTrioWithOne(List<CardObj> cards) {
        if (cards.size() != 4) return null;

        Map<Integer, List<CardObj>> groups = groupByValue(cards);
        for (Map.Entry<Integer, List<CardObj>> entry : groups.entrySet()) {
            if (entry.getValue().size() == 1) {
                return entry.getValue().get(0);
            }
        }
        return null;
    }

    /**
     * 选择最佳候选（首轮专用）
     */
    private static List<CardObj> selectBestCandidate(List<PlayOptionWithRemain> candidates, HandAnalysis analysis, List<CardObj> originalHand) {
        // 过滤掉无效选项
        List<PlayOptionWithRemain> validCandidates = candidates.stream()
                .filter(opt -> opt.totalScore > -500 && !isBomb(opt.type))
                .collect(Collectors.toList());

        if (validCandidates.isEmpty()) {
            // 没有合适选择时，出最小单牌
            return Arrays.asList(findMediumCardForFirstRound(originalHand));
        }

        // 按分数排序
        validCandidates.sort((a, b) -> Integer.compare(b.totalScore, a.totalScore));

        // 输出前3个候选用于调试
        System.out.println("=== 首轮候选分析 ===");
        for (int i = 0; i < Math.min(3, validCandidates.size()); i++) {
            PlayOptionWithRemain opt = validCandidates.get(i);
            System.out.println("候选" + (i + 1) + ": " + opt.cards + " 类型:" + opt.type + " 分数:" + opt.totalScore);
        }

        return validCandidates.get(0).cards;
    }

    private static CardObj findMediumCardForFirstRound(List<CardObj> handCards) {
        List<CardObj> sortedHand = new ArrayList<>(handCards);
        Collections.sort(sortedHand);

        // 优先选择8-Q之间的牌（中等牌值）
        List<CardObj> mediumCards = sortedHand.stream()
                .filter(card -> card.cardMod >= 8 && card.cardMod <= 12) // 8到Q
                .collect(Collectors.toList());

        if (!mediumCards.isEmpty()) {
            // 取中等牌中最小的
            return mediumCards.get(0);
        }

        // 如果没有8-Q的牌，选择7-K之间的牌
        List<CardObj> fallbackCards = sortedHand.stream()
                .filter(card -> card.cardMod >= 7 && card.cardMod <= 13) // 7到K
                .collect(Collectors.toList());

        if (!fallbackCards.isEmpty()) {
            return fallbackCards.get(0);
        }

        // 实在没有合适的中等牌，选择中间位置的牌
        int middleIndex = sortedHand.size() / 2;
        return sortedHand.get(middleIndex);
    }

    private static CardObj findSmallestCard(List<CardObj> handCards) {
        return handCards.stream()
                .min(Comparator.comparingInt(c -> c.cardMod))
                .orElse(handCards.get(0));
    }

    /**
     * 检查是否为炸弹
     */
    private static boolean isBomb(int playType) {
        return playType == Config.TYPE_ZHA;
    }

    /**
     * 收集所有可能的首出牌（排除炸弹）
     */
    private static List<List<CardObj>> collectAllPossibleFirstPlays(List<CardObj> handCards) {
        List<List<CardObj>> allPlays = new ArrayList<>();

        // 单牌（限制大牌）
        allPlays.addAll(findSinglesAbove(handCards, -1).stream()
                .filter(play -> play.get(0).cardMod <= 12) // 首轮不出K以上的单牌
                .collect(Collectors.toList()));

        // 对子
        allPlays.addAll(findPairsAbove(handCards, -1));

        // 顺子 (5-8张)
        for (int len = 5; len <= 8; len++) {
            allPlays.addAll(findStraightsAbove(handCards, -1, len));
        }

        // 连对 (2-4连对)
        for (int pairCount = 2; pairCount <= 4; pairCount++) {
            allPlays.addAll(findConsecutivePairsAbove(handCards, -1, pairCount));
        }

        // 三带一
        allPlays.addAll(findTrioWithOneAbove(handCards, -1));


        return allPlays;
    }


    /**
     * 基于整体牌型特征评分（保护大牌）
     */
    private static void calculateStructuralScoreWithBigCardProtection(PlayOptionWithRemain option,
                                                                      HandAnalysis analysis, List<CardObj> originalHand) {
        int score = 0;

        // 1. 禁止拆炸弹
        if (isBreakingBomb(option.cards, originalHand)) {
            score -= 1000;
            option.totalScore = score;
            return;
        }

        // 2. 修复：保护大牌扣分机制
        score -= calculateBigCardPenalty(option.cards, originalHand);

        // 3. 根据牌型特征动态评分
        score += evaluateByHandStructureWithBigCardProtection(option, analysis, originalHand);

        // 4. 剩余手牌质量
        score += option.analysis.remainScore;

        // 5. 出牌数量考虑
        score += option.cards.size() * 8;

        option.totalScore = score;
    }

    /**
     * 计算大牌惩罚分数（出大牌扣分）
     */
    private static int calculateBigCardPenalty(List<CardObj> playCards, List<CardObj> originalHand) {
        int penalty = 0;

        // 统计手牌中的大牌数量
        long originalBigCards = originalHand.stream()
                .filter(card -> card.cardMod >= 13) // K, A, 2
                .count();

        // 统计出牌中的大牌数量
        long playBigCards = playCards.stream()
                .filter(card -> card.cardMod >= 13)
                .count();

        // 如果出牌中包含大牌，根据比例扣分
        if (playBigCards > 0) {
            double bigCardRatio = (double) playBigCards / playCards.size();

            // 大牌比例越高，扣分越多
            penalty += (int) (bigCardRatio * 50);

            // 如果手牌中大牌不多，扣分更重
            if (originalBigCards <= 3) {
                penalty += 30;
            }

            // 特别保护2(A)和A(K)
            for (CardObj card : playCards) {
                if (card.cardMod == 15) { // 2
                    penalty += 25;
                } else if (card.cardMod == 14) { // A
                    penalty += 15;
                } else if (card.cardMod == 13) { // K
                    penalty += 10;
                }
            }
        }

        return penalty;
    }

    /**
     * 根据手牌结构特征评估（保护大牌）
     */
    private static int evaluateByHandStructureWithBigCardProtection(PlayOptionWithRemain option,
                                                                    HandAnalysis analysis, List<CardObj> originalHand) {
        int score = 0;
        int playType = option.type;
        int handSize = originalHand.size();

        // === 关键修复：手牌很多时的保守策略 ===
        if (handSize > 10) {
            // 手牌多时，优先出小牌，保护大牌
            if (playType == Config.TYPE_DANPAI) {
                CardObj card = option.cards.get(0);
                if (card.cardMod <= 10) { // 10及以下的小牌
                    score += 20;
                } else if (card.cardMod >= 13) { // K以上的大牌
                    score -= 25; // 大牌扣分
                }
            }

            // 手牌多时优先出顺子、连对等组合牌
            if (playType == Config.TYPE_SHUNZI || playType == Config.TYPE_LIANDUI) {
                // 检查顺子/连对中是否包含大牌
                boolean containsBigCard = option.cards.stream().anyMatch(card -> card.cardMod >= 13);
                if (!containsBigCard) {
                    score += 35; // 不含大牌的顺子/连对大幅加分
                } else {
                    score += 15; // 含大牌的顺子/连对适当加分
                }
            }

            // 手牌多时避免首出对子（容易被压）
            if (playType == Config.TYPE_DUIZI) {
                int maxValue = option.cards.stream().mapToInt(c -> c.cardMod).max().orElse(0);
                if (maxValue >= 12) { // Q以上的对子
                    score -= 20;
                }
            }
        }

        // === 手牌较少时的激进策略 ===
        if (handSize <= 6) {
            if (handSize <= 3) {
                // 手牌很少时，优先出最大的牌夺取出牌权
                if (playType == Config.TYPE_DANPAI) {
                    CardObj card = option.cards.get(0);
                    if (card.cardMod >= 13) { // K, A, 2
                        score += 50; // 大单牌大幅加分
                    }
                }
                // 避免出小对子
                if (playType == Config.TYPE_DUIZI) {
                    int maxValue = option.cards.stream().mapToInt(c -> c.cardMod).max().orElse(0);
                    if (maxValue < 10) { // 小对子扣分
                        score -= 30;
                    }
                }
            }

            // 手牌较少时，优先出能一次出完或接近出完的牌型
            if (option.cards.size() == handSize) {
                score += 80; // 能一次出完大幅加分
            } else if (option.cards.size() >= handSize - 2) {
                score += 40; // 接近出完加分
            }
        }

        // 特征1: 小单牌多 → 优先出能带走小牌的牌型
        if (analysis.smallSingleCount >= 3) {
            if (playType == Config.TYPE_3_1 || playType == Config.TYPE_SHUNZI) {
                score += 30;
            }
            if (playType == Config.TYPE_DANPAI && isSmallCard(option.cards.get(0))) {
                score += 15;
            }
        }

        // 特征2: 连对长 → 优先出连对
        if (analysis.maxConsecutivePairs >= 3) {
            if (playType == Config.TYPE_LIANDUI) {
                score += 25;
            }
        }

        // 特征3: 大牌多 → 可以出控制力强的牌型
        if (analysis.bigCardCount >= 2) {
            if (playType == Config.TYPE_LIANDUI || playType == Config.TYPE_SHUNZI) {
                score += 15;
            }
        }

        // 特征4: 对子多 → 优先出对子或连对
        if (analysis.pairCount >= 4) {
            if (playType == Config.TYPE_DUIZI || playType == Config.TYPE_LIANDUI) {
                score += 20;
            }
        }

        // 特征5: 避免首出带大牌的牌型（除非手牌很少）
        if (containsBigCards(option.cards) && analysis.smallSingleCount > 0 && handSize > 6) {
            score -= 25;
        }

        // === 新增：出牌控制力评估 ===
        score += evaluatePlayControl(option, originalHand);

        return score;
    }


    /**
     * 手牌分析类
     */
    static class HandAnalysis {
        Map<String, Object> features = new HashMap<>();
        List<List<CardObj>> allPossiblePlays = new ArrayList<>();
        Map<Integer, Integer> valueCount;

        // 关键特征
        int smallSingleCount;      // 小单牌数量(3-8)
        int bigCardCount;          // 大牌数量(2,A,K)
        int pairCount;             // 对子数量
        int trioCount;             // 三张数量
        int bombCount;             // 炸弹数量
        int maxStraightLength;     // 最长顺子
        int maxConsecutivePairs;   // 最长连对
        boolean hasControlCards;   // 是否有控制牌
    }

    /**
     * 评估出牌控制力
     */
    private static int evaluatePlayControl(PlayOptionWithRemain option, List<CardObj> originalHand) {
        int score = 0;
        int playType = option.type;

        // 计算出牌中的最大牌值
        int maxPlayValue = option.cards.stream().mapToInt(c -> c.cardMod).max().orElse(0);

        // 单牌：大牌有控制力
        if (playType == Config.TYPE_DANPAI) {
            if (maxPlayValue >= 15) score += 40; // 2
            else if (maxPlayValue >= 14) score += 30; // A
            else if (maxPlayValue >= 13) score += 20; // K
            else if (maxPlayValue <= 8) score -= 10; // 小单牌控制力差
        }

        // 对子：大对子有控制力
        if (playType == Config.TYPE_DUIZI) {
            if (maxPlayValue >= 13) score += 25; // K对以上
            else if (maxPlayValue <= 9) score -= 15; // 小对子容易被压
        }

        // 顺子、连对：长度越长越难被压
        if (playType == Config.TYPE_SHUNZI || playType == Config.TYPE_LIANDUI) {
            score += option.cards.size() * 2;
        }

        // 炸弹：绝对控制力
        if (playType == Config.TYPE_ZHA) {
            score += 60;
        }

        return score;
    }

    /**
     * 找到最好的单牌出牌
     */
    private static List<CardObj> findBestCardToPlay(List<CardObj> handCards, Map<Integer, List<Integer>> seatRemainHistory) {
        Map<Integer, Integer> otherSeatsLastRemain = getOtherSeatsLastRemain(HuNanPaoDeKuai.seat, seatRemainHistory);
        boolean hasAnyEqualOne = otherSeatsLastRemain.values().stream().anyMatch(value -> value == 1);
        if (hasAnyEqualOne) {
            // 优先考虑能出完的牌型：三带、连对、顺子
            System.out.println("检测到对手只剩一张牌，优先查找能出完的牌型");

            // 检查三带（三带一或三带对）
            List<CardObj> trioPlay = findQuickWinPlay(handCards);
            if (!trioPlay.isEmpty()) {
                System.out.println("找到能出完的三带牌型: " + trioPlay);
                return trioPlay;
            }

            // 检查连对
            List<CardObj> consecutivePairs = findChainPair(handCards);
            if (!consecutivePairs.isEmpty()) {
                System.out.println("找到能出完的连对牌型: " + consecutivePairs);
                return consecutivePairs;
            }

            // 如果没有能出完的牌型，再出对子压制
            System.out.println("未找到能出完的牌型，优先出对子压制");
            List<CardObj> pair = findAnyPair(handCards);
            if (pair != null && pair.size() == 2) {
                System.out.println("推荐出牌: " + pair + " (对子压制)");
                return pair;
            }
        }
        return new ArrayList<>();
    }

    /**
     * 在手牌中找任意对子
     */
    private static List<CardObj> findAnyPair(List<CardObj> handCards) {
        Map<Integer, List<CardObj>> valueGroups = groupByValue(handCards);
        return valueGroups.entrySet().stream()
                .filter(entry -> entry.getValue().size() >= 2)
                .min(Comparator.comparingInt(Map.Entry::getKey))
                .map(entry -> entry.getValue().subList(0, 2))
                .orElse(new ArrayList<>());
    }


    // 辅助方法
    private static int countSmallSingles(List<CardObj> handCards, Map<Integer, Integer> valueCount) {
        return (int) valueCount.entrySet().stream()
                .filter(entry -> entry.getValue() == 1 && entry.getKey() >= 3 && entry.getKey() <= 8)
                .count();
    }

    private static int countBigCards(Map<Integer, Integer> valueCount) {
        return (int) valueCount.keySet().stream()
                .filter(value -> value >= 13) // K, A, 2
                .count();
    }

    private static boolean isSmallCard(CardObj card) {
        return card.cardMod >= 3 && card.cardMod <= 8;
    }

    private static boolean containsBigCards(List<CardObj> cards) {
        return cards.stream().anyMatch(card -> card.cardMod >= 13);
    }

    /**
     * 检查是否拆炸弹
     */
    private static boolean isBreakingBomb(List<CardObj> playCards, List<CardObj> originalHand) {
        Map<Integer, Integer> originalCount = getValueCount(originalHand);
        Map<Integer, Integer> playCount = getValueCount(playCards);

        for (Map.Entry<Integer, Integer> entry : playCount.entrySet()) {
            int cardValue = entry.getKey();
            int playCountForValue = entry.getValue();
            int originalCountForValue = originalCount.getOrDefault(cardValue, 0);

            // 如果原始有4张，但只出了3张或更少，就是拆炸弹
            if (originalCountForValue >= 4 && playCountForValue < 4) {
                return true;
            }
        }
        return false;
    }

    /**
     * 智能响应出牌（考虑出牌后手牌）
     */
    private static List<CardObj> intelligentResponsePlayWithRemainConsideration(List<CardObj> handCards, int minCard,
                                                                                int len, List<CardObj> opponentCards, int type) {
        if (handCards.isEmpty()) return new ArrayList<>();

        // 查找能压住对手的牌，并评估出牌后的手牌
        List<PlayOptionWithRemain> validOptions = findValidResponseOptionsWithRemain(handCards, minCard, len, type);

        // 选择最优出牌
        PlayOptionWithRemain bestOption = selectBestOptionWithRemain(validOptions, handCards.size(), false);

        System.out.println("响应出牌选择: " + bestOption.cards + ", 类型: " + bestOption.type +
                ", 综合分数: " + bestOption.totalScore + ", 预计手数: " + bestOption.getEstimatedTurns());
        return bestOption.cards;
    }

    /**
     * 分析所有出牌选项（考虑出牌后手牌）
     */
    private static List<PlayOptionWithRemain> analyzeAllPlayOptionsWithRemain(List<CardObj> handCards) {
        List<PlayOptionWithRemain> options = new ArrayList<>();

        // 分析各种牌型
        addOptionsWithRemainAnalysis(options, analyzeSingles(handCards), handCards);
        addOptionsWithRemainAnalysis(options, analyzePairs(handCards), handCards);
        addOptionsWithRemainAnalysis(options, analyzeStraights(handCards), handCards);
        addOptionsWithRemainAnalysis(options, analyzeConsecutivePairs(handCards), handCards);
        addOptionsWithRemainAnalysis(options, analyzeBombs(handCards), handCards);
        addOptionsWithRemainAnalysis(options, analyzeTrioWithOnes(handCards), handCards);
        addOptionsWithRemainAnalysis(options, analyzeTrioWithPairs(handCards), handCards);
        addOptionsWithRemainAnalysis(options, analyzeFourWithTwos(handCards), handCards);

        return options;
    }

    /**
     * 添加选项并进行出牌后手牌分析
     */
    private static void addOptionsWithRemainAnalysis(List<PlayOptionWithRemain> target,
                                                     List<PlayOption> source,
                                                     List<CardObj> originalHand) {
        for (PlayOption option : source) {
            // 计算出牌后的手牌
            List<CardObj> remainHand = calculateRemainHand(originalHand, option.cards);

            // 分析出牌后手牌的质量
            RemainHandAnalysis analysis = analyzeRemainHand(remainHand);

            // 创建包含出牌后分析的选项
            PlayOptionWithRemain optionWithRemain = new PlayOptionWithRemain(option, remainHand, analysis);

            // 计算综合分数
            calculateTotalScore(optionWithRemain, originalHand.size());

            target.add(optionWithRemain);
        }
    }

    /**
     * 计算出牌后的手牌
     */
    private static List<CardObj> calculateRemainHand(List<CardObj> originalHand, List<CardObj> playCards) {
        List<CardObj> remainHand = new ArrayList<>(originalHand);

        // 从手牌中移除打出的牌
        for (CardObj playCard : playCards) {
            Iterator<CardObj> iterator = remainHand.iterator();
            while (iterator.hasNext()) {
                CardObj card = iterator.next();
                if (card.cardMod == playCard.cardMod && card.card == playCard.card) {
                    iterator.remove();
                    break;
                }
            }
        }

        return remainHand;
    }

    /**
     * 分析出牌后手牌质量
     */
    private static RemainHandAnalysis analyzeRemainHand(List<CardObj> remainHand) {
        RemainHandAnalysis analysis = new RemainHandAnalysis();

        if (remainHand.isEmpty()) {
            analysis.isWin = true;
            analysis.estimatedTurns = 0;
            analysis.remainScore = 1000; // 出完牌的最高分
            return analysis;
        }

        // 分析剩余手牌的各种特征
        analysis.cardCount = remainHand.size();
        analysis.maxCardValue = remainHand.stream().mapToInt(c -> c.cardMod).max().orElse(0);
        analysis.minCardValue = remainHand.stream().mapToInt(c -> c.cardMod).min().orElse(0);
        analysis.avgCardValue = remainHand.stream().mapToInt(c -> c.cardMod).average().orElse(0);

        // 统计剩余牌型组合
        Map<Integer, Integer> valueCount = getValueCount(remainHand);
        analysis.singleCount = (int) valueCount.values().stream().filter(count -> count == 1).count();
        analysis.pairCount = (int) valueCount.values().stream().filter(count -> count == 2).count();
        analysis.trioCount = (int) valueCount.values().stream().filter(count -> count >= 3).count();

        // 新增：统计剩余大牌数量
        analysis.bigCardRemain = (int) remainHand.stream()
                .filter(card -> card.cardMod >= 13)
                .count();

        // 分析顺子潜力
        analysis.straightPotential = analyzeStraightPotential(remainHand);

        // 分析连对潜力
        analysis.consecutivePairPotential = analyzeConsecutivePairPotential(remainHand);

        // 估算出完剩余牌需要的手数
        analysis.estimatedTurns = estimateRemainingTurns(remainHand, valueCount);

        // 计算剩余手牌分数
        analysis.remainScore = calculateRemainHandScore(analysis);

        return analysis;
    }

    /**
     * 估算剩余手牌需要的手数
     */
    private static int estimateRemainingTurns(List<CardObj> remainHand, Map<Integer, Integer> valueCount) {
        if (remainHand.isEmpty()) return 0;

        int estimatedTurns = 0;

        // 统计各种牌型组合
        int singleCount = 0;
        int pairCount = 0;
        int trioCount = 0;
        int bombCount = 0;

        for (int count : valueCount.values()) {
            switch (count) {
                case 1:
                    singleCount++;
                    break;
                case 2:
                    pairCount++;
                    break;
                case 3:
                    trioCount++;
                    break;
                case 4:
                    bombCount++;
                    break;
            }
        }

        // 估算手数（简化算法）
        // 炸弹可以一次出完
        estimatedTurns += bombCount;

        // 三张可以带牌或单独出
        estimatedTurns += Math.max(trioCount, singleCount + pairCount - trioCount);

        // 对子和单牌
        estimatedTurns += Math.max(pairCount, singleCount - trioCount);

        // 确保至少1手
        estimatedTurns = Math.max(1, estimatedTurns);

        return estimatedTurns;
    }

    /**
     * 分析顺子潜力
     */
    private static int analyzeStraightPotential(List<CardObj> remainHand) {
        List<Integer> distinctValues = remainHand.stream()
                .map(c -> c.cardMod)
                .filter(value -> value != 15) // 排除2
                .distinct()
                .sorted()
                .collect(Collectors.toList());

        if (distinctValues.size() < 5) return 0;

        int maxStraightLength = 1;
        int currentLength = 1;

        for (int i = 1; i < distinctValues.size(); i++) {
            if (distinctValues.get(i) - distinctValues.get(i - 1) == 1) {
                currentLength++;
                maxStraightLength = Math.max(maxStraightLength, currentLength);
            } else {
                currentLength = 1;
            }
        }

        return maxStraightLength >= 5 ? maxStraightLength : 0;
    }

    /**
     * 分析连对潜力
     */
    private static int analyzeConsecutivePairPotential(List<CardObj> remainHand) {
        Map<Integer, Integer> valueCount = getValueCount(remainHand);
        List<Integer> pairValues = valueCount.entrySet().stream()
                .filter(entry -> entry.getValue() >= 2)
                .map(Map.Entry::getKey)
                .sorted()
                .collect(Collectors.toList());

        if (pairValues.size() < 2) return 0;

        int maxConsecutivePairs = 1;
        int currentConsecutive = 1;

        for (int i = 1; i < pairValues.size(); i++) {
            if (pairValues.get(i) - pairValues.get(i - 1) == 1) {
                currentConsecutive++;
                maxConsecutivePairs = Math.max(maxConsecutivePairs, currentConsecutive);
            } else {
                currentConsecutive = 1;
            }
        }

        return maxConsecutivePairs >= 2 ? maxConsecutivePairs : 0;
    }

    /**
     * 计算剩余手牌分数
     */
    private static int calculateRemainHandScore(RemainHandAnalysis analysis) {
        int score = 0;

        // 牌数越少分数越高
        score += (20 - analysis.cardCount) * 5;

        // 预计手数越少分数越高
        score += (10 - analysis.estimatedTurns) * 8;

        // 剩余大牌数量加分（保护大牌策略）
        score += analysis.bigCardRemain * 12;

        // 有顺子潜力加分
        if (analysis.straightPotential >= 5) {
            score += analysis.straightPotential * 3;
        }

        // 有连对潜力加分
        if (analysis.consecutivePairPotential >= 2) {
            score += analysis.consecutivePairPotential * 4;
        }

        // 单牌少加分
        score -= analysis.singleCount * 2;

        // 对子多加分（容易组合）
        score += analysis.pairCount * 3;

        // 三张多加分
        score += analysis.trioCount * 5;

        return Math.max(0, score);
    }

    /**
     * 计算综合分数
     */
    private static void calculateTotalScore(PlayOptionWithRemain option, int originalHandSize) {
        int totalScore = 0;

        // 当前出牌的基础分数
        totalScore += getBaseTypeScore(option.type);

        // 出牌后手牌质量分数（权重较高）
        totalScore += option.analysis.remainScore * 2;

        // 预计手数考虑
        totalScore -= option.analysis.estimatedTurns * 10;

        // 出牌大小考虑（优先出小牌）
        int maxPlayValue = option.cards.stream().mapToInt(c -> c.cardMod).max().orElse(0);
        totalScore -= maxPlayValue;

        // 首轮出牌特殊考虑
        if (originalHandSize == option.analysis.cardCount + option.cards.size()) { // 首轮
            // 首轮避免出太大的牌
            if (maxPlayValue > 12) {
                totalScore -= 15; // 加大扣分
            }
            // 首轮优先出能形成控制的牌型
            if (option.type == Config.TYPE_SHUNZI || option.type == Config.TYPE_LIANDUI) {
                totalScore += 15;
            }
        }

        // 炸弹特殊处理
        if (option.type == Config.TYPE_ZHA) {
            if (option.analysis.cardCount > 8) { // 手牌多时慎用炸弹
                totalScore -= 30; // 加大扣分
            } else { // 手牌少时积极用炸弹
                totalScore += 25;
            }
        }

        option.totalScore = totalScore;
    }

    /**
     * 选择最优选项（考虑出牌后手牌）
     */
    private static PlayOptionWithRemain selectBestOptionWithRemain(List<PlayOptionWithRemain> options,
                                                                   int handSize, boolean isFirstPlay) {
        return options.stream()
                .max(Comparator.comparingInt(option -> option.totalScore))
                .orElse(options.isEmpty() ? null : options.get(0));
    }

    /**
     * 查找有效的响应选项（考虑出牌后手牌）
     */
    private static List<PlayOptionWithRemain> findValidResponseOptionsWithRemain(List<CardObj> handCards,
                                                                                 int minCard, int len, int type) {
        List<PlayOptionWithRemain> validOptions = new ArrayList<>();
        List<PlayOption> basicOptions = new ArrayList<>();

//        boolean isFewCards = handCards.size() <= 15;

        // 根据牌型查找基本选项
        switch (type) {
            case Config.TYPE_DANPAI:
//                if (isFewCards) {
//                    // 手牌少时，用非炸弹牌找单牌
//                    basicOptions.addAll(findSinglesAboveWithoutBreakingBomb(handCards, minCard).stream()
//                            .map(cards -> new PlayOption(cards, Config.TYPE_DANPAI))
//                            .collect(Collectors.toList()));
//                } else {
                basicOptions.addAll(findSinglesAbove(handCards, minCard).stream()
                        .map(cards -> new PlayOption(cards, Config.TYPE_DANPAI))
                        .collect(Collectors.toList()));
//                }
                break;
            case Config.TYPE_DUIZI:
//                if (isFewCards) {
//                    basicOptions.addAll(findPairsAboveWithoutBreakingBomb(handCards, minCard).stream()
//                            .map(cards -> new PlayOption(cards, Config.TYPE_DUIZI))
//                            .collect(Collectors.toList()));
//                } else {
                basicOptions.addAll(findPairsAbove(handCards, minCard).stream()
                        .map(cards -> new PlayOption(cards, Config.TYPE_DUIZI))
                        .collect(Collectors.toList()));
//                }
                break;
            case Config.TYPE_SHUNZI:
//                if (isFewCards) {
//                    basicOptions.addAll(findStraightsAboveWithoutBreakingBomb(handCards, minCard, len).stream()
//                            .map(cards -> new PlayOption(cards, Config.TYPE_SHUNZI))
//                            .collect(Collectors.toList()));
//                } else {
                basicOptions.addAll(findStraightsAbove(handCards, minCard, len).stream()
                        .map(cards -> new PlayOption(cards, Config.TYPE_SHUNZI))
                        .collect(Collectors.toList()));
//                }
                break;
            case Config.TYPE_LIANDUI:
//                if (isFewCards) {
//                    basicOptions.addAll(findConsecutivePairsAboveWithoutBreakingBomb(handCards, minCard, len).stream()
//                            .map(cards -> new PlayOption(cards, Config.TYPE_LIANDUI))
//                            .collect(Collectors.toList()));
//                } else {
                basicOptions.addAll(findConsecutivePairsAbove(handCards, minCard, len).stream()
                        .map(cards -> new PlayOption(cards, Config.TYPE_LIANDUI))
                        .collect(Collectors.toList()));
//                }
                break;
            case Config.TYPE_3_1:
//                if (isFewCards) {
//                    basicOptions.addAll(findTrioWithOneAboveWithoutBreakingBomb(handCards, minCard).stream()
//                            .map(cards -> new PlayOption(cards, Config.TYPE_3_1))
//                            .collect(Collectors.toList()));
//                } else {
                basicOptions.addAll(findTrioWithOneAbove(handCards, minCard).stream()
                        .map(cards -> new PlayOption(cards, Config.TYPE_3_1))
                        .collect(Collectors.toList()));
//                }
                break;

            case Config.TYPE_FEIJI:


                break;

            case Config.TYPE_ZHA:
                // 炸弹本身不需要特殊处理，因为不会拆炸弹
                basicOptions.addAll(findBombsAbove(handCards, minCard).stream()
                        .map(cards -> new PlayOption(cards, Config.TYPE_ZHA))
                        .collect(Collectors.toList()));
                break;
        }

        // 如果正常牌型找不到，尝试用炸弹压
        if (basicOptions.isEmpty() && type != Config.TYPE_ZHA) {
            List<PlayOption> bombOptions = findBombsAbove(handCards, -1).stream()
                    .map(cards -> new PlayOption(cards, Config.TYPE_ZHA))
                    .collect(Collectors.toList());

//            if (isFewCards) {
            // 手牌少时，只有在确实没有其他选择时才用炸弹
//            if (bombOptions.isEmpty()) {
//            } else {
//                // 有炸弹，但手牌少时要特别标记
//                basicOptions.addAll(bombOptions);
//            }
////            } else {
            // 手牌多时正常使用炸弹
            basicOptions.addAll(bombOptions);
        }
        // 为每个基本选项添加出牌后分析
        addOptionsWithRemainAnalysis(validOptions, basicOptions, handCards);

        return validOptions;
    }


    private static List<List<CardObj>> findTrioWithOneAboveWithoutBreakingBomb(List<CardObj> handCards, int minCard) {
        Map<Integer, Integer> valueCount = getValueCount(handCards);
        Set<Integer> bombs = findBombValues(valueCount);

        List<List<CardObj>> result = new ArrayList<>();

        // 从手牌中完全移除炸弹牌
        List<CardObj> cardsWithoutBombs = handCards.stream()
                .filter(card -> !bombs.contains(card.cardMod))
                .collect(Collectors.toList());

        // 用非炸弹牌重新计算牌值数量
        Map<Integer, Integer> valueCountWithoutBombs = getValueCount(cardsWithoutBombs);

        // 找三张（在非炸弹牌中找）
        List<Integer> trioCandidates = valueCountWithoutBombs.entrySet().stream()
                .filter(entry -> entry.getValue() >= 3 && entry.getKey() > minCard)
                .map(Map.Entry::getKey)
                .collect(Collectors.toList());

        for (int trioValue : trioCandidates) {
            // 在非炸弹牌中找两张带牌
            List<CardObj> carryCards = findTwoCarryCardsWithoutBombs(cardsWithoutBombs, trioValue);

            if (carryCards.size() == 2) {
                List<CardObj> play = cardsWithoutBombs.stream()
                        .filter(card -> card.cardMod == trioValue)
                        .limit(3).collect(Collectors.toList());
                play.addAll(carryCards);
                result.add(play);
            }
        }

        return result;
    }

    /**
     * 在非炸弹牌中找两张带牌
     */
    private static List<CardObj> findTwoCarryCardsWithoutBombs(List<CardObj> cardsWithoutBombs, int excludeValue) {
        // 移除三张的主牌
        List<CardObj> availableCards = cardsWithoutBombs.stream()
                .filter(card -> card.cardMod != excludeValue)
                .collect(Collectors.toList());

        Map<Integer, Integer> valueCount = getValueCount(availableCards);

        // 优先找对子作为带牌
        Optional<Integer> pairCandidate = valueCount.entrySet().stream()
                .filter(entry -> entry.getValue() >= 2)
                .map(Map.Entry::getKey)
                .findFirst();

        if (pairCandidate.isPresent()) {
            int pairValue = pairCandidate.get();
            return availableCards.stream()
                    .filter(card -> card.cardMod == pairValue)
                    .limit(2)
                    .collect(Collectors.toList());
        }

        // 没有对子，找两张单牌
        List<CardObj> sortedCards = availableCards.stream()
                .sorted(Comparator.comparingInt(card -> card.cardMod))
                .collect(Collectors.toList());

        if (sortedCards.size() >= 2) {
            Set<Integer> usedValues = new HashSet<>();
            List<CardObj> result = new ArrayList<>();

            for (CardObj card : sortedCards) {
                if (!usedValues.contains(card.cardMod)) {
                    result.add(card);
                    usedValues.add(card.cardMod);
                    if (result.size() == 2) {
                        return result;
                    }
                }
            }
        }

        return new ArrayList<>();
    }

    /**
     * 不拆炸弹的单牌查找
     */
    private static List<List<CardObj>> findSinglesAboveWithoutBreakingBomb(List<CardObj> handCards, int minCard) {
        Map<Integer, Integer> valueCount = getValueCount(handCards);
        Set<Integer> bombs = findBombValues(valueCount);

        return handCards.stream()
                .filter(card -> card.cardMod > minCard && !bombs.contains(card.cardMod))
                .map(Collections::singletonList)
                .collect(Collectors.toList());
    }

    /**
     * 不拆炸弹的对子查找
     */
    private static List<List<CardObj>> findPairsAboveWithoutBreakingBomb(List<CardObj> handCards, int minCard) {
        Map<Integer, Integer> valueCount = getValueCount(handCards);
        Set<Integer> bombs = findBombValues(valueCount);

        return valueCount.entrySet().stream()
                .filter(entry -> entry.getValue() >= 2 && entry.getKey() > minCard)
                .filter(entry -> !bombs.contains(entry.getKey())) // 排除炸弹牌值
                .map(entry -> handCards.stream()
                        .filter(card -> card.cardMod == entry.getKey())
                        .limit(2)
                        .collect(Collectors.toList()))
                .collect(Collectors.toList());
    }

    /**
     * 不拆炸弹的顺子查找
     */
    private static List<List<CardObj>> findStraightsAboveWithoutBreakingBomb(List<CardObj> handCards, int minCard, int len) {
        Map<Integer, Integer> valueCount = getValueCount(handCards);
        Set<Integer> bombs = findBombValues(valueCount);

        // 从原牌中移除炸弹牌
        List<CardObj> cardsWithoutBombs = handCards.stream()
                .filter(card -> !bombs.contains(card.cardMod))
                .collect(Collectors.toList());

        // 用非炸弹牌找顺子
        return findStraightsAbove(cardsWithoutBombs, minCard, len);
    }

    /**
     * 不拆炸弹的连对查找
     */
    private static List<List<CardObj>> findConsecutivePairsAboveWithoutBreakingBomb(List<CardObj> handCards, int minCard, int len) {
        Map<Integer, Integer> valueCount = getValueCount(handCards);
        Set<Integer> bombs = findBombValues(valueCount);

        // 从原牌中移除炸弹牌
        List<CardObj> cardsWithoutBombs = handCards.stream()
                .filter(card -> !bombs.contains(card.cardMod))
                .collect(Collectors.toList());

        return findConsecutivePairsAbove(cardsWithoutBombs, minCard, len);
    }


    /**
     * 找出所有的炸弹牌值
     */
    private static Set<Integer> findBombValues(Map<Integer, Integer> valueCount) {
        return valueCount.entrySet().stream()
                .filter(entry -> entry.getValue() == 4)
                .map(Map.Entry::getKey)
                .collect(Collectors.toSet());
    }

    /**
     * 获取基础牌型分数
     */
    private static int getBaseTypeScore(int type) {
        switch (type) {
            case Config.TYPE_SHUNZI:
                return 25;
            case Config.TYPE_LIANDUI:
                return 20;
            case Config.TYPE_FEIJI:
                return 18;
            case Config.TYPE_3_1:
                return 15;
            case Config.TYPE_4_2_dui:
                return 12;
            case Config.TYPE_DUIZI:
                return 8;
            case Config.TYPE_DANPAI:
                return 5;
            case Config.TYPE_ZHA:
                return 30;
            default:
                return 10;
        }
    }

    // ============ 牌型分析方法 ============

    /**
     * 分析单牌选项
     */
    private static List<PlayOption> analyzeSingles(List<CardObj> handCards) {
        List<PlayOption> options = new ArrayList<>();
        Map<Integer, List<CardObj>> valueGroups = groupByValue(handCards);

        // 真单牌
        for (Map.Entry<Integer, List<CardObj>> entry : valueGroups.entrySet()) {
            if (entry.getValue().size() == 1) {
                options.add(new PlayOption(Arrays.asList(entry.getValue().get(0)), Config.TYPE_DANPAI));
            }
        }

        // 从对子中拆出的单牌
        for (Map.Entry<Integer, List<CardObj>> entry : valueGroups.entrySet()) {
            if (entry.getValue().size() >= 2) {
                options.add(new PlayOption(Arrays.asList(entry.getValue().get(0)), Config.TYPE_DANPAI));
            }
        }

        return options;
    }

    /**
     * 分析对子选项
     */
    private static List<PlayOption> analyzePairs(List<CardObj> handCards) {
        List<PlayOption> options = new ArrayList<>();
        Map<Integer, List<CardObj>> valueGroups = groupByValue(handCards);

        for (Map.Entry<Integer, List<CardObj>> entry : valueGroups.entrySet()) {
            if (entry.getValue().size() >= 2) {
                options.add(new PlayOption(entry.getValue().subList(0, 2), Config.TYPE_DUIZI));
            }
        }

        return options;
    }

    /**
     * 分析顺子选项
     */
    private static List<PlayOption> analyzeStraights(List<CardObj> handCards) {
        List<PlayOption> options = new ArrayList<>();

        for (int length = 5; length <= 12; length++) {
            List<List<CardObj>> straights = findStraightsAbove(handCards, -1, length);
            for (List<CardObj> straight : straights) {
                options.add(new PlayOption(straight, Config.TYPE_SHUNZI));
            }
        }

        return options;
    }

    /**
     * 分析连对选项
     */
    private static List<PlayOption> analyzeConsecutivePairs(List<CardObj> handCards) {
        List<PlayOption> options = new ArrayList<>();

        for (int pairCount = 2; pairCount <= 6; pairCount++) {
            List<List<CardObj>> consecutivePairs = findConsecutivePairsAbove(handCards, -1, pairCount);
            for (List<CardObj> pairs : consecutivePairs) {
                options.add(new PlayOption(pairs, Config.TYPE_LIANDUI));
            }
        }

        return options;
    }

    /**
     * 分析炸弹选项
     */
    private static List<PlayOption> analyzeBombs(List<CardObj> handCards) {
        List<PlayOption> options = new ArrayList<>();
        List<List<CardObj>> bombs = findBombsAbove(handCards, -1);

        for (List<CardObj> bomb : bombs) {
            options.add(new PlayOption(bomb, Config.TYPE_ZHA));
        }

        return options;
    }

    /**
     * 分析三带一选项
     */
    private static List<PlayOption> analyzeTrioWithOnes(List<CardObj> handCards) {
        List<PlayOption> options = new ArrayList<>();
        List<List<CardObj>> trioWithOnes = findTrioWithOneAbove(handCards, -1);

        for (List<CardObj> cards : trioWithOnes) {
            options.add(new PlayOption(cards, Config.TYPE_3_1));
        }

        return options;
    }

    /**
     * 分析三带对选项
     */
    private static List<PlayOption> analyzeTrioWithPairs(List<CardObj> handCards) {
        List<PlayOption> options = new ArrayList<>();
        List<List<CardObj>> trioWithPairs = findTrioWithPairAbove(handCards, -1);

        for (List<CardObj> cards : trioWithPairs) {
            options.add(new PlayOption(cards, Config.TYPE_FEIJI));
        }

        return options;
    }

    /**
     * 分析四带二选项
     */
    private static List<PlayOption> analyzeFourWithTwos(List<CardObj> handCards) {
        List<PlayOption> options = new ArrayList<>();
        List<List<CardObj>> fourWithTwos = findFourWithTwoPairsAbove(handCards, -1);

        for (List<CardObj> cards : fourWithTwos) {
            options.add(new PlayOption(cards, Config.TYPE_4_2_dui));
        }

        return options;
    }

    // ============ 辅助方法 ============

    /**
     * 按牌值分组
     */
    private static Map<Integer, List<CardObj>> groupByValue(List<CardObj> handCards) {
        Map<Integer, List<CardObj>> groups = new HashMap<>();
        for (CardObj card : handCards) {
            groups.computeIfAbsent(card.cardMod, k -> new ArrayList<>()).add(card);
        }
        return groups;
    }

    /**
     * 查找最大单牌
     */
    private static CardObj findMaxSingleCard(List<CardObj> handCards) {
        return handCards.stream()
                .max(Comparator.comparingInt(c -> c.cardMod))
                .orElse(handCards.get(0));
    }

    // ============ 保留原有的查找方法 ============

    private static List<List<CardObj>> findSinglesAbove(List<CardObj> handCards, int minValue) {
        List<List<CardObj>> result = new ArrayList<>();
        for (CardObj card : handCards) {
            if (card.cardMod > minValue) {
                result.add(Arrays.asList(card));
            }
        }
        return result;
    }

    private static List<List<CardObj>> findPairsAbove(List<CardObj> handCards, int minValue) {
        List<List<CardObj>> result = new ArrayList<>();
        Map<Integer, List<CardObj>> valueGroups = groupByValue(handCards);

        for (List<CardObj> cards : valueGroups.values()) {
            if (cards.size() >= 2 && cards.get(0).cardMod > minValue) {
                result.add(Arrays.asList(cards.get(0), cards.get(1)));
            }
        }
        return result;
    }

    private static List<List<CardObj>> findStraightsAbove(List<CardObj> handCards, int minValue, int length) {
        List<List<CardObj>> result = new ArrayList<>();

        // 只过滤掉2(15)，A(14)可以参与顺子
        List<Integer> distinctValues = handCards.stream()
                .map(c -> c.cardMod)
                .filter(value -> value != 15) // 只排除2
                .distinct()
                .sorted()
                .collect(Collectors.toList());

        for (int i = 0; i <= distinctValues.size() - length; i++) {
            if (isConsecutive(distinctValues, i, length) && distinctValues.get(i) > minValue) {
                result.add(buildStraight(handCards, distinctValues.subList(i, i + length)));
            }
        }

        return result;
    }

    private static List<List<CardObj>> findConsecutivePairsAbove(List<CardObj> handCards, int minValue, int pairCount) {
        List<List<CardObj>> result = new ArrayList<>();
        if (handCards.isEmpty() || pairCount < 2) return result;

        handCards.sort(Comparator.comparingInt(c -> c.cardMod));
        Map<Integer, List<CardObj>> valueGroups = new HashMap<>();
        for (CardObj card : handCards) {
            valueGroups.computeIfAbsent(card.cardMod, k -> new ArrayList<>()).add(card);
        }

        List<Integer> pairValues = new ArrayList<>();
        for (Map.Entry<Integer, List<CardObj>> entry : valueGroups.entrySet()) {
            if (entry.getValue().size() >= 2) {
                pairValues.add(entry.getKey());
            }
        }

        if (pairValues.size() < pairCount) return result;
        Collections.sort(pairValues);

        for (int i = 0; i <= pairValues.size() - pairCount; i++) {
            boolean isConsecutive = true;
            for (int j = i; j < i + pairCount - 1; j++) {
                if (pairValues.get(j + 1) - pairValues.get(j) != 1) {
                    isConsecutive = false;
                    break;
                }
            }

            if (isConsecutive && pairValues.get(i) > minValue) {
                List<CardObj> consecutivePairs = new ArrayList<>();
                for (int k = i; k < i + pairCount; k++) {
                    int value = pairValues.get(k);
                    List<CardObj> pair = valueGroups.get(value).subList(0, 2);
                    consecutivePairs.addAll(pair);
                }
                result.add(consecutivePairs);
            }
        }
        return result;
    }

    private static List<List<CardObj>> findBombsAbove(List<CardObj> handCards, int minValue) {
        List<List<CardObj>> result = new ArrayList<>();
        handCards.sort(Comparator.comparingInt(c -> c.cardMod));
        Map<Integer, List<CardObj>> valueGroups = new HashMap<>();
        for (CardObj card : handCards) {
            valueGroups.computeIfAbsent(card.cardMod, k -> new ArrayList<>()).add(card);
        }

        for (Map.Entry<Integer, List<CardObj>> entry : valueGroups.entrySet()) {
            int cardValue = entry.getKey();
            List<CardObj> cards = entry.getValue();
            if (cards.size() >= 4 && cardValue > minValue) {
                result.add(cards);
            }
        }
        return result;
    }

    private static List<List<CardObj>> findTrioWithOneAbove(List<CardObj> handCards, int minValue) {
        List<List<CardObj>> result = new ArrayList<>();
        Map<Integer, List<CardObj>> valueGroups = groupByValue(handCards);

        // 找出所有三张的牌
        List<Integer> trioValues = new ArrayList<>();
        for (Map.Entry<Integer, List<CardObj>> entry : valueGroups.entrySet()) {
            if (entry.getValue().size() >= 3 && entry.getKey() > minValue) {
                trioValues.add(entry.getKey());
            }
        }

        Collections.sort(trioValues);

        for (int trioValue : trioValues) {
            List<CardObj> trio = valueGroups.get(trioValue).subList(0, 3);

            // 找出所有可带的牌（排除三张的牌值）
            List<CardObj> availableCards = new ArrayList<>();
            for (Map.Entry<Integer, List<CardObj>> entry : valueGroups.entrySet()) {
                if (entry.getKey() != trioValue) {
                    availableCards.addAll(entry.getValue());
                }
            }

            if (availableCards.size() < 2) continue;

            // 找出所有可能的两个牌组合（可以是一对或两个单牌）
            findTrioCombinations(result, trio, availableCards);
        }

        return result;
    }


    private static void findTrioCombinations(List<List<CardObj>> result, List<CardObj> trio, List<CardObj> availableCards) {
        availableCards.sort(Comparator.comparingInt(c -> c.cardMod));
        Set<String> combinationSet = new HashSet<>();

        for (int i = 0; i < availableCards.size() - 1; i++) {
            CardObj card1 = availableCards.get(i);
            for (int j = i + 1; j < availableCards.size(); j++) {
                CardObj card2 = availableCards.get(j);
                if (card1.card != card2.card) {
                    String comboKey = card1.cardMod <= card2.cardMod ?
                            card1.cardMod + "-" + card2.cardMod :
                            card2.cardMod + "-" + card1.cardMod;
                    if (!combinationSet.contains(comboKey)) {
                        combinationSet.add(comboKey);
                        List<CardObj> play = new ArrayList<>(trio);
                        play.add(card1);
                        play.add(card2);
                        result.add(play);
                    }
                }
            }
        }
    }

    private static List<List<CardObj>> findTrioWithPairAbove(List<CardObj> handCards, int minValue) {
        // 实现飞机逻辑
        return new ArrayList<>();
    }

    private static List<List<CardObj>> findFourWithTwoPairsAbove(List<CardObj> handCards, int minValue) {
        // 实现四带二对子逻辑
        return new ArrayList<>();
    }

    private static boolean isConsecutive(List<Integer> values, int start, int length) {
        for (int i = start; i < start + length - 1; i++) {
            if (values.get(i + 1) - values.get(i) != 1) {
                return false;
            }
        }
        return true;
    }

    private static List<CardObj> buildStraight(List<CardObj> handCards, List<Integer> values) {
        List<CardObj> straight = new ArrayList<>();
        for (int value : values) {
            // 取第一张该值的牌（确保不取2，但可以取A）
            for (CardObj card : handCards) {
                if (card.cardMod == value && value != 15) { // 只排除2
                    straight.add(card);
                    break;
                }
            }
        }
        return straight;
    }

    /**
     * 统计对子数量
     */
    private static int countPairs(Map<Integer, Integer> valueCount) {
        return (int) valueCount.values().stream()
                .filter(count -> count == 2)
                .count();
    }

    /**
     * 统计三张数量
     */
    private static int countTrios(Map<Integer, Integer> valueCount) {
        return (int) valueCount.values().stream()
                .filter(count -> count == 3)
                .count();
    }

    /**
     * 统计炸弹数量
     */
    private static int countBombs(Map<Integer, Integer> valueCount) {
        return (int) valueCount.values().stream()
                .filter(count -> count >= 4)
                .count();
    }

    /**
     * 查找最长顺子长度
     */
    private static int findMaxStraightLength(List<CardObj> handCards) {
        // 只过滤掉2(15)，A(14)可以参与顺子
        List<Integer> distinctValues = handCards.stream()
                .map(c -> c.cardMod)
                .filter(value -> value != 15) // 只排除2
                .distinct()
                .sorted()
                .collect(Collectors.toList());

        if (distinctValues.size() < 5) return 0;

        int maxLength = 1;
        int currentLength = 1;

        for (int i = 1; i < distinctValues.size(); i++) {
            if (distinctValues.get(i) - distinctValues.get(i - 1) == 1) {
                currentLength++;
                maxLength = Math.max(maxLength, currentLength);
            } else {
                currentLength = 1;
            }
        }

        return maxLength >= 5 ? maxLength : 0;
    }

    /**
     * 查找最长连对长度
     */
    private static int findMaxConsecutivePairs(List<CardObj> handCards) {
        Map<Integer, Integer> valueCount = getValueCount(handCards);
        List<Integer> pairValues = valueCount.entrySet().stream()
                .filter(entry -> entry.getValue() >= 2)
                .map(Map.Entry::getKey)
                .sorted()
                .collect(Collectors.toList());

        if (pairValues.size() < 2) return 0;

        int maxLength = 1;
        int currentLength = 1;

        for (int i = 1; i < pairValues.size(); i++) {
            if (pairValues.get(i) - pairValues.get(i - 1) == 1) {
                currentLength++;
                maxLength = Math.max(maxLength, currentLength);
            } else {
                currentLength = 1;
            }
        }

        return maxLength;
    }

    /**
     * 设置分析特征标签
     */
    private static void setAnalysisFeatures(HandAnalysis analysis) {
        // 基础特征
        analysis.features.put("smallSingleCount", analysis.smallSingleCount);
        analysis.features.put("bigCardCount", analysis.bigCardCount);
        analysis.features.put("pairCount", analysis.pairCount);
        analysis.features.put("trioCount", analysis.trioCount);
        analysis.features.put("bombCount", analysis.bombCount);
        analysis.features.put("maxStraightLength", analysis.maxStraightLength);
        analysis.features.put("maxConsecutivePairs", analysis.maxConsecutivePairs);

        // 特征标签
        if (analysis.smallSingleCount >= 3) {
            analysis.features.put("feature", "多小单牌");
        } else if (analysis.maxStraightLength >= 6) {
            analysis.features.put("feature", "长顺子");
        } else if (analysis.maxConsecutivePairs >= 3) {
            analysis.features.put("feature", "长连对");
        } else if (analysis.pairCount >= 4) {
            analysis.features.put("feature", "多对子");
        } else if (analysis.bigCardCount >= 3) {
            analysis.features.put("feature", "多大牌");
        } else {
            analysis.features.put("feature", "均衡牌型");
        }
    }

    /**
     * 从手牌中移除指定的牌
     */
    private static List<CardObj> removeCards(List<CardObj> originalHand, List<CardObj> cardsToRemove) {
        List<CardObj> remainHand = new ArrayList<>(originalHand);

        for (CardObj cardToRemove : cardsToRemove) {
            Iterator<CardObj> iterator = remainHand.iterator();
            while (iterator.hasNext()) {
                CardObj card = iterator.next();
                if (card.cardMod == cardToRemove.cardMod && card.card == cardToRemove.card) {
                    iterator.remove();
                    break;
                }
            }
        }

        return remainHand;
    }

    /**
     * 获取出牌类型
     */
    private static int getPlayType(List<CardObj> cards) {
        if (cards == null || cards.isEmpty()) return -1;

        int size = cards.size();
        Map<Integer, Integer> valueCount = getValueCount(cards);

        // 单牌
        if (size == 1) {
            return Config.TYPE_DANPAI;
        }

        // 对子
        if (size == 2 && valueCount.size() == 1) {
            return Config.TYPE_DUIZI;
        }

        // 顺子
        if (size >= 5 && isStraight(cards)) {
            return Config.TYPE_SHUNZI;
        }

        // 连对
        if (size >= 4 && size % 2 == 0 && isConsecutivePairs(cards)) {
            return Config.TYPE_LIANDUI;
        }

        // 三带一
        if (size == 4 && hasTrioWithSingle(valueCount)) {
            return Config.TYPE_3_1;
        }

        // 三带二
        if (size == 5 && hasTrioWithPair(valueCount)) {
            return Config.TYPE_FEIJI;
        }

        // 炸弹
        if (size >= 4 && valueCount.size() == 1) {
            return Config.TYPE_ZHA;
        }

        // 四带二
        if (size == 6 && hasFourWithTwo(valueCount)) {
            return Config.TYPE_4_2_dui;
        }

        return -1; // 未知类型
    }

    /**
     * 判断是否为顺子
     */
    private static boolean isStraight(List<CardObj> cards) {
        if (cards.size() < 5) return false;

        List<Integer> values = cards.stream()
                .map(c -> c.cardMod)
                .distinct()
                .sorted()
                .collect(Collectors.toList());

        // 只检查是否有2(15)，2不能参与顺子，A(14)可以参与
        if (values.contains(15)) {
            return false;
        }

        if (values.size() != cards.size()) return false; // 有重复牌值

        for (int i = 1; i < values.size(); i++) {
            if (values.get(i) - values.get(i - 1) != 1) {
                return false;
            }
        }

        return true;
    }

    /**
     * 判断是否为连对
     */
    private static boolean isConsecutivePairs(List<CardObj> cards) {
        if (cards.size() < 4 || cards.size() % 2 != 0) return false;

        Map<Integer, Integer> valueCount = getValueCount(cards);

        // 检查每个牌值都是2张
        for (int count : valueCount.values()) {
            if (count != 2) return false;
        }

        // 检查是否连续
        List<Integer> values = valueCount.keySet().stream()
                .sorted()
                .collect(Collectors.toList());

        for (int i = 1; i < values.size(); i++) {
            if (values.get(i) - values.get(i - 1) != 1) {
                return false;
            }
        }

        return true;
    }

    /**
     * 判断是否为三带一
     */
    private static boolean hasTrioWithSingle(Map<Integer, Integer> valueCount) {
        if (valueCount.size() != 2) return false;

        boolean hasTrio = valueCount.values().stream().anyMatch(count -> count == 3);
        boolean hasSingle = valueCount.values().stream().anyMatch(count -> count == 1);

        return hasTrio && hasSingle;
    }

    /**
     * 判断是否为三带二
     */
    private static boolean hasTrioWithPair(Map<Integer, Integer> valueCount) {
        if (valueCount.size() != 2) return false;

        boolean hasTrio = valueCount.values().stream().anyMatch(count -> count == 3);
        boolean hasPair = valueCount.values().stream().anyMatch(count -> count == 2);

        return hasTrio && hasPair;
    }

    /**
     * 判断是否为四带二
     */
    private static boolean hasFourWithTwo(Map<Integer, Integer> valueCount) {
        if (valueCount.size() != 3) return false;

        boolean hasFour = valueCount.values().stream().anyMatch(count -> count == 4);
        boolean hasTwoSingles = valueCount.values().stream().filter(count -> count == 1).count() == 2;
        boolean hasOnePair = valueCount.values().stream().anyMatch(count -> count == 2);

        return hasFour && (hasTwoSingles || hasOnePair);
    }


    /**
     * 统计牌值数量
     */
    private static Map<Integer, Integer> getValueCount(List<CardObj> cards) {
        Map<Integer, Integer> countMap = new HashMap<>();
        for (CardObj card : cards) {
            countMap.put(card.cardMod, countMap.getOrDefault(card.cardMod, 0) + 1);
        }
        return countMap;
    }

    // 获取除当前座位外所有其他座位的最后记录
    public static Map<Integer, Integer> getOtherSeatsLastRemain(int currentSeat, Map<Integer, List<Integer>> seatRemainHistory) {
        Map<Integer, Integer> result = new HashMap<>();

        for (Map.Entry<Integer, List<Integer>> entry : seatRemainHistory.entrySet()) {
            int seat = entry.getKey();
            List<Integer> remainList = entry.getValue();

            // 排除当前座位
            if (seat != currentSeat && !remainList.isEmpty()) {
                // 取list最后一个记录
                int lastRemain = remainList.get(remainList.size() - 1);
                result.put(seat, lastRemain);
            }
        }
        return result;
    }


    /**
     * 基础出牌选项类
     */
    static class PlayOption {
        List<CardObj> cards;
        int type;
        int score;

        public PlayOption(List<CardObj> cards, int type) {
            this.cards = cards;
            this.type = type;
            this.score = 0;
        }
    }

    /**
     * 出牌后手牌分析类
     */
    static class RemainHandAnalysis {
        boolean isWin = false;
        int cardCount = 0;
        int maxCardValue = 0;
        int minCardValue = 0;
        double avgCardValue = 0;
        int singleCount = 0;
        int pairCount = 0;
        int trioCount = 0;
        int straightPotential = 0;
        int consecutivePairPotential = 0;
        int estimatedTurns = 0;
        int remainScore = 0;
        int bigCardRemain = 0; // 新增：剩余大牌数量
    }

    /**
     * 出牌选项类（包含出牌后手牌分析）
     */
    static class PlayOptionWithRemain {
        List<CardObj> cards;
        int type;
        int totalScore;
        List<CardObj> remainHand;
        RemainHandAnalysis analysis;

        public PlayOptionWithRemain(PlayOption option, List<CardObj> remainHand, RemainHandAnalysis analysis) {
            this.cards = option.cards;
            this.type = option.type;
            this.remainHand = remainHand;
            this.analysis = analysis;
            this.totalScore = 0;
        }

        public int getEstimatedTurns() {
            return analysis.estimatedTurns;
        }
    }
}