package cse1030; import java.util.Arrays; import java.util.HashMap; import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; /** * An immutable class representing a playing card from a standard 52 card deck. * A playing card is identified by its suit (clubs, diamond, heart, spade) and * its rank (two through ten, jack, queen, king, and ace). Both the suit and * rank are represented with strings. * * The class is implemented as a multiton; there is only one * PlayingCardM object for each unique combination of rank and * suit. * * * @author CSE1030 * */ public final class PlayingCardM implements Comparable { private static final String[] RANKS = { "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A" }; private static final String[] SUITS = { "S", "C", "D", "H" }; private static final Map instances = new HashMap(); private final String rank; private final String suit; /** * Create a playing card with a given rank and suit. * *

* Valid ranks are "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", * "K", "A" (the number cards 2 through 10, and the face cards jack, queen, * king, and ace). * *

* Valid suits are "H", "D", "C", "S" (the suits hearts, diamonds, clubs, and * spades). * * @param rank * The rank of the card. * @param suit * The suit of the card. * @throws IllegalArgumentException if the rank or the suit is * not valid. */ private PlayingCardM(String rank, String suit) { boolean valueOk = Arrays.asList(RANKS).contains(rank); boolean suitOk = Arrays.asList(SUITS).contains(suit); if (!valueOk) { throw new IllegalArgumentException("Bad rank : " + rank); } if (!suitOk) { throw new IllegalArgumentException("Bad suit : " + suit); } this.rank = rank; this.suit = suit; } /** * Get a playing card with a given rank and suit. Only one * PlayingCardM object will ever be created for each unique * combination of rank and state. * *

* Valid ranks are "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", * "K", "A" (the number cards 2 through 10, and the face cards jack, queen, * king, and ace). * *

* Valid suits are "H", "D", "C", "S" (the suits hearts, diamonds, clubs, and * spades). * * @param rank * The rank of the card. * @param suit * The suit of the card. * @return A card with the given rank and suit. * @throws IllegalArgumentException if the rank or the suit is * not valid. */ public static PlayingCardM getCard(String rank, String suit) { String key = rank + suit; PlayingCardM card = PlayingCardM.instances.get(key); if (card == null) { card = new PlayingCardM(rank, suit); PlayingCardM.instances.put(key, card); } return card; } /** * Gets the rank of the card. The rank is guaranteed to be one of the rank * strings described in {@link PlayingCardM#getCard(String, String)}. * * @return the rank * @see PlayingCardM#getCard(String, String) */ public String getRank() { return rank; } /** * Gets the suit of the card. The suit is guaranteed to be one of the suit * strings described in {@link PlayingCardM#getCard(String, String)}. * * @return the suit * @see PlayingCardM#getCard(String, String) */ public String getSuit() { return suit; } /** * Return a hash code for this playing card. * * @return A hash code value for this playing card. */ @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((suit == null) ? 0 : suit.hashCode()); result = prime * result + ((rank == null) ? 0 : rank.hashCode()); return result; } /** * Compares this playing card to the specified object. The result is * true if and only if the argument is a * PlayingCardM with the same rank and suit as this card. * * @param obj * The object to compare this PlayingCardM against. * @return true if the given object is a * PlayingCardM equal to this playing card, * false otherwise. */ @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } PlayingCardM other = (PlayingCardM) obj; if (suit == null) { if (other.suit != null) { return false; } } else if (!suit.equals(other.suit)) { return false; } if (rank == null) { if (other.rank != null) { return false; } } else if (!rank.equals(other.rank)) { return false; } return true; } /** * Compares two playing cards by their ranks and suits. The result is * guaranteed to be consistent with equals. * *

* The cards are first compared by their ranks. If their ranks are equal then * the cards are compared by their suits. * *

* The ordering of ranks from smallest to largest is 2, 3, 4, 5, 6, 7, 8, 9, * 10, J, Q, K, A (i.e., 2 is considered the smallest rank and A (ace) is * considered the largest rank). * *

* The order of suits from smallest to largest is S, C, D, H (i.e., spades < * clubs < diamonds < hearts). * * @param other * The PlayingCardM/code> to be compared against. * @return the value 0 if argument card is equal to this card; a * value less than zero if this card is smaller than the other card; a * value greater than zero if this card is greater than the other * card. */ @Override public int compareTo(PlayingCardM other) { // compare ranks int thisRank = Arrays.asList(RANKS).indexOf(this.getRank()); int otherRank = Arrays.asList(RANKS).indexOf(other.getRank()); int result = thisRank - otherRank; if (result == 0) { // compare suits int thisSuit = Arrays.asList(SUITS).indexOf(this.getSuit()); int otherSuit = Arrays.asList(SUITS).indexOf(other.getSuit()); result = thisSuit - otherSuit; } return result; } /** * Returns a string representation of this playing card. * *

* The returned string is the rank of the card followed by " of " * followed by the suit of the card. For example, the card representing the * ace of hearts has the string representation "A of H". * * @return A string representation of this playing card. */ @Override public String toString() { return this.getRank() + " of " + this.getSuit(); } /** * Returns a set of the strings that can be used to specify the rank of a * playing card. The set is guaranteed to contain all of the rank strings * described in {@link PlayingCardM#getCard(String, String)}. * * @return a set of the valid ranks as strings */ public static Set getAllRanks() { return new LinkedHashSet(Arrays.asList(RANKS)); } /** * Returns a set of the strings that can be used to specify the suit of a * playing card. The set is guaranteed to contain all of the suit strings * described in {@link PlayingCardM#getCard(String, String)}. * * @return a set of the valid suits as strings */ public static Set getAllSuits() { return new LinkedHashSet(Arrays.asList(SUITS)); } public static void main(String[] args) { // generate a standard 52 card deck Set ranks = PlayingCardM.getAllRanks(); Set suits = PlayingCardM.getAllSuits(); for (String r : ranks) { for (String s : suits) { PlayingCardM card = PlayingCardM.getCard(r, s); System.out.println(card); } } } }