您好,登录后才能下订单哦!
密码登录
登录注册
点击 登录注册 即表示同意《亿速云用户服务条款》
# 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}; // 示例顺子
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
}
}
需单独处理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;
}
需验证输入合法性(1-13和0):
for(int num : nums) {
if(num < 0 || num > 14) {
throw new IllegalArgumentException("Invalid card value");
}
}
对于无大小王的情况,可用位掩码快速判断:
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(无王时) - 重复非王牌 可直接返回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}));
}
}
实现德州扑克的牌型判断时,需先选出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;
}
相同算法可迁移到其他语言:
- 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;
}
}
通过这个案例,我们不仅掌握了顺子判断算法,更学习了如何: - 处理游戏规则的特殊边界 - 进行渐进式的性能优化 - 设计严谨的测试用例 “`
(注:实际字数为约1800字,核心内容已完整覆盖。可通过扩展测试用例和性能对比部分进一步增加字数)
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。