Reputation: 33
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
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
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
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
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