0

I have an assignment to create a deck of cards and deal five random cards. I finally got it "working" but I need help with a couple things. One I just read that java now has a shuffle method to shuffle a list. We're on arrays right now so I think arrays were wanted is there a way to use the shuffle method with an array? If not can someone guide me in switching to a list? I think it will help with answer my next question. The only thing left for me to do is somehow state how many cards are left in the deck after the 5 random cards are dealt. However, seeing as how I'm using an array and you cannot remove items from an array because it's fixed (right?) I wanted to see if there was a way to simulate removing the cards from the array so that they aren't dealt again? Or would it just be easier to turn the arrays into a list/collection?

Here is my code. Any help is greatly appreciated. Also, I'll take any suggestions on cleaning the code up too...

public class CardGame {
    public static void main (String [] args) { 

    DeckOfCards deck = new DeckOfCards();
    //call shuffle
    deck.shuffle(1000);

   Card b;
   for (int i = 0; i < 5; i++) {
       b = deck.deal();
       System.out.println("Deal a card: " + b);  
    }
  }  
}


class Card {

   public static final int SPADE   = 4;
   public static final int HEART   = 3;
   public static final int CLUB    = 2;
   public static final int DIAMOND = 1;

   private static final String[] Suit = {"*", "Hearts", "Clubs", "Spades", "Diamonds"};
   private static final String[] Rank = {"*", "*", "Ace", "2", "3", "4", "5", "6", "7", "8", "9", "10", "Jack", "Queen", "King"};    

   private int cardSuit;
   private int cardRank;

   public Card( int suit, int rank ) {
      if ( rank == 1 )
         cardRank = 14;     // Give Ace the rank 14
      else
         cardRank = (int) rank;

      cardSuit = (int) suit;
   }

   public int suit() {
      return ( this.cardSuit );     
   }

   public String suitStr() {
      return( this.Suit[ this.cardSuit ] );  
   }

   public int rank() {
      return ( this.cardRank );
   }

   public String rankStr() {
      return ( Rank[ this.cardRank ] );
   }

   public String toString() {
      return ( Rank[ this.cardRank ] + " of "+ Suit[ this.cardSuit ] );
   }
}

class DeckOfCards {
   public static final int NEWCARDS = 52;
   private Card[] deckOfCards;         // Contains all 52 cards
   private int currentCard;            // deal THIS card in deck

   public DeckOfCards( ) {
      deckOfCards = new Card[ NEWCARDS ];
      int i = 0;

      for (int suit = Card.DIAMOND; suit <= Card.SPADE; suit++)
         for ( int rank = 1; rank <= 13; rank++ )
             deckOfCards[i++] = new Card(suit, rank);
             currentCard = 0;
   }
  //shuffle(n): shuffle the deck
   public void shuffle(int n) {
      int i, j, k;

      for ( k = 0; k < n; k++ ){ 
      i = (int) ( NEWCARDS * Math.random() );  // Pick 2 random cards
      j = (int) ( NEWCARDS * Math.random() );  // in the deck

      //swap these randomly picked cards
      Card temp = deckOfCards[i];
      deckOfCards[i] = deckOfCards[j];
      deckOfCards[j] = temp;
      }
      currentCard = 0;   // Reset current card to deal
   }

   //deal(): deal deckOfCards[currentCard] out
   public Card deal() {

      if (currentCard < NEWCARDS) {
         return ( deckOfCards[currentCard++] );
      }
      else{
         System.out.println("Out of cards error");
         return ( null );  // Error;
      }
   }

   public String toString() {
      String s = "";
      int k;
      k = 0;

      for ( int i = 0; i < 4; i++ ) {        
          for ( int j = 1; j <= 13; j++ )
             s += (deckOfCards[k++] + " ");
             s += "\n";
     }
      return (s);
   }
}

After all the help I decided to rewrite my code and here is what I got but I'm having a little trouble bringing it all together and making it work!

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;   

