chloe
chloe

Reputation: 33

Shuffling Deck of Cards Using Card object

Have been attempting to create a class called CardDeck to shuffle card objects created in a different class (called DeckOfCard, sorry for the confusion, not well named) but have run out of ideas of how to accomplish this.

here is what I have come up with, I've included the original class DeckOfCards as well, any help/ advice is welcomed and appreciated!

//CODE FOR CARD OBJECT//
   public final static int ace = 1, two= 2,three=3, four=4, five=5, six=6, seven =7, eight=8, nine=9, ten=10, jack= 11, queen=12, king=13; 

   public final static int diamonds= 1, clubs= 2, spades= 3, hearts=4; 

   private final static int numberOfFaces = 13;
   private final static int numberOfSuits = 4;

   private int face, suit;
   private String faceValue, suitName;

   //create a random card 
   public DeckOfCards()
   {
       face= (int)(Math.random() * numberOfFaces);
       setFaceValue();

       suit= (int) (Math.random() * numberOfSuits);
       setSuitName();
    }

   //sets the string representation of each face value to its coorspdoing numeric value
    private void setFaceValue()
   {
       switch(face)
       {
           case ace:
            faceValue= "Ace";
            break;
           case two:
            faceValue= "Two";
            break;
           case three:
            faceValue= "Three";
            break;
           case four:
            faceValue= "Four";
            break;
           case five:
            faceValue = "Five";
            break;
           case six:
            faceValue = "Six";
            break;
           case seven:
            faceValue= "Seven";
            break;
           case eight:
            faceValue= "Eight";
            break;
           case nine:
            faceValue= "Nine";
            break;
           case ten:
            faceValue= "Ten";
            break;
           case jack:
            faceValue= "Jack";
            break;
           case queen:
            faceValue= "Queen";
            break;
           case king:
            faceValue= "King";
            break;
       }
   }

      //set the string representation of each suit 
private void setSuitName()
{
    switch(suit)
    {
        case diamonds:
            suitName = "Diamonds";
            break;
        case clubs:
            suitName= "Clubs";
            break;
        case spades:
            suitName = "Spades";
            break;
        case hearts:
            suitName = "Hearts";
            break;
        }
    }

public String getFaceValue()
{
    return faceValue;
}

public String getSuitName()
{
    return suitName;
}

public String toString()
{
    return faceValue+ " of " +suitName;
}
}

And Here is my current code... It's not much but this is as close as I have been able to get thus far:

import java.util.Random;
public class CardDeck
{
   private DeckOfCards[] cards;

   //create new deck of cards
   public CardDeck()
   {
       cards = new DeckOfCards[52];
       int index= 0;


       int[] cardTypes = {DeckOfCards.ace, DeckOfCards.diamonds, DeckOfCards.spades,      DeckOfCards.hearts};

       for(int cardType : cardTypes)
       {
           for(int i = 1; i<=13; i++)
           {
               DeckOfCards card = new DeckOfCards();
               cards[index++]= card;
            }
        }
  }

  //create shuffle method, use loop to generate random suit and random faceValue
    public void shuffle()
    {


        System.out.println("Suffuling cards");

            int loopCount = 53;

            while (loopCount > 0) {

            double index1 = Math.random();

            double index2 = Math.random();

            DeckOfCards temp = cards[index1];

            cards[index1] = cards[index2];

            cards[index2] = temp;

            loopCount--;

}

}

}

Upvotes: 0

Views: 696

Answers (4)

erickson
erickson

Reputation: 269897

Define a enum types for the rank and the suit. This provides type safety so that you don't accidentally pass a rank for a suit parameter or vice versa. The enumerated values also make good keys to use in maps to define scoring systems for different games and so on. Note also that enums can have properties and methods, so you can add user friendly names for values that way.

Then create a Card type that has a rank and a suit.

Iterate over the ranks, and for each rank, iterate over the suits. Create a new Card for each combination of rank and suit, and add it to a List; this is your deck. When your deck is built, you can shuffle it with a convenience method in Collections.

