You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

自定义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;
    }           
}

问题分析与解决方案

  1. 空指针核心原因
    rand变量未完成实例化,处于null状态,调用nextInt()方法时必然抛出NullPointerException。

  2. 直接修复步骤
    在使用rand前完成实例化:

    • 如果是方法内局部变量,添加:
      Random rand = new Random();
      
    • 如果是类成员变量,在类中初始化:
      private Random rand = new Random();
      
  3. 额外优化建议

    • 拆分牌堆逻辑简化:原循环固定跑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()));
      

内容的提问来源于stack exchange,提问作者Carter

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 00:18:19