Java扑克牌顺子怎么实现

发布时间:2021-12-13 15:00:34 作者:iii
来源:亿速云 阅读:189
# Java扑克牌顺子怎么实现

## 一、问题背景与定义

在扑克牌游戏中,**顺子(Straight)**是指五张连续数字的牌型(如3-4-5-6-7)。特殊情况下,A可以视为1(A-2-3-4-5)或延续K(10-J-Q-K-A)。本文将探讨如何在Java中实现顺子的判定逻辑。

---

## 二、核心算法设计

### 2.1 输入数据表示
通常使用长度为5的整数数组表示手牌:
```java
int[] cards = {3, 5, 4, 6, 7}; // 示例顺子

2.2 关键步骤

  1. 排序数组:便于检查连续性
  2. 统计大小王(癞子):可作为任意牌
  3. 计算间隔缺口:判断是否可用癞子补全

三、基础实现代码

import java.util.Arrays;

public class PokerStraight {
    public static boolean isStraight(int[] nums) {
        // 1. 排序数组
        Arrays.sort(nums);
        
        int jokerCount = 0; // 大小王计数
        int gap = 0;        // 间隔总和
        
        // 2. 统计大小王(假设0代表大小王)
        for(int i = 0; i < nums.length; i++) {
            if(nums[i] == 0) {
                jokerCount++;
                continue;
            }
            
            // 3. 计算非王牌的间隔
            if(i > 0 && nums[i-1] != 0) {
                int diff = nums[i] - nums[i-1];
                if(diff == 0) return false; // 有对子不是顺子
                gap += diff - 1;
            }
        }
        
        // 4. 缺口可用王补全
        return gap <= jokerCount;
    }

    public static void main(String[] args) {
        System.out.println(isStraight(new int[]{1,2,3,4,5})); // true
        System.out.println(isStraight(new int[]{0,0,3,5,4})); // true
        System.out.println(isStraight(new int[]{1,2,3,4,6})); // false
    }
}

四、边界情况处理

4.1 A作为1的特殊情况

需单独处理A-2-3-4-5的顺子:

// 在排序后检查是否为A-2-3-4-5
if(nums[4] == 14) { // A记为14
    boolean lowStraight = true;
    for(int i = 0; i < 4; i++) {
        if(nums[i] != i+1) {
            lowStraight = false;
            break;
        }
    }
    if(lowStraight) return true;
}

4.2 牌面值验证

需验证输入合法性(1-13和0):

for(int num : nums) {
    if(num < 0 || num > 14) {
        throw new IllegalArgumentException("Invalid card value");
    }
}

五、性能优化方案

5.1 位运算优化

对于无大小王的情况,可用位掩码快速判断:

if(jokerCount == 0) {
    int mask = 0;
    for(int num : nums) {
        mask |= 1 << num;
    }
    // 检查是否形成5个连续1的窗口
    int pattern = 0b11111;
    while(pattern <= (1 << 14)) {
        if((mask & pattern) == pattern) return true;
        pattern <<= 1;
    }
    return false;
}

5.2 提前终止条件

排序后若发现: - 最大牌与最小牌差值≥5(无王时) - 重复非王牌 可直接返回false。


六、单元测试用例

import org.junit.Test;
import static org.junit.Assert.*;

public class PokerStraightTest {
    @Test
    public void testNormalStraight() {
        assertTrue(PokerStraight.isStraight(new int[]{1,2,3,4,5}));
    }
    
    @Test
    public void testWithJokers() {
        assertTrue(PokerStraight.isStraight(new int[]{0,0,7,8,10}));
    }
    
    @Test
    public void testInvalidCases() {
        assertFalse(PokerStraight.isStraight(new int[]{1,2,3,4,6}));
        assertFalse(PokerStraight.isStraight(new int[]{1,1,2,3,4}));
    }
}

七、扩展应用场景

7.1 德州扑克规则扩展

实现德州扑克的牌型判断时,需先选出5张牌的最优组合:

// 从7张牌中找出可能的最佳顺子
public static boolean hasStraightInTexas(int[] sevenCards) {
    Arrays.sort(sevenCards);
    // 使用滑动窗口检查所有5张组合
    for(int i = 0; i <= 2; i++) {
        int[] subArray = Arrays.copyOfRange(sevenCards, i, i+5);
        if(isStraight(subArray)) return true;
    }
    return false;
}

7.2 多语言适配

相同算法可迁移到其他语言: - Python:利用collections.Counter - C++:使用std::sort和类似逻辑


八、算法复杂度分析

步骤 时间复杂度 空间复杂度
数组排序 O(nlogn) O(1)
遍历统计 O(n) O(1)
位运算优化版本 O(n) O(1)

九、完整实现代码(含所有优化)

import java.util.Arrays;

public class AdvancedPokerStraight {
    public static boolean isStraight(int[] nums) {
        if(nums.length != 5) return false;
        
        Arrays.sort(nums);
        
        // 边界检查
        if(nums[4] > 14 || nums[0] < 0) return false;
        
        // 特殊处理A-2-3-4-5
        if(nums[4] == 14 && nums[0] == 2 && nums[1] == 3 
           && nums[2] == 4 && nums[3] == 5) {
            return true;
        }
        
        int joker = 0, gap = 0;
        for(int i = 0; i < nums.length; i++) {
            if(nums[i] == 0) {
                joker++;
                continue;
            }
            if(i > 0 && nums[i-1] != 0) {
                if(nums[i] == nums[i-1]) return false;
                gap += nums[i] - nums[i-1] - 1;
            }
        }
        return gap <= joker;
    }
}

十、总结与延伸思考

  1. 核心要点:排序+缺口计算是判定顺子的通用方法
  2. 扩展方向
    • 支持更多扑克牌型(同花顺、四条等)
    • 实现扑克的胜率计算
    • 网络扑克游戏的服务器端验证

通过这个案例,我们不仅掌握了顺子判断算法,更学习了如何: - 处理游戏规则的特殊边界 - 进行渐进式的性能优化 - 设计严谨的测试用例 “`

(注:实际字数为约1800字,核心内容已完整覆盖。可通过扩展测试用例和性能对比部分进一步增加字数)

推荐阅读:
  1. 如何基于Python实现扑克牌
  2. java如何实现扑克牌分发功能

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

java

上一篇:怎么给容器服务的Docker增加数据盘

下一篇:centos7中如何安装使用Docker

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》