|
@@ -198,13 +198,13 @@ public final class GDUtils {
|
|
|
return compareTripleWithTwo(previousPoints, currentPoints, curLevel, wildCardCountCurrent, wildCardCountPrevious);
|
|
|
case TRIPLE_SEQUENCE:
|
|
|
// 三顺(二个连续三张)
|
|
|
-// break;
|
|
|
+ return compareThreeConsecutive(previousPoints, currentPoints, curLevel, wildCardCountCurrent, wildCardCountPrevious);
|
|
|
case STRAIGHT:
|
|
|
// 顺子:赖子牌可以补齐顺子
|
|
|
-// return compareStraight(previousPoints, currentPoints, curLevel, wildCardCountCurrent, wildCardCountPrevious);
|
|
|
+ return compareStraight(previousPoints, currentPoints, curLevel, wildCardCountCurrent, wildCardCountPrevious);
|
|
|
case BOMB:
|
|
|
// 炸弹:赖子牌可以增强炸弹的级别
|
|
|
-// return compareBomb(previousPoints, currentPoints, wildCardCountCurrent, wildCardCountPrevious);
|
|
|
+ return compareBomb(previousPoints, currentPoints, wildCardCountCurrent, wildCardCountPrevious);
|
|
|
default:
|
|
|
// 默认按最大点数比较
|
|
|
return Integer.compare(
|
|
@@ -485,6 +485,199 @@ public final class GDUtils {
|
|
|
return Integer.compare(maxCurrentTriple, maxPreviousTriple);
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 比较两组三张连续牌型的大小,支持赖子牌的处理
|
|
|
+ *
|
|
|
+ * @param previousPoints 上一手牌的点数列表(三张连续牌)
|
|
|
+ * @param currentPoints 当前手牌的点数列表(三张连续牌)
|
|
|
+ * @param curLevel 当前级数(主牌)
|
|
|
+ * @param wildCardCountCurrent 当前手牌的赖子数量
|
|
|
+ * @param wildCardCountPrevious 上一手牌的赖子数量
|
|
|
+ * @return 正数表示当前牌较大,负数表示上一手牌较大,0表示相等
|
|
|
+ */
|
|
|
+ private static int compareThreeConsecutive(List<Integer> previousPoints, List<Integer> currentPoints, int curLevel, int wildCardCountCurrent, int wildCardCountPrevious) {
|
|
|
+ // 替换赖子牌为当前级牌点数,形成有效的三张连续牌
|
|
|
+ List<Integer> adjustedPrevious = replaceWildCardsWithTrump(previousPoints, wildCardCountPrevious, curLevel, 3);
|
|
|
+ List<Integer> adjustedCurrent = replaceWildCardsWithTrump(currentPoints, wildCardCountCurrent, curLevel, 3);
|
|
|
+
|
|
|
+ // 判断上一手牌和当前手牌的强度
|
|
|
+ int previousStrength = calculateHandStrength(adjustedPrevious, wildCardCountPrevious);
|
|
|
+ int currentStrength = calculateHandStrength(adjustedCurrent, wildCardCountCurrent);
|
|
|
+
|
|
|
+ // 如果当前牌比上一手牌强,返回1
|
|
|
+ if (currentStrength > previousStrength) {
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+ // 如果上一手牌比当前牌强,返回-1
|
|
|
+ if (currentStrength < previousStrength) {
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果两手牌的强度相同,按点数进行比较
|
|
|
+ return compareByPoints(adjustedPrevious, adjustedCurrent);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 计算手牌的强度(考虑赖子牌替换后的牌型)
|
|
|
+ * @param points 调整后的点数列表
|
|
|
+ * @param wildCardCount 赖子牌数量
|
|
|
+ * @return 该手牌的强度值
|
|
|
+ */
|
|
|
+ private static int calculateHandStrength(List<Integer> points, int wildCardCount) {
|
|
|
+ // 如果有赖子牌,根据赖子的数量来决定牌型的强度
|
|
|
+ if (wildCardCount == 0) {
|
|
|
+ // 没有赖子牌,则返回手牌的最大点数
|
|
|
+ return points.get(points.size() - 1);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 赖子牌数量 > 0 时,尝试使用赖子提升最大点数
|
|
|
+ int adjustedStrength = points.get(points.size() - 1); // 先按最大牌计算
|
|
|
+ // 如果赖子数量比较多,可能有机会改变牌型的强度,考虑赖子的替换效果
|
|
|
+ if (wildCardCount > 1) {
|
|
|
+ adjustedStrength += 1; // 假设通过赖子牌,我们可以增加一张更高的牌
|
|
|
+ }
|
|
|
+ return adjustedStrength;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 比较两手牌的点数
|
|
|
+ * @param previousPoints 上一手牌的点数列表
|
|
|
+ * @param currentPoints 当前手牌的点数列表
|
|
|
+ * @return 正数表示当前牌较大,负数表示上一手牌较大,0表示相等
|
|
|
+ */
|
|
|
+ private static int compareByPoints(List<Integer> previousPoints, List<Integer> currentPoints) {
|
|
|
+ // 先比较最大点数
|
|
|
+ int maxPrevious = getMaxConsecutiveValue(previousPoints);
|
|
|
+ int maxCurrent = getMaxConsecutiveValue(currentPoints);
|
|
|
+
|
|
|
+ // 如果当前牌的最大点数较大,返回1
|
|
|
+ if (maxCurrent > maxPrevious) {
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+ // 如果上一手牌的最大点数较大,返回-1
|
|
|
+ if (maxCurrent < maxPrevious) {
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果最大点数相同,比较最小点数
|
|
|
+ int minPrevious = getMinConsecutiveValue(previousPoints);
|
|
|
+ int minCurrent = getMinConsecutiveValue(currentPoints);
|
|
|
+
|
|
|
+ return Integer.compare(minCurrent, minPrevious);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取连续三张牌的最大点数(即三张中的最大牌)
|
|
|
+ *
|
|
|
+ * @param points 调整后的点数列表
|
|
|
+ * @return 三张牌中的最大点数
|
|
|
+ */
|
|
|
+ private static int getMaxConsecutiveValue(List<Integer> points) {
|
|
|
+ return points.get(points.size() - 1); // 假设牌已经是顺序排列
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取连续三张牌的最小点数(即三张中的最小牌)
|
|
|
+ *
|
|
|
+ * @param points 调整后的点数列表
|
|
|
+ * @return 三张牌中的最小点数
|
|
|
+ */
|
|
|
+ private static int getMinConsecutiveValue(List<Integer> points) {
|
|
|
+ return points.get(0); // 假设牌已经是顺序排列
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 比较顺子牌型的大小(考虑赖子牌的补充)
|
|
|
+ *
|
|
|
+ * @param previousPoints 上一手牌的点数列表
|
|
|
+ * @param currentPoints 当前手牌的点数列表
|
|
|
+ * @param curLevel 当前级数(主牌)
|
|
|
+ * @param wildCardCountCurrent 当前手牌的赖子数量
|
|
|
+ * @param wildCardCountPrevious 上一手牌的赖子数量
|
|
|
+ * @return 正数表示当前牌较大,负数表示上一手牌较大,0表示相等
|
|
|
+ */
|
|
|
+ private static int compareStraight(List<Integer> previousPoints, List<Integer> currentPoints, int curLevel, int wildCardCountCurrent, int wildCardCountPrevious) {
|
|
|
+ // 替换赖子牌为当前级牌点数,形成有效的顺子
|
|
|
+ List<Integer> adjustedPrevious = replaceWildCardsWithTrump(previousPoints, wildCardCountPrevious, curLevel, 5);
|
|
|
+ List<Integer> adjustedCurrent = replaceWildCardsWithTrump(currentPoints, wildCardCountCurrent, curLevel, 5);
|
|
|
+
|
|
|
+ // 获取每手牌的最大顺子点数
|
|
|
+ int maxPreviousStraight = getMaxStraightValue(adjustedPrevious);
|
|
|
+ int maxCurrentStraight = getMaxStraightValue(adjustedCurrent);
|
|
|
+
|
|
|
+ // 如果当前顺子的最大点数较大,返回1
|
|
|
+ if (maxCurrentStraight > maxPreviousStraight) {
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+ // 如果上一手牌的最大点数较大,返回-1
|
|
|
+ if (maxCurrentStraight < maxPreviousStraight) {
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果顺子的最大点数相同,比较顺子的最小点数(头牌)
|
|
|
+ int minPreviousStraight = getMinStraightValue(adjustedPrevious);
|
|
|
+ int minCurrentStraight = getMinStraightValue(adjustedCurrent);
|
|
|
+
|
|
|
+ return Integer.compare(minCurrentStraight, minPreviousStraight);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取顺子的最大点数(即顺子中的最大牌)
|
|
|
+ *
|
|
|
+ * @param points 调整后的点数列表
|
|
|
+ * @return 顺子的最大点数
|
|
|
+ */
|
|
|
+ private static int getMaxStraightValue(List<Integer> points) {
|
|
|
+ // 顺子应该由连续的五张牌组成,获取顺子的最大点数
|
|
|
+ return points.get(points.size() - 1);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取顺子的最小点数(即顺子中的最小牌)
|
|
|
+ *
|
|
|
+ * @param points 调整后的点数列表
|
|
|
+ * @return 顺子的最小点数
|
|
|
+ */
|
|
|
+ private static int getMinStraightValue(List<Integer> points) {
|
|
|
+ // 顺子应该由连续的五张牌组成,获取顺子的最小点数
|
|
|
+ return points.get(0);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 比较炸弹牌型的大小(考虑赖子牌的增强)
|
|
|
+ *
|
|
|
+ * @param previousPoints 上一手牌的点数列表
|
|
|
+ * @param currentPoints 当前手牌的点数列表
|
|
|
+ * @param wildCardCountCurrent 当前手牌中的赖子数量
|
|
|
+ * @param wildCardCountPrevious 上一手牌中的赖子数量
|
|
|
+ * @return 正数表示当前牌较大,负数表示上一手牌较大,0表示相等
|
|
|
+ */
|
|
|
+ private static int compareBomb(List<Integer> previousPoints, List<Integer> currentPoints, int wildCardCountCurrent, int wildCardCountPrevious) {
|
|
|
+ // 获取上一手牌和当前手牌中的最大炸弹点数
|
|
|
+ int maxPreviousBomb = getMaxFrequencyCard(previousPoints, 4);
|
|
|
+ int maxCurrentBomb = getMaxFrequencyCard(currentPoints, 4);
|
|
|
+
|
|
|
+ // 如果当前手牌的炸弹点数较大,返回1
|
|
|
+ if (maxCurrentBomb > maxPreviousBomb) {
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+ // 如果上一手牌的炸弹点数较大,返回-1
|
|
|
+ if (maxCurrentBomb < maxPreviousBomb) {
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果炸弹点数相同,考虑赖子的数量,赖子越多,炸弹越强
|
|
|
+ if (wildCardCountCurrent > wildCardCountPrevious) {
|
|
|
+ return 1; // 当前手牌有更多赖子,炸弹更强
|
|
|
+ }
|
|
|
+ if (wildCardCountCurrent < wildCardCountPrevious) {
|
|
|
+ return -1; // 上一手牌有更多赖子,炸弹更强
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果炸弹点数和赖子数量都相同,则返回平局
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* 获取指定频率的最大点数
|
|
|
*
|
|
@@ -640,18 +833,18 @@ public final class GDUtils {
|
|
|
return CardType.STRAIGHT;
|
|
|
}
|
|
|
|
|
|
- // 6. 连对(赖子可补齐缺失对数)
|
|
|
- if (cardCount >= 6 && cardCount % 2 == 0 && uniqueCount + wildCount >= cardCount / 2
|
|
|
- && isPairSequenceWithWild(pointFrequency, wildCount)) {
|
|
|
- return CardType.PAIR_SEQUENCE;
|
|
|
- }
|
|
|
-
|
|
|
- // 7. 三顺(赖子可补齐缺失三张)
|
|
|
+ // 6. 三顺(赖子可补齐缺失三张)
|
|
|
if (cardCount >= 6 && cardCount % 3 == 0 && uniqueCount + wildCount >= cardCount / 3
|
|
|
&& isTripleSequenceWithWild(pointFrequency, wildCount)) {
|
|
|
return CardType.TRIPLE_SEQUENCE;
|
|
|
}
|
|
|
|
|
|
+ // 7. 连对(赖子可补齐缺失对数)
|
|
|
+ if (cardCount >= 6 && cardCount % 2 == 0 && uniqueCount + wildCount >= cardCount / 2
|
|
|
+ && isPairSequenceWithWild(pointFrequency, wildCount)) {
|
|
|
+ return CardType.PAIR_SEQUENCE;
|
|
|
+ }
|
|
|
+
|
|
|
// 8. 三带二
|
|
|
if (cardCount == 5 && uniqueCount <= 3 && isTripleWithTwo(pointFrequency, wildCount)) {
|
|
|
return CardType.TRIPLE_WITH_TWO;
|
|
@@ -770,6 +963,10 @@ public final class GDUtils {
|
|
|
.sorted()
|
|
|
.collect(Collectors.toList());
|
|
|
|
|
|
+ // 如果没有符合条件的三张连续牌,直接返回 false
|
|
|
+ if (triples.isEmpty()) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
// 排除特例:A-A-A-2-2-2 是有效的最小三顺
|
|
|
if (triples.contains(14) && triples.contains(2)) { // A 和 2 的点数
|
|
|
return true; // A-A-A-2-2-2 不是有效的三顺
|
|
@@ -790,6 +987,7 @@ public final class GDUtils {
|
|
|
}
|
|
|
gaps += (int) (3 - pointFrequency.get(triples.get(i)));
|
|
|
}
|
|
|
+ // 最后一个元素也需要处理
|
|
|
gaps += (int) (3 - pointFrequency.get(triples.get(triples.size() - 1)));
|
|
|
return gaps <= wildCount;
|
|
|
}
|