You are on the right track but it will be a whole lot easier of you keep it all as object-oriented as possible.
Each playing card will have a Suit
and Rank
, and they are a range of predefined values. It makes sense to make them each enum values like so:
public enum PlayingCardSuit
{
None(0),
Spades(1),
Diamonds(2),
Hearts(3),
Clubs(4);
private int suit;
private PlayingCardSuit(int suit)
{
this.suit = suit;
}
}
public enum PlayingCardRank
{
None(0),
Ace(1),
Two(2),
Three(3),
Four(4),
Five(5),
Size(6),
Seven(7),
Eight(8),
Nine(9),
Ten(10),
Jack(11),
Queen(12),
King(13);
private int rank;
private PlayingCardRank(int rank)
{
this.rank = rank;
}
}
Now, you can have a Card
class which represents the Suit
and Rank
together. I also use a UUID
to assign each card a randomized unique ID value. This makes it much easier to shuffle them by sorting on the UUID
rather than do some complex ordering.
Here's the PlayingCard
class:
import java.util.*;
public final class PlayingCard
{
private UUID id;
private PlayingCardSuit suit;
private PlayingCardRank rank;
public PlayingCard(PlayingCardSuit suit, PlayingCardRank rank)
{
this.id = UUID.randomUUID();
this.suit = suit;
this.rank = rank;
}
public UUID id()
{
return this.id;
}
public void setId(UUID id)
{
this.id = id;
}
public PlayingCardSuit suit()
{
return this.suit;
}
public PlayingCardRank rank()
{
return this.rank;
}
public String toString()
{
return String.format("%s of %s", this.rank, this.suit);
}
}
Now a Deck
is merely a fancy wrapper around a collection of Card
s, with methods like shuffle()
and drawCard()
. It being its own class rather than an array is you get to encapsulate all the management from within and not have to worry about keeping track of 'which cards are left.' It does all that using a Stack
collection.
import java.util.*;
public final class PlayingCardDeck
{
private Stack<PlayingCard> deck;
public PlayingCardDeck()
{
initializeDeck();
shuffle();
}
private void initializeDeck()
{
deck = new Stack<PlayingCard>();
for(final PlayingCardSuit suit : EnumSet.allOf(PlayingCardSuit.class))
{
// Skip the 'None' suit.
if(suit == PlayingCardSuit.None) continue;
for(final PlayingCardRank rank : EnumSet.allOf(PlayingCardRank.class))
{
// Skip the 'None' rank card.
if(rank == PlayingCardRank.None) continue;
PlayingCard card = new PlayingCard(suit, rank);
deck.push(card);
}
}
}
public int size()
{
return deck.size();
}
public void shuffle()
{
// Generate new UUIDs to randomize.
for(final PlayingCard card : deck)
card.setId(UUID.randomUUID());
// Sort the deck based on the card UUID for randomization.
Collections.sort(deck, new Comparator<PlayingCard>()
{
public int compare(PlayingCard a, PlayingCard b)
{
UUID aID = a.id();
UUID bID = b.id();
return aID.compareTo(bID);
}
});
}
public PlayingCard drawCard()
{
return deck.pop();
}
}
It will generate all 52 cards of each suit and rank when created. It will also shuffle them (and can be shuffled again later). When you draw a card via drawCard()
, it will remove the card from the top of the deck.
This may seem like overkill, but it's really organized approach and will make your life a lot easier when multiple decks come into play.
Here's the little driver class I had made to test:
public static void main(String[] args)
{
Untitled program = new Untitled();
program.run();
}
public void run()
{
PlayingCardDeck deck = new PlayingCardDeck();
System.out.println(String.format("Deck has %d cards in it.", deck.size()));
int i = 0;
while(deck.size() > 0)
{
PlayingCard card = deck.drawCard();
System.out.println(String.format("[Card %2d]: Drew the %s card.", (++i), card.toString()));
}
System.out.println("Deck is empty.");
}
And the output (randomized):
Deck has 52 cards in it.
[Card 1]: Drew the Queen of Diamonds card.
[Card 2]: Drew the Eight of Clubs card.
[Card 3]: Drew the King of Clubs card.
[Card 4]: Drew the Queen of Hearts card.
[Card 5]: Drew the Four of Clubs card.
[Card 6]: Drew the Three of Diamonds card.
[Card 7]: Drew the Nine of Diamonds card.
[Card 8]: Drew the Ace of Diamonds card.
[Card 9]: Drew the Seven of Spades card.
[Card 10]: Drew the Two of Hearts card.
[Card 11]: Drew the Nine of Hearts card.
[Card 12]: Drew the Size of Clubs card.
[Card 13]: Drew the Jack of Diamonds card.
[Card 14]: Drew the Size of Hearts card.
[Card 15]: Drew the Three of Clubs card.
[Card 16]: Drew the Three of Spades card.
[Card 17]: Drew the Ten of Spades card.
[Card 18]: Drew the Jack of Hearts card.
[Card 19]: Drew the Five of Clubs card.
[Card 20]: Drew the Seven of Clubs card.
[Card 21]: Drew the Size of Diamonds card.
[Card 22]: Drew the Ten of Hearts card.
[Card 23]: Drew the Three of Hearts card.
[Card 24]: Drew the Ace of Spades card.
[Card 25]: Drew the Four of Hearts card.
[Card 26]: Drew the Eight of Diamonds card.
[Card 27]: Drew the Ace of Clubs card.
[Card 28]: Drew the Two of Clubs card.
[Card 29]: Drew the Nine of Spades card.
[Card 30]: Drew the Jack of Spades card.
[Card 31]: Drew the Ace of Hearts card.
[Card 32]: Drew the Seven of Hearts card.
[Card 33]: Drew the Five of Hearts card.
[Card 34]: Drew the Eight of Spades card.
[Card 35]: Drew the King of Hearts card.
[Card 36]: Drew the Jack of Clubs card.
[Card 37]: Drew the Size of Spades card.
[Card 38]: Drew the Five of Spades card.
[Card 39]: Drew the Five of Diamonds card.
[Card 40]: Drew the King of Diamonds card.
[Card 41]: Drew the Ten of Clubs card.
[Card 42]: Drew the Queen of Spades card.
[Card 43]: Drew the King of Spades card.
[Card 44]: Drew the Seven of Diamonds card.
[Card 45]: Drew the Four of Spades card.
[Card 46]: Drew the Queen of Clubs card.
[Card 47]: Drew the Ten of Diamonds card.
[Card 48]: Drew the Eight of Hearts card.
[Card 49]: Drew the Four of Diamonds card.
[Card 50]: Drew the Two of Diamonds card.
[Card 51]: Drew the Nine of Clubs card.
[Card 52]: Drew the Two of Spades card.
Deck is empty.