public class CardGame {
    public static void main (String [] args) { 

    DeckOfCards deck = new DeckOfCards();
    //call shuffle
    deck.shuffle();

   Card b;
   for (int i = 0; i < 5; i++) {
       b = deck.deal();
       System.out.println("Deal a card: " + b);  
   }
 }  
}



class Card {

enum Suit {
   HEARTS(1), 
   CLUBS(2), 
   DIAMONDS(3), 
   SPADES(4);

  private int suitValue;

  private Suit (int suitValue)
  {
    this.suitValue = suitValue;
  }

  public int getSuitValue()
  {
    return suitValue;
  }  
}

private Suit suit;
private Value value;

 public Card (Suit suit, Value value)
{
this.suit = suit;
this.value = value;
}

public Suit getSuit() {
    return suit;
}
public Value getValue() {
    return value;
}

/*
public int compareTo(Card o) {

  return 0;
  }
 } */

class DeckOfCards 
{
 private List<Card> cards = new ArrayList<Card>();

 public DeckOfCards () {

 for (Suit suit : Suit.values()) {
     for (Value value : Value.values()) {
        Card card = new Card(suit, value);
        cards.add(card);
  }
 }
}

  public List<Card> getCards() {
      return cards;
  }

  public void shuffleDeckOfCards() {
       Collections.shuffle(cards);
  }


 public String toString() {
     return this.Value + " of "+ this.Suit;
  }
 }
NoobCoderChick
  • 617
  • 3
  • 21
  • 40
  • Removing cards from array - set references = null. Convert array to list, shuffle and then reconvert to array. – Erran Morad Aug 03 '14 at 01:07
  • I actually just heard back from my professor and he wants us to only use arrays. "For the assignment, I want you to use arrays, as we haven't covered Lists yet. As cards are dealt from the deck in an order, you can keep a count of how many cards have been dealt from the array and then use this count to retrieve the next card from the array." – NoobCoderChick Aug 03 '14 at 07:00

2 Answers2

1

Here is a fully working sample program which demonstrates all the things you need - Shuffling and removing cards from an array.

Sample Card class:

public class Card {
    private String value = "";

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }

    public Card(String value) {
        super();
        this.value = value;
    }

}

Sample program:

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;

public class CardGame {

    public static void main(String[] args) {

        List<Card> pack = new ArrayList<Card>();
        Card c1 = new Card("c1");
        Card c2 = new Card("c2");
        Card c3 = new Card("c3");
        pack.add(c1);
        pack.add(c2);
        pack.add(c3);

        System.out.print("List : ");
        CardGame.displayCardList(pack);

        Card[] packArr = cardListToArray(pack);

        System.out.print("Array : ");
        CardGame.displayCardArray(packArr);

        // http://stackoverflow.com/questions/4228975/how-to-randomize-arraylist
        long seed = System.nanoTime();
        Collections.shuffle(pack, new Random(seed));

        System.out.print("Shuffle List : ");
        CardGame.displayCardList(pack);

        packArr = cardListToArray(pack);

        System.out.print("Shuffle Array : ");
        CardGame.displayCardArray(packArr);

        System.out.print("Remove Card from Array : ");
        CardGame.removeCardFromArray(packArr, new Card("c1"));
        CardGame.displayCardArray(packArr);

    }

    public static boolean removeCardFromArray(Card[] packArr, Card card) {

        boolean cardFound = false;

        for (int i = 0; i < packArr.length; i++) {

            if (packArr[i].getValue().equalsIgnoreCase(card.getValue())) {
                packArr[i] = null;
                cardFound = true;
                break;
            }

        }

        return cardFound;

    }

    public static Card[] cardListToArray(List<Card> pack) {

        Card[] packArr = new Card[pack.size()];

        for (int i = 0; i < pack.size(); i++) {
            packArr[i] = pack.get(i);
        }

        return packArr;

    }

