001    package ps0.optional;
002    
003    /**
004     * Card is a class representing single playing card consisting of a value and a
005     * suit (e.g. [Ace,Spades],[10,Clubs]). Cards are immutable; once a Card has
006     * been created with a given value and suit, that value and suit cannot be
007     * changed.
008     */
009    public class Card implements Comparable<Card> {
010    
011        // AF(c) = c represents a playing card with value of c.value and a
012        // suit of c.suit (e.g. Ace of Spades, 10 of Clubs)
013    
014        // RI(c) = c.value != null && c.suit != null
015    
016        //
017        // MEMBER VARIABLES
018        //
019    
020        // the member variables are declared to be final because this class
021        // is immutable.
022    
023        /**
024         * The value of this card.
025         */
026        private final CardValue value;
027    
028        /**
029         * The suit of this card.
030         */
031        private final CardSuit suit;
032    
033        //
034        // METHODS
035        //
036    
037        // -------------------------------------------
038        /**
039         * Creates a new playing card.
040         *
041         * @param aValue
042         *            the value of this card
043         * @param aSuit
044         *            the suit of this card
045         *
046         * @modifies this
047         * @effects creates a new <code>Card</code> object
048         */
049        public Card(CardValue aValue, CardSuit aSuit) {
050            this.value = aValue;
051            this.suit = aSuit;
052        }
053    
054        // -------------------------------------------
055        /**
056         * @effects returns the <code>CardSuit</code> associated with this card
057         */
058        public CardSuit getSuit() {
059            return this.suit;
060        }
061    
062        // -------------------------------------------
063        /**
064         * @effects returns the <code>CardValue</code> associated with this card
065         */
066        public CardValue getValue() {
067            return this.value;
068        }
069    
070        // -------------------------------------------
071        /**
072         * Compares this card with the specified card for order. The purpose of
073         * being able to compare cards is to be able to sort a hand of cards.
074         * <p>
075         * Cards are ranked primarily by number, secondarily by suit. That means
076         * that this card is ranked lower than another card if one of these
077         * conditions is met:
078         * <ul>
079         * <li>This card's face value is less than the other card's face value; or
080         * <li>Both cards' face values are equal, but this card's suit is ranked
081         * lower than the other card's suit.
082         * </ul>
083         *
084         * EXAMPLE: [Ace,Clubs] is ranked higher than [10,Spades] because face value
085         * is higher, but is ranked lower than [Ace,Spades] because its suit is
086         * ranked lower.
087         *
088         * @param c
089         *            the Card to be compared
090         * @exception ClassCastException
091         *                if the specified object's type is not Card
092         * @exception NullPointerException
093         *                if the specified object is null
094         *
095         * @effects
096         * <ul>
097         * <li>If <code>o</code> is not an instance of Card, throws a
098         * <code>ClassCastException</code></li>
099         * <li>If <code>o</code> is null, throws a
100         * <code>NullPointerException</code></li>
101         * <li>Returns a negative integer, zero, or a positive integer if this
102         * <code>Card</code> is less than, equal to, or greater than the specified
103         * <code>Card</code>, respectively</li>
104         * </ul>
105         */
106        public int compareTo(Card c) {
107            if (c == null) {
108                throw new NullPointerException();
109            }
110            // cast the Object o to a Card now that we've check to make sure it
111            // is one!
112    
113            if (this.value.equals(c.value)) {
114                return this.suit.compareTo(c.suit);
115            } else {
116                return this.value.compareTo(c.value);
117            }
118        }
119    
120        // -------------------------------------------
121        /**
122         * Returns true if this card is equal to the other card. Two cards are equal
123         * if both their values and suits are identical.
124         *
125         * @param otherCardObject
126         *            the other card
127         *
128         * @effects returns true if both cards are equal; in all other cases,
129         *          returns false
130         */
131        public boolean equals(Object otherCardObject) {
132            if (!(otherCardObject instanceof Card)) {
133                return false;
134            }
135            return hashCode() == ((Card) otherCardObject).hashCode();
136        }
137    
138        // -------------------------------------------
139        /**
140         * Returns a hashcode for this object. This hashcode is the same for all
141         * Cards equal to this one (as indicated by the equals method). Note that it
142         * is good practice to override the hashCode method when redefining the
143         * equals method.
144         *
145         * @effects returns a hashcode for this object; invoking this methods on two
146         *          equal Cards results in the same hashcode
147         */
148        public int hashCode() {
149            int suitMultiplier = suit.ordinal();
150            int valueInt = value.ordinal() + 1;
151            return ((suitMultiplier * 13) + valueInt);
152        }
153    
154        // -------------------------------------------
155        /**
156         * @effects returns a description of this card
157         */
158        public String toString() {
159            return (value.toString() + " of " + suit.toString());
160        }
161    
162    }