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
相关产品推荐
相关产品推荐