    public static void displayCardList(List<Card> pack) {

        for (Card c : pack) {
            System.out.print(c.getValue() + ", ");
        }
        System.out.println();
    }

    public static void displayCardArray(Card[] packArr) {

        for (Card c : packArr) {

            if (c == null) {
                System.out.print("REMOVED, ");
            } else {
                System.out.print(c.getValue() + ", ");

            }

        }
        System.out.println();
    }

}
Erran Morad
  • 4,563
  • 10
  • 43
  • 72
  • Thanks Borat! I'm trying to rewrite my code so this will definitely help! How would you deal the five random cards from your sample here and show how many cards are left in the deck? – NoobCoderChick Aug 03 '14 at 05:29
1

Card

In the Card class the suits should be an enum. You can create the enum like this.

enum Suit {

    SPADE,
    HEART,
    CLUB,
    DIAMOND
};

Then the class should hold a variable of it's current suit like

Suit suit;

You can change the value of it very easily.

suit = Suit.HEART;

If you must use an index to access a suit you could use

suit = Suit.values()[index];

When getting the rank of the card you could use

return Rank[suit.ordinal()];

The name of the functions in the Card class are not the typical names you should use. Some of these should be getters. I would recommend names like getSuit() and getSuitName(), you want names that just by reading them you can understand what they do. Names like suit() are a little confusing, they don't tell you what they are doing with suit.

DeckOfCards

In the DeckOfCards class, when initializing the deck use a for each loop for the suits.

for (Suit suit : Suits.values()) {

    ...
}

This will loop over every suit.

If you wanted to switch over to a List you should declare your private variable deckOfCards to be an ArrayList.

private List<Card> deckOfCards = new ArrayList<>();

If you haven't worked with lists before, this is creating a list of Card objects. The diamond operator (<>) assumes the object type from the type you specified before (Card) This is a java 7 feature, if you are working with older version you would use

new ArrayList<Card>();

Instead of tracking your position in the deck, you add a card with the add() function

deckOfCards.add(card);

This would allow you to use Collections.shuffle(deckOfCards) to shuffle the cards around randomly.

To access a card, you use the get(int i) function

deckOfCards.get(index);

If you are still using arrays, when you are shuffling use a Random object. Throw a

Random random = new Random();

in the begging of your class. The inside of the for loop could look like this

int i = random.nextInt(NEWCARDS);
int j = random.nextInt(NEWCARDS);

Card temp = deckOfCards[i];
deckOfCards[i] = deckOfCards[j];
deckOfCards[j] = temp;

In the shuffle function I would change the names of i, j, and k. Variable K should be called i because it is the iterator. Variable j and k should be renamed to more meaningful names.

If you want to convert Arrays to lists you can use

Arrays.asList(new ArrayList<Card>());

And the opposite of that, to convert back to an array.

list.toArray();//This will return an array of Objects[]

Card[] cards = new Card[NEWCARDS];

list.toArray(cards)//This will store the list into the array cards.
//Note if the lists is bigger than the array it is storing it in, the function will return a new array that can hold all of the elemnents in the list.

Note: In these example I have been using ArrayList, there are other implementations of the List class which you may want to research.

Personal Preference

I would remove the parenthesis off of the return statements except on your toString() for the Card class.

You have some extra spaces when using parenthesis in your code such as your DeckOfCards constructor. I would make it like so

public DeckOfCards() {

There also shouldn't be spaces surrounding the stuff inside parenthesis such as

i = (int) ( NEWCARDS * Math.random() );

//should be

i = (int) (NEWCARDS * Math.random());
gyroninja
  • 111
  • 1
  • 1
  • 5
  • Awesome thank you gyroninja! I'm trying to rewrite the entire thing and it is proving to be difficult! I'm getting there slowly though, thanks for the help! – NoobCoderChick Aug 03 '14 at 05:27