6

this is my first question ever. Just to clarify, I did check to see if there were any questions that could have helped me before asking this. Apologies in advance if I do anything incorrectly, I'm new.

Anyways, for my AP CS class I must make a deck a cards and print it out in the text window. I believe I am very close to being finished. As the title says, in general how do I create a deck of cards with a focus on static arrays? But furthermore (After the error I ask about below is solved), when looking at the code I have produced so far, is that the correct way to do it?

Here is the given code (meaning this can not be changed):

public class Card
{
   private String suit;
   private String rank;
   private int value;

   public Card(String s, String r, int v)
   {
      suit = s;
      rank = r;
      value = v;
   }

   public String getSuit()       { return suit; }
   public String getRank()       { return rank; }
   public int getValue()         { return value; }

   public void setSuit(String s) { suit = s; }
   public void setRank(String r) { rank = r; }
   public void setValue(int v)   { value = v; } 

   public String toString()
   {
      return "[" + suit + ", " + rank + ", " + value + "]";
   }
}

And here is the what I have coded so far:

public class Lab11bst
{
    public static void main(String[] args)
    {
      Deck deck = new Deck();
      System.out.println(deck);
    }
}


class Deck
{
   private int numberOfCards;
   private Card [] cards;
   private String [] suits = {"Clubs","Diamonds","Hearts","Spades"};
   private String rank;
   private int value;


   public Deck() // This creates a deck of 52 playing cards.
   {
      numberOfCards = 52;
      cards = new Card[52];
      for ( int suit = 0; suit <= 3; suit++ )
      {
         String [] ranks = {"Two","Three","Four","Five","Six","Seven","Eight","Nine","Ten"};
         for ( int rank = 1; rank <= 13; rank++ )
         {
            if (rank == 1)
            {
               this.rank = "Ace";
            }
            else if (rank == 11)
            {
               this.rank = "Jack";
            }
            else if (rank == 12)
            {
               this.rank = "Queen";
            }
            else if (rank == 13)
            {
               this.rank = "King";
            }
            else
            {
               this.rank = "" + ranks[rank];
            }
            for ( int value = 1; value <= 10; value++ )
            {
               if (this.rank == "Ace")
               {
                  value = 1;
               }
               else if (this.rank == "Jack")
               {
                  value = 10;
               }
               else if (this.rank == "Queen")
               {
                  value = 10;
               }
               else if (this.rank == "King")
               {
                  value = 10;
               }
               else
               {
                  this.value = value;
               }
               cards [numberOfCards] = new Card(suits[suit],this.rank,value);
               numberOfCards ++;
            }
         }
      }
   }
}

Looking at my code, I'm pretty sure there is a better way to get rid of all those if statements and make it all more short and concise. My sort-of third question (which may be necessary/might help to solve before answering the main two questions) is how do I fix this error when I run the program?:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 52
    at Deck.<init>(Lab11bst.java:89)
    at Lab11bst.main(Lab11bst.java:5)

