Reputation: 25
I'm trying to finish this homework but it has been a little bit challenging so far, I'm quite new at java:
1). I have to create enums to replace the named constants for rank and suit in Card.java.
2).Make the changes necessary in Deck.java and DisplayDeck.java so they will work with the new Card.java.
This is my code so far for my three classes: Card.java, Deck.java and DisplayDeck.java
Original Card.java
public class Card {
private final int rank;
private final int suit;
// Kinds of suits
public final static int DIAMONDS = 1;
public final static int CLUBS = 2;
public final static int HEARTS = 3;
public final static int SPADES = 4;
// Kinds of ranks
public final static int ACE = 1;
public final static int DEUCE = 2;
public final static int THREE = 3;
public final static int FOUR = 4;
public final static int FIVE = 5;
public final static int SIX = 6;
public final static int SEVEN = 7;
public final static int EIGHT = 8;
public final static int NINE = 9;
public final static int TEN = 10;
public final static int JACK = 11;
public final static int QUEEN = 12;
public final static int KING = 13;
public Card(int rank, int suit) {
assert isValidRank(rank);
assert isValidSuit(suit);
this.rank = rank;
this.suit = suit;
}
public int getSuit() {
return suit;
}
public int getRank() {
return rank;
}
public static boolean isValidRank(int rank) {
return ACE <= rank && rank <= KING;
}
public static boolean isValidSuit(int suit) {
return DIAMONDS <= suit && suit <= SPADES;
}
public static String rankToString(int rank) {
switch (rank) {
case ACE:
return "Ace";
case DEUCE:
return "Deuce";
case THREE:
return "Three";
case FOUR:
return "Four";
case FIVE:
return "Five";
case SIX:
return "Six";
case SEVEN:
return "Seven";
case EIGHT:
return "Eight";
case NINE:
return "Nine";
case TEN:
return "Ten";
case JACK:
return "Jack";
case QUEEN:
return "Queen";
case KING:
return "King";
default:
//Handle an illegal argument. There are generally two
//ways to handle invalid arguments, throwing an exception
//(see the section on Handling Exceptions) or return null
return null;
}
}
public static String suitToString(int suit) {
switch (suit) {
case DIAMONDS:
return "Diamonds";
case CLUBS:
return "Clubs";
case HEARTS:
return "Hearts";
case SPADES:
return "Spades";
default:
return null;
}
}
public static void main(String[] args) {
// must run program with -ea flag (java -ea ..) to
// use assert statements
assert rankToString(ACE) == "Ace";
assert rankToString(DEUCE) == "Deuce";
assert rankToString(THREE) == "Three";
assert rankToString(FOUR) == "Four";
assert rankToString(FIVE) == "Five";
assert rankToString(SIX) == "Six";
assert rankToString(SEVEN) == "Seven";
assert rankToString(EIGHT) == "Eight";
assert rankToString(NINE) == "Nine";
assert rankToString(TEN) == "Ten";
assert rankToString(JACK) == "Jack";
assert rankToString(QUEEN) == "Queen";
assert rankToString(KING) == "King";
assert suitToString(DIAMONDS) == "Diamonds";
assert suitToString(CLUBS) == "Clubs";
assert suitToString(HEARTS) == "Hearts";
assert suitToString(SPADES) == "Spades";
}
}
My modified Card.java so far:
public class Card {
public enum Suit
{
DIAMONDS(1),
CLUBS(2),
HEARTS(3),
SPADES(4);
private final int suit;
private Suit(int suit)
{
this.suit = suit;
}
public int getSuit()
{
return suit;
}
} //end enum suit
public enum Rank
{
ACE(1),
DEUCE(2),
THREE(3),
FOUR(4),
FIVE(5),
SIX(6),
SEVEN(7),
EIGHT(8),
NINE(9),
TEN(10),
JACK(11),
QUEEN(12),
KING(13);
private final int rank;
private Rank(int rank)
{
this.rank = rank;
}
public int getRank()
{
return rank;
}
}//end enum rank
public static String rankToString(Rank rank) {
switch (rank) {
case ACE:
return "Ace";
case DEUCE:
return "Deuce";
case THREE:
return "Three";
case FOUR:
return "Four";
case FIVE:
return "Five";
case SIX:
return "Six";
case SEVEN:
return "Seven";
case EIGHT:
return "Eight";
case NINE:
return "Nine";
case TEN:
return "Ten";
case JACK:
return "Jack";
case QUEEN:
return "Queen";
case KING:
return "King";
default:
//Handle an illegal argument. There are generally two
//ways to handle invalid arguments, throwing an exception
//(see the section on Handling Exceptions) or return null
return null;
}
}
public static String suitToString(Suit suit) {
switch (suit) {
case DIAMONDS:
return "Diamonds";
case CLUBS:
return "Clubs";
case HEARTS:
return "Hearts";
case SPADES:
return "Spades";
default:
return null;
}
}
}//end class
And this are the original Deck.java and DisplayDeck.java:
Original Deck.java
import java.util.*;
public class Deck {
public static int numSuits = 4;
public static int numRanks = 13;
public static int numCards = numSuits * numRanks;
private Card[][] cards;
public Deck() {
cards = new Card[numSuits][numRanks];
for (int suit = Card.DIAMONDS; suit <= Card.SPADES; suit++) {
for (int rank = Card.ACE; rank <= Card.KING; rank++) {
cards[suit-1][rank-1] = new Card(rank, suit);
}
}
}
public Card getCard(int suit, int rank) {
return cards[suit-1][rank-1];
}
}
Modified Deck.java:
import java.util.*;
public class Deck {
public static int numSuits = 4;
public static int numRanks = 13;
public static int numCards = numSuits * numRanks;
private Card[][] cards;
public Deck() {
cards = new Card[numSuits][numRanks];
for (Card.Suit suit : Card.Suit.values()) {
for (Card.Rank rank : Card.Rank.values()) {
// I dont know how to change this to work with Card.java
cards[suit-1][rank-1] = new Card(rank, suit);
}
}
}
public Card getCard(int suit, int rank) {
return cards[suit-1][rank-1];
}
}
and DisplayDeck.java
import java.util.*;
public class DisplayDeck {
public static void main(String[] args) {
Deck deck = new Deck();
/// how can i modify this code to work with both Card.java and Deck.java?
for (int suit = Card.DIAMONDS; suit <= Card.SPADES; suit++) {
for (int rank = Card.ACE; rank <= Card.KING; rank++) {
Card card = deck.getCard(suit, rank);
System.out.format("%s of %s%n",
card.rankToString(card.getRank()),
card.suitToString(card.getSuit()));
}
}
}
}
I update my code on what I got so far.
Upvotes: 0
Views: 444
Reputation: 234807
Get rid of all your int
representations for rank and suit. You can replace loops like this:
for (int suit = Card.DIAMONDS; suit <= Card.SPADES; suit++) { ...
with an enhanced for
loop:
for (Suit suit : Card.Suit.values()) { ...
Replace mappings from int
to String
with EnumMap<Suit,String>
or EnumMap<Rank,String>
as appropriate. Methods for checking whether an int
value is valid can be disposed of, as a non-null enum
is guaranteed to be a legal value.
EDIT (in response to comment): You can define your deck as simply an array of Card
objects:
public class Deck {
private List<Card> cards;
public Deck() {
cards = new ArrayList<>();
for (Card.Suit suit : Card.Suit.values()) {
for (Card.Rank rank : Card.Rank.values()) {
cards.add(new Card(suit, rank));
}
}
}
}
With this, you can use the Collections
utility class to trivially implement shuffling:
public class Deck {
. . . // as above
public void shuffle() {
Collections.shuffle(cards);
}
}
Since every enum
type comes with a built-in compareTo()
method that tells you the relative order of two enum
values (of the same type). You can build on this to make the Card
class implement Comparable<Card>
. (This is left as an exercise for the reader :-)). Then you can trivially sort the deck back into its "brand new" order or even sort hands drawn randomly from the deck.
I see that you are currently retrieving a card by suit and rank. That's a weird way to access cards in a deck, especially since you just turn around and use the Card
object to retrieve its suit and rank. But if you really need that kind of retrieval, you can expand the Deck
definition to include internally an EnumMap<Suit, EnumMap<Rank, Card>>
to allow you to quickly retrieve a card that way. (Yes, each card would then be stored in two distinct data structures inside the Deck
object.) A better approach, in my view, is to add a method to retrieve a card by offset into the deck (and another method to tell you the deck size):
public class Deck {
. . .
public Card getCard(int index) {
return cards.get(index);
}
public int cardCount() {
return cards.size();
}
}
To be fancier, you can define a method that returns an iterator over all the cards:
public class Deck {
. . .
public Iterator<Card> iterator() {
return cards.iterator();
}
}
Even fancier yet, you could declare Deck
to implement Iterable<Card>
. Then you can print the deck contents very simply:
Deck deck = new Deck();
for (Card card : deck) {
// print the card
}
Upvotes: 1