得到NullPointerException并且不知道为什么。战争游戏

时间:2014-11-08 12:53:19

标签: java nullpointerexception

我正在写纸牌游戏" war"。 我的课程:

主要DeckOfCardsCard

import java.util.*;

public class DeckOfCards
{
        private ArrayList<Card> deck;
        private static final Random randomNumbers=new Random();

        public DeckOfCards()
        {
                deck=new ArrayList<Card>();
        }
        public DeckOfCards(int cardsFaces) //normal deck has 4 faces
        {
                deck=new ArrayList<Card>();
                for (int i=0;i<cardsFaces;i++)
                        for (int j=2;j<=14;j++)
                        {
                                deck.add(new Card(j));                         
                        }
        }
        public void shuffle()
        {
                for(int first=0;first<deck.size();first++)
                {
                        int second =randomNumbers.nextInt(deck.size()-1);
                        Card temp=deck.get(first);
                        deck.set(first, deck.get(second));
                        deck.set(second, temp);
                }
        }
        public Card dealCard()
        {
                if (deck.isEmpty())
                {
                        System.out.println("trying to deal from empty deck");
                        return null;
                }
                else
                        return deck.remove(0);

        }
        public ArrayList<Card> getDeck()
        {
                return deck;
        }
        public String toString()
        {
                String s="";
                for (int i=0;i<deck.size();i++)
                {
                        s=s+deck.get(i)+" ";
                }
                return s;
        }
        public boolean isEmpty()
        {
                return (deck.isEmpty());
        }
        public void addCard(Card c)
        {
                deck.add(c);
        }
        public int size()
        {
                return deck.size();
        }
}

public class Card
{
        private int value;//2-14 , 14 is ace.
        public Card(int value)
        {
                this.value=value;
        }
        public int getValue()
        {
                return value;
        }
        public String toString()
        {
                return Integer.toString(value);
        }
}

public class Main
{

        public static void main(String[] args)
        {
                DeckOfCards gameDeck =new DeckOfCards(1);
                gameDeck.shuffle();
                DeckOfCards p1Deck=new DeckOfCards();//player 1 deck
                DeckOfCards p2Deck=new DeckOfCards(); //player 2 deck
                DeckOfCards sideDeck=new DeckOfCards();
                Card p1Card;
                Card p2Card;
                boolean gameOver=false;
                while(!gameDeck.isEmpty()) //dealing cards to players
                {
                        p1Deck.addCard(gameDeck.dealCard());
                        p2Deck.addCard(gameDeck.dealCard());
                }
                while(gameOver==false)
                {
                        p1Card=p1Deck.dealCard();
                        p2Card=p2Deck.dealCard();
                        System.out.println("p1card="+p1Card.getValue()+" p2card="+p2Card.getValue());
                        if(p1Card.getValue()>p2Card.getValue()) //player 1 won the cards
                        {
                                p1Deck.addCard(p1Card);
                                p1Deck.addCard(p2Card);
                                while(!sideDeck.isEmpty())
                                        p1Deck.addCard(sideDeck.dealCard());
                                System.out.println("player 1 won the cards,deck sizes: p1:"+p1Deck.size()+" p2:"+p2Deck.size());
                        }
                        if(p2Card.getValue()>p1Card.getValue()) //player 2 won the cards
                        {
                                p2Deck.addCard(p1Card);
                                p2Deck.addCard(p2Card);
                                while(!sideDeck.isEmpty())
                                        p2Deck.addCard(sideDeck.dealCard());
                                System.out.println("player 2 won the cards,deck sizes: p1:"+p1Deck.size()+" p2:"+p2Deck.size());
                        }
                        while(p1Card.getValue()==p2Card.getValue()) //war
                        {
                                System.out.println("war");
                                sideDeck.addCard(p1Card);
                                sideDeck.addCard(p2Card);
                                if(p1Deck.size()>3 && p2Deck.size()>3)
                                {
                                        for(int i=0;i<2;i++)
                                        {
                                                sideDeck.addCard(p1Deck.dealCard());
                                                sideDeck.addCard(p2Deck.dealCard());
                                        }
                                }
                                else
                                {
                                        winner(p1Deck,p2Deck,true);
                                }

                        }
                        if(winner(p1Deck,p2Deck,false))
                                gameOver=true;
                }

        }
        public static boolean winner(DeckOfCards p1Deck,DeckOfCards p2Deck,boolean war)
        {
                if(p1Deck.isEmpty()|| p1Deck.isEmpty())
                {
                        if(p1Deck.isEmpty())
                                System.out.println("player 2 is the winner");
                        else
                                System.out.println("player 1 is the winner");
                        return true;
                }
                if (p1Deck.size()<3 && p2Deck.size()<3 && war==true)
                {
                        System.out.println("it's a tie");
                        return true;
                }
                return false;
        }

}

