Shuffling and drawing from a deck of cards in java
Categories:
Shuffling and Drawing from a Deck of Cards in Java

Learn how to implement a virtual deck of cards in Java, including shuffling algorithms and drawing mechanics, using standard library features.
Simulating a deck of cards is a common programming exercise that touches upon fundamental concepts like data structures, randomization, and object-oriented design. This article will guide you through creating a Card
class, assembling a Deck
of cards, implementing a shuffling mechanism, and finally, drawing cards from the deck.
Designing the Card Class
The first step is to define what a single card is. A playing card typically has a Suit
(e.g., Hearts, Diamonds) and a Rank
(e.g., Ace, King, 2). We can represent these using Java enums for type safety and readability.
public enum Suit {
HEARTS, DIAMONDS, CLUBS, SPADES
}
public enum Rank {
TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, JACK, QUEEN, KING, ACE
}
public class Card {
private final Suit suit;
private final Rank rank;
public Card(Suit suit, Rank rank) {
this.suit = suit;
this.rank = rank;
}
public Suit getSuit() {
return suit;
}
public Rank getRank() {
return rank;
}
@Override
public String toString() {
return rank + " of " + suit;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Card card = (Card) o;
return suit == card.suit && rank == card.rank;
}
@Override
public int hashCode() {
return java.util.Objects.hash(suit, rank);
}
}
Suit
and Rank
makes your code more robust by preventing invalid card values and improving readability compared to using raw strings or integers.Building and Shuffling the Deck
Once we have our Card
class, we can create a Deck
class. A deck will typically hold a collection of Card
objects. The standard 52-card deck consists of one card for each combination of Suit
and Rank
. Java's Collections.shuffle()
method provides an efficient and well-tested way to randomize the order of cards in the deck.
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Deck {
private List<Card> cards;
public Deck() {
cards = new ArrayList<>();
for (Suit suit : Suit.values()) {
for (Rank rank : Rank.values()) {
cards.add(new Card(suit, rank));
}
}
}
public void shuffle() {
Collections.shuffle(cards);
}
public Card drawCard() {
if (cards.isEmpty()) {
System.out.println("Deck is empty. Cannot draw more cards.");
return null;
}
return cards.remove(0); // Remove and return the top card
}
public int cardsRemaining() {
return cards.size();
}
@Override
public String toString() {
return "Deck with " + cards.size() + " cards remaining.\n" + cards;
}
public static void main(String[] args) {
Deck deck = new Deck();
System.out.println("New Deck:\n" + deck);
deck.shuffle();
System.out.println("\nShuffled Deck (first 5 cards):\n" + deck.cards.subList(0, Math.min(5, deck.cards.size())));
System.out.println("\nDrawing cards:");
for (int i = 0; i < 5; i++) {
Card drawnCard = deck.drawCard();
if (drawnCard != null) {
System.out.println("Drew: " + drawnCard + ", Cards remaining: " + deck.cardsRemaining());
}
}
// Draw until empty to demonstrate handling
while (deck.cardsRemaining() > 0) {
deck.drawCard();
}
deck.drawCard(); // Attempt to draw from empty deck
}
}
flowchart TD A[Start] --> B{Create Deck}; B --> C[Initialize 52 Cards]; C --> D[Add Cards to List]; D --> E{Shuffle Deck?}; E -- Yes --> F[Call Collections.shuffle()]; E -- No --> G[Deck Ready]; F --> G; G --> H{Draw Card?}; H -- Yes --> I{Is Deck Empty?}; I -- No --> J[Remove First Card]; J --> K[Return Card]; I -- Yes --> L[Handle Empty Deck]; K --> H; L --> H; H -- No --> M[End];
Flowchart of Deck Initialization, Shuffling, and Drawing
Drawing Cards and Handling an Empty Deck
The drawCard()
method is crucial for interacting with the deck. It should return the 'top' card and remove it from the deck. It's also important to handle the scenario where the deck runs out of cards to prevent errors. Our implementation returns null
and prints a message when the deck is empty, allowing the caller to decide how to proceed (e.g., reshuffle a discard pile, end the game).
Collections.shuffle()
method uses a default random number generator. For more control or cryptographic security, you can provide your own Random
instance to Collections.shuffle(List<?> list, Random rnd)
.