001package hw0.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 */ 009public 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}