Browse Source

1.解决对4,8可以出;2.解决3带2,10可以出;3.解决33322,44455不能出

johnclot69 4 months ago
parent
commit
359c2f2769

+ 6 - 4
incubator-game/src/main/java/com/incubator/game/handler/jdgd/JDGDDisCardHandler.java

@@ -83,17 +83,19 @@ public class JDGDDisCardHandler extends NetHandler {
         }
 
         // 判断玩家出牌牌型
-        JDGDUtils.CardType cardType = JDGDUtils.determineCardType(disCardList, 2);
-        if (cardType == JDGDUtils.CardType.INVALID) {
+        JDGDUtils.CardType disCardType = JDGDUtils.determineCardType(disCardList, 2);
+        if (disCardType == JDGDUtils.CardType.INVALID) {
             logger.info("牌型错误");
             response.setCode(9);
             response.setMessage("牌型错误...");
             return;
         }
 
+        //
+
         if (room.data.curDisCardList != null && room.data.curDisCardType != null) {
             // 是否大过桌上牌
-            if (!room.canDisCard(disCardList, cardType, 2)) {
+            if (!room.canDisCard(disCardList, disCardType, 2)) {
                 logger.info("出牌错误,无法大过当前牌...");
                 response.setCode(10);
                 response.setMessage("出牌错误,无法大过当前牌...");
@@ -102,7 +104,7 @@ public class JDGDDisCardHandler extends NetHandler {
         }
 
         // 出牌
-        room.playerDisCard(player, disCardList, cardType);
+        room.playerDisCard(player, disCardList, disCardType);
 
         // 正常返回
         response.setData(ProtoUtil.roomToMessage(room, player, room.data.currentPlayer));

+ 14 - 11
incubator-game/src/main/java/com/incubator/game/room/JDGDRoom.java

@@ -335,18 +335,21 @@ public class JDGDRoom extends Room implements GRoomInterface {
      * @return 是否可以出牌
      */
     public boolean canDisCard(int[] disCardsList, JDGDUtils.CardType disCardsType, int currentLevel) {
-        // 获取权重值
-        int previousWeight = JDGDUtils.getCardTypeWeight(this.data.curDisCardType);
-        int currentWeight = JDGDUtils.getCardTypeWeight(disCardsType);
-
-        // 权重不同,按权重大小比较
-        if (currentWeight > previousWeight) {
-            return true;
-        }
+        // 牌型是否一致
+        if (this.data.curDisCardType != null && this.data.curDisCardType.equals(disCardsType)) {
+            // 获取权重值
+            int previousWeight = JDGDUtils.getCardTypeWeight(this.data.curDisCardType);
+            int currentWeight = JDGDUtils.getCardTypeWeight(disCardsType);
+
+            // 权重不同,按权重大小比较
+            if (currentWeight > previousWeight) {
+                return true;
+            }
 
-        // 权重相同,根据牌点大小进行比较(仅适用于同类型的牌型,如炸弹或顺子)
-        if (currentWeight == previousWeight) {
-            return JDGDUtils.compareCardStrength(this.data.curDisCardList, disCardsList, currentLevel) > 0;
+            // 权重相同,根据牌点大小进行比较(仅适用于同类型的牌型,如炸弹或顺子)
+            if (currentWeight == previousWeight) {
+                return JDGDUtils.compareCardStrength(this.data.curDisCardList, disCardsList, currentLevel, disCardsType) > 0;
+            }
         }
 
         return false; // 其他情况不能出牌

+ 102 - 10
incubator-game/src/main/java/com/incubator/game/util/JDGDUtils.java

@@ -53,24 +53,116 @@ public final class JDGDUtils {
 
     /**
      * 比较两组牌的大小(仅在牌型相同时调用)
+     *
      * @param previousCards 上一手牌
      * @param disCardList 当前玩家出的牌
      * @param curLevel 当前级数
+     * @param cardType 牌型
      * @return 正数表示当前牌较大,负数表示上一手牌较大,0表示相等
      */
-    public static int compareCardStrength(int[] previousCards, int[] disCardList, int curLevel) {
-        List<Integer> previousPoints = new ArrayList<>();
-        for (int card : previousCards) {
-            previousPoints.add(getCardPoint(card, curLevel));
-        }
+    public static int compareCardStrength(int[] previousCards, int[] disCardList, int curLevel, CardType cardType) {
+        List<Integer> previousPoints = Arrays.stream(previousCards)
+                .map(card -> getCardPoint(card, curLevel))
+                .sorted()
+                .boxed()
+                .collect(Collectors.toList());
 
-        List<Integer> currentPoints = new ArrayList<>();
-        for (int card : disCardList) {
-            currentPoints.add(getCardPoint(card, curLevel));
+        List<Integer> currentPoints = Arrays.stream(disCardList)
+                .map(card -> getCardPoint(card, curLevel))
+                .sorted()
+                .boxed()
+                .collect(Collectors.toList());
+
+        switch (cardType) {
+            case SINGLE:
+            case PAIR:
+            case TRIPLE:
+            case STRAIGHT:
+                // 单张、对子、三不带、顺子直接比较最大点数
+                return Integer.compare(
+                        currentPoints.get(currentPoints.size() - 1),
+                        previousPoints.get(previousPoints.size() - 1)
+                );
+
+            case TRIPLE_WITH_TWO:
+                // 三带二:优先比较三张部分,再比较两张部分
+                int currentTriple = getMaxFrequencyCard(currentPoints, 3);
+                int previousTriple = getMaxFrequencyCard(previousPoints, 3);
+
+                if (currentTriple != previousTriple) {
+                    return Integer.compare(currentTriple, previousTriple);
+                }
+
+                // 如果三张部分相等,比较附带的两张部分
+                List<Integer> currentPair = currentPoints.stream()
+                        .filter(point -> point != currentTriple)
+                        .sorted(Comparator.reverseOrder())
+                        .collect(Collectors.toList());
+                List<Integer> previousPair = previousPoints.stream()
+                        .filter(point -> point != previousTriple)
+                        .sorted(Comparator.reverseOrder())
+                        .collect(Collectors.toList());
+
+                for (int i = 0; i < currentPair.size(); i++) {
+                    int cmp = Integer.compare(currentPair.get(i), previousPair.get(i));
+                    if (cmp != 0) {
+                        return cmp;
+                    }
+                }
+                return 0;
+
+            case PAIR_SEQUENCE:
+            case TRIPLE_SEQUENCE:
+                // 连对、三顺:逐一比较点数
+                for (int i = 0; i < currentPoints.size(); i++) {
+                    int cmp = Integer.compare(currentPoints.get(i), previousPoints.get(i));
+                    if (cmp != 0) {
+                        return cmp;
+                    }
+                }
+                return 0;
+
+            case BOMB:
+            case FOUR_BOMB:
+            case FIVE_BOMB:
+            case SIX_BOMB:
+            case SEVEN_BOMB:
+            case EIGHT_BOMB:
+            case FOUR_KINGS:
+                // 炸弹:按炸弹的牌型权重比较
+                int currentWeight = getCardTypeWeight(determineCardType(disCardList, curLevel));
+                int previousWeight = getCardTypeWeight(determineCardType(previousCards, curLevel));
+
+                if (currentWeight != previousWeight) {
+                    return Integer.compare(currentWeight, previousWeight);
+                }
+                // 若权重相等,比较炸弹点数
+                return Integer.compare(
+                        currentPoints.get(currentPoints.size() - 1),
+                        previousPoints.get(previousPoints.size() - 1)
+                );
+
+            default:
+                // 对于未定义类型的比较,按最大点数处理
+                return Integer.compare(
+                        currentPoints.get(currentPoints.size() - 1),
+                        previousPoints.get(previousPoints.size() - 1)
+                );
         }
+    }
 
-        // 比较最高点
-        return currentPoints.get(currentPoints.size() - 1) - previousPoints.get(previousPoints.size() - 1);
+    /**
+     * 获取指定频率的最大点数
+     *
+     * @param points 点数列表
+     * @param frequency 目标频率(如 3 表示三张)
+     * @return 满足频率的最大点数
+     */
+    private static int getMaxFrequencyCard(List<Integer> points, int frequency) {
+        return points.stream()
+                .filter(p -> Collections.frequency(points, p) == frequency)
+                .max(Integer::compareTo)
+                .orElse(0);
     }
 
     /**