I'm trying to make a small program that creates a deck of cards. All of the code compiles, but when I try to run the tester class, it says:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 52
at cardDeck.giveValue(cardDeck.java:23)
at CardTest.main(CardTest.java:6)
I've only been using java for a few weeks, so I don't know exactly where the problem is, or how to fix it. I'd appreciate any help.
Card class:
public class Card {
private int value;
private String name;
private String suit;
public void setValue(int v){
value = v;
}
public int getValue(){
return value;
}
public void setName(String n){
name = n;
}
public String getName(){
return name;
}
public void setSuit(String s){
suit = s;
}
public String getSuit(){
return suit;
}
}
Card Deck class:
public class cardDeck {
int [] values = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
String[] names = {"Two", "Three", "Four", "Five", "Six", "Seven", "Eight", "Nine", "Ten", "King", "Queen", "Jack", "Ace"};
String[] suits = {"Clubs", "Spades", "Hearts", "Diamonds"};
public Card[] giveName (Card[] d){
int j = 0;
while(j < 52){
for(String k: names){
d[j] = new Card();
d[j].setName(k);
j++;
}
}
return d;
}
public Card[] giveValue(Card[] e){
int a = 0;
while(a < 52){
for(int m: values){
if((e[a].getName().equals("King")) || (e[a].getName().equals("Ten")) || (e[a].getName().equals("Queen")) || (e[a].getName().equals("Jack"))){
e[a].setValue(10);
a++;
}else if(e[a].getName().equals("Ace")){
e[a].setValue(11);
a++;
}else{
e[a].setValue(m);
a++;
}
}
}
return e;
}
public Card[] giveSuit(Card[] f){
int b = 0;
while(b < 52){
for(String l:suits){
f[b].setSuit(l);
b++;
}
}
return f;
}
}
Tester class:
class CardTest {
public static void main(String[] args){
Card[] deck = new Card[52];
cardDeck playingCards = new cardDeck();
playingCards.giveName(deck);
playingCards.giveValue(deck);
playingCards.giveSuit(deck);
for(int q = 0; q < 52; q++){
System.out.println("A "+deck[q].getName()+ " of " +deck[q].getSuit()+ " " +deck[q].getValue());
}
}
}
Look at your nested loop:
while(a < 52) {
for(int m: values) {
// Various things which increment a
}
}
You're incrementing a
lots of times for each iteration of the while
loop... which means you'll easily end up with a
being 52 during the loop, at which point you'll get an exception. You've got the same problem in other methods too, such as giveSuit
and giveName
. The other methods just about work because your other arrays have lengths which divide exactly into 52 - whereas values
has only 10 elements, so after 5 iterations of the while
loop you'll be on a = 50
... so after 3 more iterations of the nested loop, you'll blow up. But why do you have nested loops at all?
While it would be possible to fix your existing giveValue
method, it would be much simpler to rewrite it as:
public Card[] giveValue(Card[] e) {
for (int i = 0; i < 52; i++) {
int rawValue = (i % 13) + 2; // Value 2-14
if (rawValue == 14) {
e[i].setValue(11); // The ace
} else if (rawValue >= 11 && rawValue <= 13) {
e[i].setValue(10); // Jack to King
} else {
e[i].setValue(rawValue);
}
}
return e;
}
I would actually suggest a redesign - I suggest you make your Card
class immutable. Think of real life - a card never changes after it's been created, so why should one of your Card
objects? Just pass the value/suit/name into the constructor, and store them in final
fields.
(Additionally, I suggest you fix the name of your cardDeck
class to follow Java naming conventions, and when you have fields which aren't logically part of the state of a particular instance - such as your values
, suits
and names
fields - you make them static.)
See more on this question at Stackoverflow