我得到NullPointerException并且不知道为什么。 当我按下异常时它会引导我去行:

System.out.println("p1card="+p1Card.getValue()+" p2card="+p2Card.getValue());

当试图调试时,我理解有时由于某种原因我的dealCard函数返回null,尽管我尝试处理的套牌不是空的。

2输出例如:

输出1:

trying to deal from empty deck
p1card=10 p2card=5
player 1 won the cards,deck sizes: p1:8 p2:6
p1card=13 p2card=14
player 2 won the cards,deck sizes: p1:7 p2:7
p1card=11 p2card=2
player 1 won the cards,deck sizes: p1:8 p2:6
p1card=9 p2card=12
player 2 won the cards,deck sizes: p1:7 p2:7
p1card=6 p2card=7
player 2 won the cards,deck sizes: p1:6 p2:8
p1card=4 p2card=8
player 2 won the cards,deck sizes: p1:5 p2:9
Exception in thread "main" java.lang.NullPointerException
    at mmn11q2.Main.main(Main.java:25)

输出2:

trying to deal from empty deck
p1card=8 p2card=10
player 2 won the cards,deck sizes: p1:6 p2:8
p1card=7 p2card=13
player 2 won the cards,deck sizes: p1:5 p2:9
p1card=6 p2card=4
player 1 won the cards,deck sizes: p1:6 p2:8
p1card=12 p2card=11
player 1 won the cards,deck sizes: p1:7 p2:7
p1card=5 p2card=3
player 1 won the cards,deck sizes: p1:8 p2:6
p1card=2 p2card=14
player 2 won the cards,deck sizes: p1:7 p2:7
Exception in thread "main" java.lang.NullPointerException
    at mmn11q2.Main.main(Main.java:25)

2 个答案:

答案 0 :(得分:0)

查看您自己的错误消息

游戏从套牌中的无效状态开始,如#34所示;试图从空白牌组处理#34;在开始的输出中。

while(!gameDeck.isEmpty()) //dealing cards to players
    {
                        p1Deck.addCard(gameDeck.dealCard());
                        p2Deck.addCard(gameDeck.dealCard());
    }

检查牌组是否有 牌,但尝试交易两张牌 - 因为源牌组有奇数牌,这导致p2Deck有牌入场无。一旦访问此条目(作为该套牌中的最后一项,您将获得例外。

单元测试

防止此类问题的有用通用解决方案是尝试正确的测试。

例如,测试一下&#39; shuffle&#39;重复洗牌的方法,然后检查牌组是否突然不包含Null值作为其中一项。

此外,防御性编程有帮助 - 每个函数都应该验证输入是否有效,以防止其他地方的错误导致该类中的无效状态。如果你的addCard方法会检查参数是否是有效的卡(而不是None),那么这个bug显然是可见的。

在dealCard函数中进行检查,以验证它是否意外地从数组中处理Null值 - 这是另一个可能的错误来源。

DRY

&#34;不要重复自己&#34;是一个有用的口头禅。例如,您的代码有多个地方,如&#34; p1Deck.addCard(gameDeck.dealCard());&#34;,并且每个这样的地方都有一个单独的检查,如果源平台不是空的,否则会是一个错误并返回一个空值。这表明你可能需要一种尝试在两个套牌之间传递卡片的方法,如果一个卡片变空,就不会改变它们。

答案 1 :(得分:0)

您的dealCard方法会从Deck

中删除卡片
public Card dealCard()
{
    if (deck.isEmpty())
    {
        System.out.println("trying to deal from empty deck");
        return null;
    }
    else
        return deck.remove(0); // <<<< here

}

所以在一些dealCard次调用之后,牌组是空的。当dealCard为空(见上文)时,null会返回Deck,因此是NPE。