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

Java实现WAR纸牌游戏调用deck.draw()时触发空指针异常求助

Java WAR纸牌游戏报错排查与修复方案

你遇到的deck.draw相关报错及逻辑异常,是多个类的基础实现错误共同导致的,以下是具体问题和可直接运行的修复代码:

核心问题汇总

  • 空指针直接诱因:Player类构造方法未初始化hand列表,直接调用p1.hand.add()时hand为null,异常并非出在draw方法本身
  • Card类字段错误使用static修饰:所有卡牌实例共享同一个花色、牌面值,生成的52张牌数值完全一致,无法正常比较大小
  • 发牌循环边界错误:原发牌循环从i=1开始、判定条件为i<26,仅执行25轮发牌,每人只拿到25张牌,后续翻牌循环执行26轮时,会因手牌为空触发索引越界
  • Card类取值逻辑完全失效:原代码写的固定循环返回常量值,没有为单张牌保存独立的花色、点数属性
  • 冗余无效代码:Deck类中定义的Card[] deck = new Card[52]全程未被使用,属于多余字段

逐类修复代码

1. Card类修复

移除实例字段的static修饰,构造方法正确赋值单张牌属性,删除错误的固定值计算方法,修正卡牌描述输出逻辑:

package warCardGame;

public class Card {

    public static final String[] SUIT = {"Clubs", "Diamonds", "Hearts", "Spades"};
    public static final String[] RANK = {"2", "3", "4", "5", "6", "7", "8", "9", "10", "Jack", "Queen", "King", "Ace"};
    
    // 每个卡牌实例独立存储花色索引、牌面大小值
    private int suitIndex;
    private int rankValue;

    public Card(int suitIndex, int rankValue) {
        this.suitIndex = suitIndex;
        this.rankValue = rankValue;
    }

    public void describe() {
        System.out.printf("The current card is %s of %s.%n", RANK[rankValue - 2], SUIT[suitIndex]);
    }

    public int getSuitIndex() {
        return suitIndex;
    }

    public void setSuitIndex(int suitIndex) {
        this.suitIndex = suitIndex;
    }

    public int getRankValue() {
        return rankValue;
    }

    public void setRankValue(int rankValue) {
        this.rankValue = rankValue;
    }
}

注:牌面大小值从2到14依次对应2到Ace,无需额外写转换逻辑即可直接比较大小

2. Deck类修复

删除无用的冗余数组字段,保留原有洗牌、抽牌逻辑即可:

package warCardGame;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class Deck {
    List<Card> cards = new ArrayList<Card>();
    
    public Deck() {
        for(int i = 0; i < 4; i++) { // 遍历4种花色
            for(int j = 2; j <= 14; j++) { // 每个花色生成2到Ace共13张牌
                cards.add(new Card(i, j));
            }
        }
    }

    public List<Card> getCards(){
        return cards;
    }
    
    public void setCards(List<Card> cards) {
        this.cards = cards;
    }
    
    public void shuffle() {
        Collections.shuffle(cards);
    }

    public Card draw() {
        if(cards.isEmpty()) {
            return null;
        }
        Card topCard = cards.get(0);
        cards.remove(0);
        return topCard;
    }
}

3. Player类修复

构造方法中初始化手牌列表,flip、draw方法增加空判断避免越界:

package warCardGame;

import java.util.ArrayList;
import java.util.List;

public class Player {
    
    List<Card> hand;
    int score;
    String name;
    
    public Player(String name) {
        this.score = 0;
        this.name = name;
        // 关键修复:初始化手牌列表,避免空指针
        this.hand = new ArrayList<>();
    }

    public void describe() {
        System.out.println(name + " has a score of " + score + " !");
        for(Card card : hand) {
            card.describe();
        }
    }
    
    public List<Card> getHand() {
        return hand;
    }
    public void setHand(List<Card> hand) {
        this.hand = hand;
    }
    public int getScore() {
        return score;
    }
    public void setScore(int score) {
        this.score = score;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Card flip() {
        if(hand.isEmpty()){
            return null;
        }
        Card topCard = hand.get(0);
        hand.remove(0);
        return topCard;
    }
    
    public void draw(Deck deck) {
        Card card = deck.draw();
        if(card != null){
            hand.add(card);     
        }
    }
    
    public void incrementScore() {
        score +=1;
    }
}

4. App主类修复

修正发牌循环边界,调用正确的牌值比较方法,增加空判断避免运行时异常:

package warCardGame;

public class App {

    public static void main(String[] args) {
        Deck deck = new Deck();
        deck.shuffle();
        
        Player p1 = new Player("Harvey");
        Player p2 = new Player("Dee");
        
        // 修复循环边界:发26轮,每人26张牌刚好用完52张牌组
        for(int i = 0; i < 26; i++) {
            p1.draw(deck);
            p2.draw(deck);
        }

        for(int i = 0; i < 26; i++) {
            Card p1Card = p1.flip();
            Card p2Card = p2.flip();
            
            if(p1Card == null || p2Card == null){
                System.out.println("Not enough cards to flip!");
                break;
            }

            if(p1Card.getRankValue() > p2Card.getRankValue()) {
                p1.incrementScore();
            } else if(p2Card.getRankValue() > p1Card.getRankValue()) {
                p2.incrementScore();
            } else {
                System.out.println("Round tie!");
            }
        }

        System.out.println("The final score for " + p1.name +" is " + p1.score);
        System.out.println("The final score for " + p2.name +" is " + p2.score);
        if(p1.score > p2.score) {
            System.out.println("The winner today is " + p1.name + " !");
        }else if(p2.score > p1.score) {
            System.out.println("The winner today is " + p2.name + " !");
        }else {
            System.out.println("The final score is a DRAW! A rematch is needed!");
        }
    }
}

修复后效果

替换上述代码后可直接运行,不会再出现空指针、索引越界报错,牌值比较、计分、胜负判定逻辑均可正常执行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 22:48:26