|
@@ -228,7 +228,9 @@ public final class GDUtils {
|
|
|
case TRIPLE_SEQUENCE:
|
|
|
// 三顺(二个连续三张)
|
|
|
return compareThreeConsecutive(previousPoints, currentPoints, curLevel, wildCardCountCurrent, wildCardCountPrevious);
|
|
|
- case STRAIGHT:
|
|
|
+ case ROYAL_FLUSH:
|
|
|
+ return compareRoyalFlush(previousPoints, currentPoints, curLevel, wildCardCountCurrent, wildCardCountPrevious);
|
|
|
+ case STRAIGHT:
|
|
|
// 顺子:赖子牌可以补齐顺子
|
|
|
return compareStraight(previousPoints, currentPoints, curLevel, wildCardCountCurrent, wildCardCountPrevious);
|
|
|
case BOMB:
|
|
@@ -260,7 +262,7 @@ public final class GDUtils {
|
|
|
* @param requiredCount 需要的牌型数量(例如三张牌需要 3)
|
|
|
* @return 调整后的点数列表
|
|
|
*/
|
|
|
- private static List<Integer> replaceWildCardsWithTrump(List<Integer> points, int wildCardCount, int curLevel, int requiredCount) {
|
|
|
+ /* private static List<Integer> replaceWildCardsWithTrump(List<Integer> points, int wildCardCount, int curLevel, int requiredCount) {
|
|
|
List<Integer> adjustedPoints = new ArrayList<>(points);
|
|
|
adjustedPoints.removeIf(p -> p == -1); // 移除赖子标识
|
|
|
|
|
@@ -288,7 +290,7 @@ public final class GDUtils {
|
|
|
|
|
|
adjustedPoints.sort(Collections.reverseOrder()); // 按照点数降序排序
|
|
|
return adjustedPoints;
|
|
|
- }
|
|
|
+ }*/
|
|
|
|
|
|
/**
|
|
|
* 比较单张牌的大小
|
|
@@ -682,27 +684,27 @@ public final class GDUtils {
|
|
|
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);
|
|
|
- }
|
|
|
+ }*/
|
|
|
|
|
|
/**
|
|
|
* 比较炸弹牌型的大小(考虑赖子牌的增强)
|
|
@@ -983,7 +985,111 @@ public final class GDUtils {
|
|
|
// 返回是否能同时构成三张和两张
|
|
|
return hasTriple && hasPair;
|
|
|
}
|
|
|
+ /**
|
|
|
+ * 比较同花顺子牌型的大小(考虑赖子牌的补充)
|
|
|
+ *
|
|
|
+ * @param previousPoints 上一手牌的点数列表
|
|
|
+ * @param currentPoints 当前手牌的点数列表
|
|
|
+ * @param curLevel 当前级数(主牌)
|
|
|
+ * @param wildCardCountCurrent 当前手牌的赖子数量
|
|
|
+ * @param wildCardCountPrevious 上一手牌的赖子数量
|
|
|
+ * @return 正数表示当前牌较大,负数表示上一手牌较大,0表示相等
|
|
|
+ */
|
|
|
+ private static int compareRoyalFlush(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 minPreviousStraight = getMinStraightValue(adjustedPrevious);
|
|
|
+ int minCurrentStraight = getMinStraightValue(adjustedCurrent);
|
|
|
+
|
|
|
+ // 如果当前顺子的最小点数较大,返回1
|
|
|
+ if (minCurrentStraight > minPreviousStraight) {
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+ // 如果上一手牌的最小点数较大,返回-1
|
|
|
+ if (minCurrentStraight < minPreviousStraight) {
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果顺子的最小点数相同,比较顺子的最大点数
|
|
|
+ int maxPreviousStraight = getMaxStraightValue(adjustedPrevious);
|
|
|
+ int maxCurrentStraight = getMaxStraightValue(adjustedCurrent);
|
|
|
+
|
|
|
+ // 如果当前顺子的最大点数较大,返回1
|
|
|
+ if (maxCurrentStraight > maxPreviousStraight) {
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
+ // 如果上一手牌的最大点数较大,返回-1
|
|
|
+ if (maxCurrentStraight < maxPreviousStraight) {
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果顺子的最小点数和最大点数都相同,返回0
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 替换赖子牌为当前手牌中的其他牌,以形成有效的牌型
|
|
|
+ *
|
|
|
+ * @param points 当前手牌的点数列表
|
|
|
+ * @param wildCardCount 赖子牌的数量
|
|
|
+ * @param curLevel 当前级数(主牌)
|
|
|
+ * @param requiredCount 需要的牌型数量(例如同花顺需要 5)
|
|
|
+ * @return 调整后的点数列表
|
|
|
+ */
|
|
|
+ private static List<Integer> replaceWildCardsWithTrump(List<Integer> points, int wildCardCount, int curLevel, int requiredCount) {
|
|
|
+ List<Integer> adjustedPoints = new ArrayList<>(points);
|
|
|
+ adjustedPoints.removeIf(p -> p == -1); // 移除赖子标识
|
|
|
+
|
|
|
+ // 找到当前手牌中排除大王和小王的最小点数
|
|
|
+ List<Integer> availablePoints = adjustedPoints.stream()
|
|
|
+ .filter(p -> p != 16 && p != 17) // 排除大王(17)和小王(16)
|
|
|
+ .distinct() // 确保不重复
|
|
|
+ .sorted()
|
|
|
+ .collect(Collectors.toList());
|
|
|
|
|
|
+ // 如果有可用的牌点,则选择最小的点数作为赖子的替换点
|
|
|
+ int replacementPoint = availablePoints.isEmpty() ? curLevel : availablePoints.get(0); // 默认选择最小点数,如果没有则选择当前级牌
|
|
|
+
|
|
|
+ // 替换赖子牌为选定的点数
|
|
|
+ while (wildCardCount > 0 && adjustedPoints.size() < requiredCount) {
|
|
|
+ adjustedPoints.add(replacementPoint); // 使用替换点数填充赖子
|
|
|
+ wildCardCount--;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果赖子牌数量仍然大于0,但已经满足requiredCount,将剩余的赖子牌添加为当前级牌
|
|
|
+ while (wildCardCount > 0) {
|
|
|
+ adjustedPoints.add(curLevel);
|
|
|
+ wildCardCount--;
|
|
|
+ }
|
|
|
+
|
|
|
+ adjustedPoints.sort(Collections.reverseOrder()); // 按照点数降序排序
|
|
|
+ return adjustedPoints;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取顺子的最小点数(即顺子中的最小牌)
|
|
|
+ *
|
|
|
+ * @param points 调整后的点数列表
|
|
|
+ * @return 顺子的最小点数
|
|
|
+ */
|
|
|
+ private static int getMinStraightValue(List<Integer> points) {
|
|
|
+ // 顺子应该由连续的五张牌组成,获取顺子的最小点数
|
|
|
+ return points.stream().min(Integer::compare).orElse(-1);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取顺子的最大点数(即顺子中的最大牌)
|
|
|
+ *
|
|
|
+ * @param points 调整后的点数列表
|
|
|
+ * @return 顺子的最大点数
|
|
|
+ */
|
|
|
+ private static int getMaxStraightValue(List<Integer> points) {
|
|
|
+ // 顺子应该由连续的五张牌组成,获取顺子的最大点数
|
|
|
+ return points.stream().max(Integer::compare).orElse(-1);
|
|
|
+ }
|
|
|
// 判断是否为顺子(赖子补齐)
|
|
|
private static boolean isStraightWithWild(List<Integer> points, int wildCount) {
|
|
|
// 特例1:A-2-3-4-5
|
|
@@ -1081,10 +1187,45 @@ public final class GDUtils {
|
|
|
return gaps <= wildCount;
|
|
|
}
|
|
|
|
|
|
- // 判断是否为同花顺(可选规则)
|
|
|
- private static boolean isRoyalFlush(int[] cards, int wildCount) {
|
|
|
- return Arrays.stream(cards).map(card -> card & 0xF0).distinct().count() == 1
|
|
|
- && isStraightWithWild(Arrays.stream(cards).map(GDUtils::getCardPoint).sorted().boxed().collect(Collectors.toList()), wildCount);
|
|
|
+ /**
|
|
|
+ * 判断是否为同花顺(可选规则)
|
|
|
+ *
|
|
|
+ * @param cards 牌的数组
|
|
|
+ * @param laiziCardPoints 赖子牌点
|
|
|
+ * @return true 如果是同花顺,false 否则
|
|
|
+ */
|
|
|
+ private static boolean isRoyalFlush(int[] cards, int laiziCardPoints) {
|
|
|
+ // 提取牌的花色和点数
|
|
|
+ List<Integer> suits = new ArrayList<>();
|
|
|
+ List<Integer> points = new ArrayList<>();
|
|
|
+ int wildCount = 0;
|
|
|
+ for (int card : cards) {
|
|
|
+ if (card == laiziCardPoints) { // 赖子牌
|
|
|
+ wildCount++;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ suits.add((card & 0xF0) >> 4); // 提取花色
|
|
|
+ points.add(card & 0x0F); // 提取点数
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查花色是否相同
|
|
|
+ if (suits.stream().distinct().count() > 1) {
|
|
|
+ return false; // 花色不相同
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查牌点是否连续
|
|
|
+ Collections.sort(points);
|
|
|
+ int gaps = 0;
|
|
|
+ for (int i = 0; i < points.size() - 1; i++) {
|
|
|
+ gaps += points.get(i + 1) - points.get(i) - 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 特殊情况处理:10-J-Q-K-A
|
|
|
+ if (points.contains(10) && points.contains(11) && points.contains(12) && points.contains(13) && points.contains(14)) {
|
|
|
+ return true; // 10-J-Q-K-A
|
|
|
+ }
|
|
|
+ // 检查是否可以使用赖子牌补齐 gaps
|
|
|
+ return gaps <= wildCount;
|
|
|
}
|
|
|
|
|
|
// 测试代码
|
|
@@ -1111,8 +1252,8 @@ public final class GDUtils {
|
|
|
System.out.println(determineCardType(cards14, 0)); // STRAIGHT
|
|
|
System.out.println(determineCardType(cards15, 0)); // PAIR_SEQUENCE*/
|
|
|
int[] cards10 = {0x08, 0x18, 0x29, 0x39, 0x45}; // 五炸弹
|
|
|
-
|
|
|
- System.out.println(determineCardType(cards10, 0x45)); // FIVE_BOMB
|
|
|
+ int[] cards = {0x22, 0x23, 0x26, 0x45, 0x45}; // 红桃5-6-7-8-赖子
|
|
|
+ System.out.println(determineCardType(cards, 0x45)); // FIVE_BOMB
|
|
|
int[] cards20 = {0x02, 0x02, 0x02, 0x0e, 0x0e, 0x0e}; // A-A-A-2-2-2
|
|
|
int[] cards21 = {0x03, 0x03, 0x03, 0x02, 0x02, 0x02}; // 3-3-3-4-4-4
|
|
|
|