【问题标题】:Writing a Blackjack program, getting nullpointerEx when I tried to printout the shuffled deck编写一个二十一点程序,当我试图打印出洗牌的牌组时得到 nullpointerEx
【发布时间】:2015-01-18 03:29:20
【问题描述】:

基本上我尝试在测试程序中运行deckTest() 以打印出洗牌后的牌组(删除deckTest 上的第一个和最后一个评论)。我得到的只是 Deck 类的 toString 方法中 answer=answer+ "\n" + deck[i].toString(); 行上的 nullpointerEx。

但是当我尝试打印出 Pre-shuffled 牌组(在 testDeck() 中打开 cmets)时,它很好。

deckTest() 中的第二条注释实际上显示了洗好的牌组的第一张牌,我认为洗牌至少有效!

感谢你们所有人,祝您 2015 年愉快! 威廉斯

有测试程序:

public class TestCard
{



    public static void main ()
    {
        Card c1=new Card(0,1);
        Card c2=new Card(3,13);
        System.out.println(c1.toString());
        System.out.println(c2.toString());

    }
    public static void deckTest()
    {
        Deck d1= new Deck();
        System.out.println(d1);

        //d1.shuffle();
        //System.out.println(d1.dealCard().toString());
        //System.out.println(d1.toString());

    }
}

有它所指的甲板类:

import java.util.Random;// for shuffing the cards


public class Deck
{


    private final int NUMOFCARDS= 52;
    private int numCards;

    private Card[] deck= new Card[53];

    /**
     * Constructor for objects of class deck
     */
    public Deck()
    {
        int c = 0;
        for (int s=0;s<=3;s++)
        {
            for (int n=1;n<=13;n++){

                deck[c]=new Card(s,n);
                c++;    
            }
        }
        numCards=NUMOFCARDS;
    }

    /**
     * Use this method to display all of the cards in the deck
     */
    public String toString()
    {
        String answer = "";

        for (int i=0;i<53;i++)
        {

            answer= answer + "\n" + deck[i].toString();
        }



        return answer;

    }

    /**
     * returns true of the current number of cards in the deck equals to 0
     */
    public boolean empty()
    {
        return numCards==0;
    }

    /**
     * pull the bottem card from the deck
     * the variable 
     */
    public Card dealCard()
    {
        if (empty())
        {
            System.out.println("the deck has run out of cards, there will be a new,preshufffled deck to continue");
            //shuffle();  //shuffle cards
            numCards=NUMOFCARDS; //reset dealPosition for dealing new deck            
        }

        numCards--;
        return deck[52-numCards];        
    }

    public void shuffle()
    {
        Random random = new Random(); // creat a random object

        Card memory;
        int randomPosition ;
        for (int i=0;i<53;i++)
        {
            randomPosition = random.nextInt(53); // assign a number between 0 to 52 as randomPosition for shuffle
            memory=deck[i];   // store the current deck[i] card 
            deck[i]=deck[randomPosition];    //assign new card to current card 
            deck[randomPosition]=memory;    //assign current card to new card 
        }

    }
}

有卡片组和测试方法所指的 Card 类:

public class Card
{
    final int JACK = 11;
    final int QUEEN = 12;
    final int KING = 13;
    final int ACE = 1;



    private int num;
    private int suit;
    final int SPADES = 0;
    final int HEARTS = 1;
    final int DIAMONDS = 2;
    final int CLUBS = 3;




    public Card(int theSuit,int theNum)
    {
        num=theNum;
        suit=theSuit;
    }

    public String showSuit()
    {
        if (suit==0)
        {
            return "Spades";
        }
        if (suit==1)
        {
            return "Hearts";
        }
        if (suit==2)
        {
            return "Diamonds";
                    }
        if (suit==3)
        {
            return "Clubs";
        }
        return "";
    }

    public String showNum()
    {
        if (num==11)
        {
            return "Jack";
        }
        if (num==12)
        {
            return "Queen";
        }
        if (num==13)
        {
            return "King";
        }
        if (num==1)
        {
            return "Ace";
        }

        return ""+num;
    }


    public String toString()
    {
        return " "+ showNum() + " of " + showSuit();
    }



    public boolean equals(Card theCard)
    {
       return theCard.toString().equals(toString());
    }

【问题讨论】:

  • 为什么Deck.deck 53 个元素长?
  • @immibis 也许删除了百搭牌,但没有删除“抽牌和梭哈扑克规则”?
  • 我问是因为,因为你只初始化了 52 个元素,其中一个是空的。而且你的 toString 不处理 null。
  • 感谢您的帮助!我很感激你的cmets

标签: java arrays nullpointerexception tostring blackjack


【解决方案1】:

问题是你正在传递你牌组的最后一张牌。 您的 Deck 构造函数中有:4 * 13 = 52 张牌。因此,您的数组将在位置 0、1、...、51 中有卡片。但在 toString 方法中,您迭代到第 52 个索引中的元素,该元素不存在!

将您的方法 toString 更改为:

@Override
public String toString() {
    String answer = "";
    for (int i = 0; i < numCards; i++) {
        answer = answer + "\n" + deck[i].toString();
    }
    return answer;
}

看看方法 dealCard 从牌组中移除了一张牌。当您移除更多卡片时,将迭代修复为 52 可能会导致 NullPointerException,因此最好使用 numCards。

此外,由于同样的原因,您的方法 shuffle 也会遭受 NullPointerException 的影响。将该方法更改为:

public void shuffle() {
    final Random random = new Random(); // creat a random object

    Card memory;
    int randomPosition;
    for (int i = 0; i < numCards; i++) {
        randomPosition = random.nextInt(numCards); // assign a number
                                                    // between 0 to
                                                    // 52 as randomPosition
                                                    // for
                                                    // shuffle
        memory = deck[i]; // store the current deck[i] card
        deck[i] = deck[randomPosition]; // assign new card to current card
        deck[randomPosition] = memory; // assign current card to new card
    }

}

【讨论】:

  • 感谢您的建议!下次编码时,我会尝试更具防御性! 2015 年过得愉快
  • 2015 年过得愉快!如果有任何答案可以解决您的问题,请记住接受一些答案:)
【解决方案2】:

变化:

/**
 * Use this method to display all of the cards in the deck
 */
public String toString()
{
    String answer = "";

    for (int i=0;i<53;i++)
    {

        answer= answer + "\n" + deck[i].toString();
    }



    return answer;

}

到这里:

/**
 * Use this method to display all of the cards in the deck
 */
public String toString()
{
    String answer = "";

    for (int i=0;i<52;i++)
    {

        answer= answer + "\n" + deck[i].toString();
    }



    return answer;

}

正如之前的海报所说,您将得到一个空指针异常,因为您只在卡片组中初始化了 0-51,但正在使用您拥有的逻辑打印 0-52。

【讨论】:

  • 我注意到我的逻辑没有任何意义,感谢您指出!最近刚学了数组,所以有时候还是觉得很难掌握
【解决方案3】:

线

answer=answer+ "\n" + deck[i].toString();

如果没有初始化deck[i],将抛出NullPointerException。使用隐式参数 null 调用 toString() 时会引发此类异常。

确保您已在此行之前初始化了 deck[i]。

查看您的代码,您似乎没有在索引 52 处初始化卡。

【讨论】:

  • 我相信我确实在构造函数 Deck() 中初始化了 deck[i]。我做了两个 for 循环来初始化牌组中的牌,并为它们分配花色 + 编号
  • 你可以通过在该行之前打印出 deck[i] 来确定。查看您的代码,似乎当您 shuffle() 您的卡片时,如果您将卡片与卡片组中较晚索引的卡片交换,则您的卡片插槽设置为空。这就是deck[i] 可能变为空的方式。但是您应该逐行检查此代码,以准确找出设置为 null 的内容/位置。
  • BlueJ 有一个内置的 STOP 功能,所以我会尝试看看是否有一个 deck[i] 为空,谢谢建议!
  • 好的,我会尝试将您的卡片组大小设置为 52,看看该错误是否消失。你可能会遇到另一个错误,因为你让其他函数依赖于硬编码的甲板大小,所以为什么不创建一个最终变量 DECK_SIZE = 52 并重构该代码以显示 DECK_SIZE 或 DECK_SIZE - 1 而不是 53 或 52。
  • 我实际上将它称为 NUMOFCARDS,但在创建它之后完全忘记了使用它。我想威廉的回应也提到了它。我会确保在未来使用更多常量!
猜你喜欢
  • 2014-10-17
  • 2020-06-18
  • 2011-02-02
  • 2019-06-03
  • 2017-08-24
  • 1970-01-01
  • 1970-01-01
  • 2018-04-02
  • 2016-04-12
相关资源
最近更新 更多