PDA

View Full Version : Simple Java Question




ScKaSx
Jan 26, 2008, 06:32 PM
Hi All,

I was following the Really Big Index Tutorial and was looking at the section on 'Enums'. I have a question about using a set of classes defined in that section for a deck of cards. The following four classes are defined (Deck.class, Card.class, Suit.class, Rank.class):

Deck.class
import java.util.*;

public class Deck {
private static Card[] cards = new Card[52];
public Deck() {
int i = 0;
for (Suit suit : Suit.values()) {
for (Rank rank : Rank.values()) {
cards[i++] = new Card(rank, suit);
}
}
}
}

Card.class
public class Card {
private final Rank rank;
private final Suit suit;

public Card(Rank rank, Suit suit) {
this.rank = rank;
this.suit = suit;
}

public Suit getSuit() {
return suit;
}

public Rank getRank() {
return rank;
}

public String toString() {
return rank + " of " + suit;
}
}

Suit.class
public enum Suit {
DIAMONDS,
CLUBS,
HEARTS,
SPADES
}

Rank.class
public enum Rank {
DEUCE, THREE, FOUR, FIVE, SIX, SEVEN,
EIGHT, NINE, TEN, JACK, QUEEN, KING, ACE
}

I want to create a main program (DisplayDeck.java) that creates a deck and lists the cards in the deck. How do I incorporate Card.toString to achieve this? Thanks.

DisplayDeck.class
import java.util.*;

public class DisplayDeck {
public static void main (String[] args) {
private static Deck deck = new Deck();
System.out.println(Card.toString) //?????
}
}

Cheers,
ScKaSx



Pring
Jan 26, 2008, 07:04 PM
I want to create a main program (DisplayDeck.java) that creates a deck and lists the cards in the deck. How do I incorporate Card.toString to achieve this? Thanks.

Cheers,
ScKaSx

You need a getCards() method in Deck which returns the array of cards. You can then do

Card[] cards = deck.getCards();

for (Card card: cards)
{
System.out.println(card); //or card.toString(), but that's implicit when you call println on any object
}

ScKaSx
Jan 26, 2008, 07:55 PM
Thanks Pring,

I added the getCard function to my Deck.java as:

public static Card[] getCards() {
return cards;
}

And now my DisplayDeck.java looks like this,

import java.util.*;

public class DisplayDeck {
public static void main(String[] args) {
Deck deck = new Deck();
Card[] cards = deck.getCards();
for (Card card: cards) {
System.out.println(card);
}
}
}

It compiles but I get the following error when I execute:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 52
at Deck.<init>(Deck2.java:9)
at DisplayDeck.main(DisplayDeck2.java:5)

Any ideas, thanks.

Cheers,
ScKaSx

Thom_Edwards
Jan 26, 2008, 10:39 PM
Just at a quick glance, I would look at when you use cards[i++] = newCard(rank, suit);. You give cards[] 52 indices, but the first card you make is cards[1] (because of i++). So, your last card is cards[52], but that is really the 53rd index since cards[] is zero-based. (cards[0] is the first card, cards[1] is the second, etc.) cards[51] is your last card, so cards[52] is out of bounds.

Try this:

cards[i] = new Card(rank, suit);
i++;

This way, the first time you go through the loop, i is still zero. Then you can increment i.

Like I said, that is just a quick glance. I may be way off.

therevolution
Jan 27, 2008, 04:24 AM
Just at a quick glance, I would look at when you use cards[i++] = newCard(rank, suit);. You give cards[] 52 indices, but the first card you make is cards[1] (because of i++). So, your last card is cards[52], but that is really the 53rd index since cards[] is zero-based. (cards[0] is the first card, cards[1] is the second, etc.) cards[51] is your last card, so cards[52] is out of bounds.

Try this:

cards[i] = new Card(rank, suit);
i++;

This way, the first time you go through the loop, i is still zero. Then you can increment i.

Like I said, that is just a quick glance. I may be way off.

Actually, 'i++' increments i after executing the statement. '++i', on the other hand, would do what you're describing. So I don't think that's the problem.

That said, I don't know why it's going out of bounds. Just thought I'd comment on the preincrement/postincrement thing. :D

Pring
Jan 27, 2008, 06:15 AM
I think I know what the problem is but I'm going to do the whole teacher thing and teach you how to debug for yourself rather than giving you the answer :)

Put some debug in your code.

Just before you instantiate your Card object in the loops in the deck put

System.out.println(i + ": Suit = " + suit + " Rank = " + rank) ;
cards[i++] = new Card(rank, suit);

This will print out to standard out exactly what card it's creating at each point.. eg "0: Diamonds, Deuce", "1: Diamonds, Three" and so on.

What you then have to do is find out what card it's trying to create before it throws the Exception. From there you should be able to see why it's failing on that card.

toddburch
Jan 27, 2008, 07:35 AM
I see the problem too.

Also, ScKaSx, instead of using & tags for your code, you should be using & tags for your code. It will preserve your indentation, which, as it happens, would give you a visual clue as to the problem.

Todd

ScKaSx
Jan 27, 2008, 02:12 PM
Thanks for your help guys, its working brilliantly now!

And Pring thanks for the debugging advice, I much prefer the the method over the answer. I had tried to do something similar but must have had the syntax wrong. Thanks again.

Cheers,
ScKaSx

Pring
Jan 27, 2008, 04:27 PM
No problem, glad you got it working.


it's an important lesson to remember for anyone learning to program properly. In order to debug you have to understand the flow of your program, one of the best ways to do this is to sprinkle output statements around your code to print the state of variables at different points. This is one of the most effective ways to find out what exactly is going wrong.

Thom_Edwards
Jan 28, 2008, 09:06 AM
Actually, 'i++' increments i after executing the statement. '++i', on the other hand, would do what you're describing. So I don't think that's the problem.

That is something I didn't know! I guess I never really even thought about it. I've always done it the way I suggested because of my ignorance. Thanks for the correction. Learn something new every day...

EdC
Jan 30, 2008, 01:03 AM
To take this a step further, you are in a unique situation to know how many objects are supposed to be in that array at all. Down the road, you should eliminate the dependency on the number 52. I'd recommend creating an ArrayList object. Add as many things to it as you like. At the end of the loop, use the ArrayList object to get a real array of the objects. You won't have to worry about how many objects your loop provides and your code is more flexible.

Before anyone else says it, this suggestion is *way* overkill for what you are trying to do here. I'm just trying to give you ideas for growth, e.g. you could reuse the algorithms to get all the cards in an Uno deck or a Magic deck or something.

Lastly, I would always tell my engineers to move the i++ to the next line outside of the array index braces. It will reduce the chance that you will do something wrong, i.e. less hours to debug your program on average. When you are starting out, System.out.println() works wonders.

Cheers.