public final class Card {

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

    public enum Suit {
        SPADES, HEARTS, DIAMOND, CLUBS
    }

    private final Rank rank;

    private final Suit suit;

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

    public Rank getRank() {
        return rank;
    }

    public Suit getSuit() {
        return suit;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == this) return true;
        if (!(obj instanceof Card)) return false;
        Card that = (Card) obj;
        return (getRank() == that.getRank()) && (getSuit() == that.getSuit());
    }

    @Override
    public int hashCode() {
        return getRank().hashCode() * 31 + getSuit().hashCode();
    }

    @Override
    public String toString() {
        return getRank() + " of " + getSuit();
    }

}

public class Deck {

    private final List<? extends Card> cards;

    public Deck(Collection<? extends Card> cards) {
        this.cards = new ArrayList<>(cards);
    }

    public void shuffle(Random random) {
        if (random == null) random = ThreadLocalRandom.current();
        Collections.shuffle(cards, random);
    }

    public static Deck newStandardDeck() {
        List<Card> cards = new ArrayList<>();
        for (Card.Rank rank : Card.Rank.values()) {
            for (Card.Suit suit : Card.Suit.values()) {
                cards.add(new Card(rank, suit));
            }
        }
        return new Deck(cards);
    }

}

Upvotes: 1

btrballin
btrballin

Reputation: 1464

Please change the name to Card instead of DeckOfCards. A list of Card objects becomes a deck of cards, so you don't want to call the object itself the deck.

The random function should follow a similar approach as the constructor of DeckOfCards in which your multiplier should be applied on top of the random number and be casted into an int. After that, your code should work fine. Card size 52 should be stored as a global private variable. Never use "magic numbers" without storing them in a variable and calling that variable. Both index1 and index2 should be the following:

double index1 = Math.random()*NUM_CARDS

Below your private array have the following variable: private final int NUM_CARDS = 52

Otherwise you are on the right track and the shuffling mechanism is good. It's just the random index generation gets a decimal number between 0 to 1.

When you have to debug, use the printing your variables technique. In this case, print out every value of index1 and index2 and check whether those values are being generated as intended. You can also try a less beginner friendly method called debug mode (cockroach icon) and double click on a line number to set a breakpoint at which you want the execution to pause and you can view all the variables stored in memory at that point of your code.

Upvotes: 0

Cole L
Cole L

Reputation: 1

So there's some big issues with your code structure but i salvaged this. The easiest solution is to create a sorted list of cards, one for each suite and value and then set each card to a random index. This will perform that on a field 'cards'

// create shuffle method, use loop to generate random suit and random faceValue
    public void shuffle() {

        System.out.println("Suffuling cards");

        int loopCount = 0;

        ArrayList<DeckOfCards> inOrder = new ArrayList<DeckOfCards>();
        for(int i = 0; i < 54; i++)
        {
            inOrder.add(cards[i]);
        }

        DeckOfCards[] shuffled = new DeckOfCards[54];

        for(int i = 0; i < 54; i++)
        {
            //Math.random()*size of inOrder will give you a double between 0 and size of in order. 
            //Round this down and convert to an int and you have a random index!
            int randCardIndex = (int) (Math.floor(Math.random()*inOrder.size()));

            //Grab the card and add it to the shuffled deck in the current position
            shuffled[i] = inOrder.get(randCardIndex);

            //Remove this card so it can no longer be grabbed
            inOrder.remove(randCardIndex);
        }

        cards = shuffled;

    }

Upvotes: 0

Jamie
Jamie

Reputation: 1937

Your issue lies here:

double index1 = Math.random();
double index2 = Math.random();

Math.random() returns a double float between 0 and 1. Try this instead:

 Random r = new Random();

 while(loopCount > 0) {
     int index1 = r.nextInt(cards.length);
     int index2 = r.nextInt(cards.length);

Upvotes: 0

Related Questions