自定义LinkedStack实现卡牌洗牌时遇NullPointerException求助
卡牌游戏洗牌逻辑中的NullPointerException问题解决
我正在开发一款模拟「War」卡牌游戏的项目,已实现初始主牌堆,尝试使用自定义LinkedStack类完成洗牌操作。我采用将牌堆拆分为四堆,通过随机switch语句将卡牌合并为单堆的方式(类似集换式卡牌的洗牌手法),但在随机数调用处触发NullPointerException,现寻求解决帮助。
相关代码
LinkedStack<Card> pileOne = new LinkedStack<Card>(); LinkedStack<Card> pileTwo = new LinkedStack<Card>(); LinkedStack<Card> pileThree = new LinkedStack<Card>(); LinkedStack<Card> pileFour = new LinkedStack<Card>(); int origSize = this.cards.size(); for(int i = 0; i < 52; i ++) { // 52 cards in the deck (supposed to be) if(this.cards.isEmpty() == false) { pileOne.push(this.cards.peek()); this.cards.pop(); } if(this.cards.isEmpty() == false) { pileTwo.push(this.cards.peek()); this.cards.pop(); } if(this.cards.isEmpty() == false) { pileThree.push(this.cards.peek()); this.cards.pop(); } if(this.cards.isEmpty() == false) { pileFour.push(this.cards.peek()); this.cards.pop(); } } while(pileOne.size() != origSize) { int randNum = rand.nextInt(3); // <- nullpointer exception switch(randNum + 1) { case 1: if(pileTwo.isEmpty() == false) { pileOne.push(pileTwo.peek()); pileTwo.pop(); } break; case 2: if(pileThree.isEmpty() == false) { pileOne.push(pileThree.peek()); pileThree.pop(); } break; default: if(pileFour.isEmpty() == false) { pileOne.push(pileFour.peek()); pileFour.pop(); } break; } }
问题分析与解决方案
空指针核心原因
rand变量未完成实例化,处于null状态,调用nextInt()方法时必然抛出NullPointerException。直接修复步骤
在使用rand前完成实例化:- 如果是方法内局部变量,添加:
Random rand = new Random(); - 如果是类成员变量,在类中初始化:
private Random rand = new Random();
- 如果是方法内局部变量,添加:
额外优化建议
- 拆分牌堆逻辑简化:原循环固定跑52次没必要,直接根据主牌堆剩余卡牌分配更高效,避免重复空判断:
while (!this.cards.isEmpty()) { if (!this.cards.isEmpty()) pileOne.push(this.cards.pop()); if (!this.cards.isEmpty()) pileTwo.push(this.cards.pop()); if (!this.cards.isEmpty()) pileThree.push(this.cards.pop()); if (!this.cards.isEmpty()) pileFour.push(this.cards.pop()); } - 合并循环条件修正:原条件
pileOne.size() != origSize会导致死循环(当其他堆卡牌耗尽后,pileOne大小无法达到origSize),应改为只要剩余堆非空就继续:while (!pileTwo.isEmpty() || !pileThree.isEmpty() || !pileFour.isEmpty()) { // 随机合并逻辑 } - 避免无效随机:如果随机选中的堆为空,可重新生成随机数,跳过无效操作:
int randNum; do { randNum = rand.nextInt(3); } while ((randNum == 0 && pileTwo.isEmpty()) || (randNum == 1 && pileThree.isEmpty()) || (randNum == 2 && pileFour.isEmpty()));
- 拆分牌堆逻辑简化:原循环固定跑52次没必要,直接根据主牌堆剩余卡牌分配更高效,避免重复空判断:
内容的提问来源于stack exchange,提问作者Carter
相关产品推荐
相关产品推荐

