Hi, I'm concentrating on getting my card and deck classes for a card game project working correctly. Both my card and deck classes are working technically correct but when I go though my nested for loop in my Deck class to create a deck of cards it ends up being in a reversed order than what we should have based on the project details. Any ideas how to easily switch the order that my for loops create a card deck so that it goes from the top down instead of bottom up?

Here are my card classes and output when I test in Deck class.

public class Card{

    public Rank rank;
    public Suit suit;
    //constructor for a single card: rank and suit
    Card( Rank rank, Suit suit){
        this.suit = suit;
        this.rank = rank;
    }
    public Rank getRank(){
        return rank;

    }

    public Suit getSuit(){
        return suit;
    }



    public String toString(){
        String temp = "";
        temp += rank.getName();
        temp += " of ";
        temp += suit.getName();
        return temp;

    }

    public static void main(String[] args){

        Card card1 = new Card(Rank.FOUR, Suit.CLUBS); 
        System.out.println(card1);
    }


}





import java.util.Arrays;

public class Deck
{
    private Card[] deck;
    static final int numberOfCards = 52;
    private static Rank[] rankValues = Rank.values();
    private static Suit[] suitValues = Suit.values();

    public Deck()
    {
        deck = new Card[52];
        int x = 0;
        for (int i = 0; i < suitValues.length; i++)
        {
            for (int j = 0; j < rankValues.length; j++)
            {
                deck[x] = new Card(rankValues[j], suitValues[i]);
                x++;
            }
        }

    }

    public void shuffle()
    {
        // Shuffles the deck.
        Card temp;
        int a;
        for (int x = 0; x < numberOfCards; x++)
        {
            a = (int)(Math.random() * numberOfCards);
            temp = deck[x];
            deck[x] = deck[a];
            deck[a] = temp;
        }
    }




    public String toString(){
        return Arrays.toString(deck);
    }
    public static void main(String[] args)
    {
        Deck deck1 = new Deck();
        System.out.println(Arrays.toString(rankValues));
        System.out.println(Arrays.toString(suitValues));
        System.out.println(deck1.toString());
        //deck1.shuffle();
        //System.out.println(deck1.toString());

    }

}

Everything is working technically correct except the order which the cards are created needs to be completely reversed. When I run the test main in my Deck class the output is
[ACE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, JACK, QUEEN, KING]
[CLUBS, DIAMONDS, HEARTS, SPADES]
[Ace of Clubs, Two of Clubs, Three of Clubs etc... Ace of Diamonds, Two of Diamonds, Three of Diamonds etc... Ace of Hearts, Two of Hearts, Three of Hearts etc... Ace of Spades, Two of Spades, Three of Spades etc...]

I need this output to begin with the King of Spades and end with the ace of Clubs in reversed order from what its currently printing out.

Dani AI

Generated

Short explanation: your nested loops walk Suit.values() then Rank.values() while advancing the deck index from the start. Because the enums themselves are declared ACE..KING and CLUBS..SPADES, the first cards you store are Ace of Clubs, Two of Clubs, etc. If you want King of Spades first you must change what you iterate or change which end of the array you fill.

As pointed out, the simplest fix is to fill the array from the end; confirmed that starting the index at the last slot and decrementing works and is perfectly fine if you want to keep the current loop structure.

Other clean options (no array-index juggling):

  • Iterate the enums in reverse (loop from length-1 down to 0) so insertion order is already the desired one.
  • Build the deck into a List and call Collections.reverse(list) after filling it. Example approach:
List<Card> list = new ArrayList<>();
for (Suit s : Suit.values()) {
  for (Rank r : Rank.values()) {
    list.add(new Card(r, s));
  }
}
Collections.reverse(list);

A couple of practical tips:

  • Decide and document which array end represents the “top” of the deck (index 0 or index length-1) and stick to that convention across deal/shuffle code.
  • For shuffling prefer a correct Fisher–Yates implementation or Collections.shuffle (the latter is simple and well-tested). Example Fisher–Yates for arrays:
Random rnd = new Random();
for (int i = deck.length - 1; i > 0; i--) {
  int j = rnd.nextInt(i + 1);
  Card tmp = deck[i]; deck[i] = deck[j]; deck[j] = tmp;
}

Also avoid hard-coded magic numbers (use a constant or deck.length) and use a seeded Random for repeatable unit tests.

Recommended Answers

All 2 Replies

Maybe put them into the array starting at the end and filling backwards? ie keep
deck[x] = new Card(rankValues[j], suitValues[i]);
but start x at 51 and decrement it in each pass of the inner loop instead of incrementing it.

ps When you have an answer to a problem please mark the thread "solved" for our knowledge base.
Thanks
J

I got it to work after playing around with it for a few minutes. Thank you for the tip. Here is the working code snippit

public Deck()
    {
        deck = new Card[52];
        int x = NUM_OF_CARDS - 1;
        for (int i = 0; i < suitValues.length; i++)
        {
            for (int j = 0; j < rankValues.length; j++)
            {
                deck[x] = new Card(rankValues[j], suitValues[i]);
                x--;
            }
        }
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.