Thank you very much in advance.

  • 1
    Hi and welcome! Nice way to start, your question is well done (I've upvoted for that). I see the row with error is 89, can you tell me which is the corresponding code? Remember that an array is zero based, so array[3] will have three index, 0, 1, 2 – Leviand Jul 25 '18 at 07:31
  • Ahh, thank you! The corresponding code for row 89 is "cards [numberOfCards] = new Card(suits[suit],this.rank,value);". –  Jul 25 '18 at 07:39
  • Once you fixed this error, you are going to run into the same error at `this.rank = "" + ranks[rank];` Because it is called with number `2-10` while the index of `ranks` runs from `0-8`. You should change this to `this.rank = "" + ranks[rank-2];` to fix that offset. –  Jul 25 '18 at 07:40
  • im currently optimizing and fixing your code, is it correct that the card "Two" has a value of 1 or a value of 2? – Instinct Jul 25 '18 at 07:45
  • Card 2 should have a value of 2. Ace's have a value of 1. –  Jul 25 '18 at 07:53

5 Answers5

1

You have set the 'numberOfCards = 52;' when initial the Deck. After that, when you need to new Card, you call numberOfCards++ as the index of array. But the array just initial with 52. So you meet this problem.

Jack Hu
  • 11
  • 1
  • 2
0

It's quite simple. You got a variable numberOfCards which is 52 at the start. If you go through the for-loop you're trying to get the 52 index from the cards array. So that will throw your ArrayIndexOutOfBoundsException.

The first element in an array is the 0 index not the 1 index.

Instead of 52 you should start at 51 so you doesn't get this error. There is one more thing if you increment the numberOfCards variable it will still throw that exception.

To print each card after the creation I would like to do some changes:

...
Card createdCard  = new Card(suits[suit], this.rank, value);
System.out.println(createdCard); //you can also do System.out.println(createdCard.toString());
cards[numberOfCards] = createdCard;
...

To print all created cards after they were created you can do this:

for(Card card : cards) {
    System.out.println(card);
}

System.out.println() will call the overriden toString() method in your Card class

CodeMatrix
  • 2,124
  • 1
  • 18
  • 30
  • 1
    As a point of clarification as well: the OP should either start with `numberOfCards = 0` and increment until 51 is reached, or start at 51 and decrement until 0 is reached to avoid the exception to reoccur. –  Jul 25 '18 at 07:38
  • Thank you, that did help. However, another unforeseen question arose which is why when each card is created, why doesn't it print the card each time as well with the "String toString" method? –  Jul 25 '18 at 07:57
  • You never call it? The only time you call print - is on Deck - but Deck doesn't have a defined toString method - as such, it prints the default representation Deck@1540e19d (In other words - Type@somehash) – Worthless Jul 25 '18 at 08:07
  • @ToheedMahmood I've added an example how to print the card after it has been created – CodeMatrix Jul 25 '18 at 08:08
0

The first problem is as pointed out by CodeMatrix - wrong starting point, you should start array index at 0. On the other hand - you increment the index of 52 item array 4*13*10 (3 loops) times - thats 520 increments. Thats why you will always jump out of range.

Worthless
  • 531
  • 3
  • 7
  • I don't know if I'm allowed to have duplicate comments to different people, so I'll just request that you see my comment to CodeMatrix. (Also btw, your answer helped a ton. Thank you.) –  Jul 25 '18 at 07:59
0

I sadly found few logical errors, especially with the numberOfCards int that you used as the index for the cards array. As a result, I have optimized and fixed your class Deck, it works with the main method and class Card you have created:

class Deck {
    private int numberOfCards = 52;
    private Card[] cards;

    private String[] suits = { "Clubs", "Diamonds", "Hearts", "Spades" };
    String[] ranks = { "Ace", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Jack", "Queen",
            "King" };
    int[] values = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10 };

    private String rank;
    private int value;

    public Deck() // This creates a deck of 52 playing cards.
    {
        cards = new Card[numberOfCards];
        int currentCardId = 0;
        for (int suit = 0; suit <= 3; suit++) {
            for (int rank = 0; rank <= 12; rank++) {
                this.rank = "" + ranks[rank];
                this.value = values[rank];

                cards[currentCardId] = new Card(suits[suit], this.rank, value);
                System.out.println(cards[currentCardId].toString()); //print out the cards .toString() as it was added to the array
                currentCardId++;
            }
        }
    }
}

It fills up the Card[] cards, feel free to test it out by using a getter and systemout. It is very adaptive to cardnaming and valuesetting, as you can fill the according arrays with whatever information you want. If you want further explanation, let me know.

Instinct
  • 321
  • 1
  • 3
  • 16
  • I had to mention this, but I scoffed when I read "I sadly found few logical errors". Spoken like a true programmer, lol. Thank you. However, how do I print each card out into the text window though? I thought when each card was created with the class provided that the "String toString" method would kick in and print it out? –  Jul 25 '18 at 08:05
  • I'm sorry if I sounded rude, I was trying to avoid exactly that. To answer your question all you need to do is to write "System.out.println(cards[currentCardId].toString());" right before "currentCardId++;" ill edit the answer to fill that in. – Instinct Jul 25 '18 at 08:10
0

Thank you everyone for providing answers, they really helped enforce some concepts for me. I wish I could accept more than just one answer for my question. Here is the complete program I ended up with (with an added "shuffle" method which I had left out earlier for simplicity).

public class Lab11bst
{
    public static void main(String[] args)
    {
      Deck deck = new Deck();
    }
}

class Deck {
   private String[] suits = { "Clubs", "Diamonds", "Hearts", "Spades" };
   String[] ranks = { "Ace", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "Jack", "Queen", "King" };
   int[] values = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10 };

   private int numberOfCards = 52; // Variable name "size" was changed to "numberOfCards" to clarify self identifier further for programmer
   private Card[] cards;
   private String rank;
   private int value;

   public Deck()
   {
      cards = new Card[numberOfCards];
      for (int suit = 0; suit <= 3; suit++) 
      {
         for (int rank = 0; rank <= 12; rank++) 
         {
            for (int values = 0; values <=12; values++)
            this.rank = ranks[rank];
            this.value = values[rank];
            numberOfCards--;
            cards[numberOfCards] = new Card(suits[suit], this.rank, value);
         }
      }

      shuffle(); // Shuffle method call. Comment out to obtain an unshuffled, ordered deck of cards.

      for(Card card : cards) 
      {
         System.out.println(card);
      }
   }

   private void shuffle()
   { 
      for (int k = 1; k < 1000; k++)
      {
         int random1 = (int) (Math.random() * 52);
         int random2 = (int) (Math.random() * 52);
         Card temp = cards[random1];
         cards[random1] = cards[random2];
         cards[random2] = temp;
      }
   }
}