// ObjectList implementation of Hand interface. public class ObjectListHand extends ObjectListOps implements Hand { // This class extends ObjectListOps so that we may use // ObjectList methods without prefixing them with class names. private ObjectList cards; // Public Constructors // Returns an empty hand (i.e. a hand with no cards). public ObjectListHand () { // initialize the instance variable this.cards = empty(); } // Private Constructor, used in copy() method. private ObjectListHand (ObjectList cards) { this.cards = cards; } // Public Instance Methods // Returns the number of cards in the hand. public int size () { return length(cards); } // Adds a card c to the hand so it is at the last index. public void add (Card c) { cards = postpend(cards, c); } // Returns the card at index i in the hand. // The behavior is unspecified for indices out of range. public Card get (int i) { ObjectList c = cards; // traverse down list until we are looking at the requested card for (int counter = 0; counter < i; counter++) { c = tail(c); } return (Card) head(c); } // Inserts the card at index i to the hand. // The indices of all cards whose index was initially // greater than or equal to i are incremented by 1. // Valid indices are from 0 to size of hand, inclusive. // The behavior is unspecified for indices out of range. public void insert (int i, Card c) { // create a list which will hold the final result (our new hand) ObjectList newCards = empty(); // copy cards before the insertion index i from the old hand to // the new hand for (int counter = 0; counter < i; counter++) { newCards = postpend(newCards, head(cards)); cards = tail(cards); } // add the new card to our hand newCards = postpend(newCards, c); // copy the rest of the cards from the old hand to the new hand while(!isEmpty(cards)) { newCards = postpend(newCards, head(cards)); cards = tail(cards); } // set the instance variable to point to our new hand cards = newCards; } // Removes the card at index i from the hand and returns it. // The indices of all cards whose index was initially // greater than i are decremented by 1. // The behavior is unspecified for indices out of range. public Card remove (int i) { // create a list which will hold the final result (our new hand) ObjectList newCards = empty(); // copy the cards before the removal index from the old hand to // the new hand for (int counter = 0; counter < i; counter++) { newCards = postpend(newCards, head(cards)); cards = tail(cards); } // remember which card we're removing Card removedCard = (Card) head(cards); // do not copy the card to our new hand (skip it) cards = tail(cards); // copy the rest of the cards from the old hand to the new hand while (!isEmpty(cards)) { newCards = postpend(newCards, head(cards)); cards = tail(cards); } // set the instance variable to point to our new hand cards = newCards; // return the card removed return removedCard; } // Replaces the card at index i with c and returns the card replaced. // The behavior is unspecified for indices out of range. public Card set (int i, Card c) { // create a list which will hold the final result (our new hand) ObjectList newCards = empty(); // copy the cards before the set index from the old hand to // the new hand for (int counter = 0; counter < i; counter++) { newCards = postpend(newCards, head(cards)); cards = tail(cards); } // add the new card to our new hand newCards = postpend(newCards, c); // remember which card we're replacing Card replacedCard = (Card) head(cards); // do not copy the card to our new hand (skip it) cards = tail(cards); // copy the rest of the cards from the old hand to the new hand while (!isEmpty(cards)) { newCards = postpend(newCards, head(cards)); cards = tail(cards); } // set the instance variable to point to our new hand cards = newCards; // return the card removed return replacedCard; } // Rearranges the cards in the hand to be in card sorted order by index, // from low value to high value. public void sort () { // Implements insertion sort using auxiliary insertSort method. for (int i=1; i < length(cards); i++) { insertSort(i); } } // Assume that cards with indices [0..i-1] inclusive are in sorted order, lo to hi. // Insert card at i into correct position so that cards [0..i] will be in sorted order. private void insertSort (int i) { // Because ObjectLists are immutable (can not be modified), // this implementation of insertion sort is a little different from the typical ones. // Instead of comparing values from hi index to lo index with our insertion value, // it compares values from lo index to hi index. // Remember which card to insert. Card card = (Card)nth(i+1, cards); // 1-based index // Remove card from hand. this.remove(i); // Initialize the insertion index (start our search from lo index to hi index). int j=0; // Create "handle" to cards so we can iterate through the list // (i.e. "see" each card) without changing the hand itself. ObjectList c = cards; // Figure out where to insert the card in the hand. while ((j < i) && (((Card)head(c)).compareTo(card) < 0)) { c = tail(c); j++; } // Insert the card in the hand. insert(j, card); } // Returns a new Hand that has the same cards as this Hand. public Hand copy () { // Create "handle" to cards so we can iterate through the list // (i.e. "see" each card) without changing the hand itself. ObjectList c = cards; // Create a list which will be a duplicate of the list cards. ObjectList newCards = empty(); // Copy the list. while (!isEmpty(c)) { newCards = postpend(newCards, head(c)); c = tail(c); } // Create a new Hand from the list and return it. // Use a private constructor which takes a list as a parameter to do this. return new ObjectListHand(newCards); } // Returns the name of this class. public String className () { return "ObjectListHand"; } // Returns a String representation of this Hand. public String toString () { StringBuffer sb = new StringBuffer(); sb.append(this.className()); if (cards == null) return sb.toString(); ObjectList c = cards; sb.append("["); if (length(c) > 0) { sb.append(((Card)head(c)).toString()); c = tail(c); while (!isEmpty(c)) { sb.append(","); sb.append(((Card)head(c)).toString()); c = tail(c); } } sb.append("]"); return sb.toString(); } }