Created
November 3, 2015 23:59
-
-
Save Michael0x2a/6d7be7b0ff80480adc75 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Michael Lee | |
* Tuesday, April 14, 2015 | |
* Sample program: StackDeck2.java | |
* | |
* This class represents a deck of cards, which you can shuffle | |
* and manipulate. | |
*/ | |
import java.util.*; | |
public class StackDeck2 implements Deck { | |
private Stack<String> cards; | |
/** | |
* Creates an empty deck of cards. | |
*/ | |
public StackDeck2() { | |
this.cards = new Stack<String>(); | |
} | |
/** | |
* Returns the number of cards in the deck. | |
*/ | |
public int size() { | |
return this.cards.size(); | |
} | |
/** | |
* Returns {@code true} if the deck contains no cards, returns {@code false} otherwise. | |
*/ | |
public boolean isEmpty() { | |
return this.cards.isEmpty(); | |
} | |
/** | |
* Removes and returns the card currently at the top of the deck. | |
* | |
* @throws NoSuchElementException if the deck is empty | |
* @return the top-most card | |
*/ | |
public String dealCard() { | |
this.failIfUnableToRemove(1); | |
return this.cards.pop(); | |
} | |
/** | |
* Returns the requested amount of cards from the top of the deck. | |
* | |
* @param amount the amount of cards to remove | |
* | |
* @throws IllegalArgumentException | |
* if {@code amount} is negative | |
* @throws NoSuchElementException | |
* if {@code amount} exceeds the size of the deck | |
* | |
* @return a new deck containing the dealt cards, with the card at | |
* the top of this deck located at the bottom of the | |
* returned one. | |
*/ | |
public Deck dealCards(int amount) { | |
this.failIfUnableToRemove(amount); | |
StackDeck2 output = new StackDeck2(); | |
this.transfer(this.cards, output.cards, amount); | |
return output; | |
} | |
/** | |
* Adds a card to the top of the deck. | |
* | |
* @param card the card to add (cannot be null) | |
*/ | |
public void addCard(String card) { | |
this.cards.push(card); | |
} | |
/** | |
* Moves all the cards in the other deck to this one. | |
* | |
* <p>Note that the other deck of cards will be emptied | |
* after this operation is over. | |
* | |
* @param other the deck to empty and grab cards from (cannot be null) | |
*/ | |
public void mergeDeck(Deck other) { | |
while (!other.isEmpty()) { | |
this.cards.push(other.dealCard()); | |
} | |
} | |
/** | |
* Randomly shuffles the cards in the deck in place. | |
*/ | |
public void shuffle() { | |
// Implements a riffle shuffle -- splits the deck in two, | |
// and splices the two together. | |
// Note: this is an _imperfect_ shuffle. It doesn't actually | |
// randomly shuffle the deck in any way, making this a rigged deck. | |
int half = this.size() / 2; | |
Stack<String> temp1 = new Stack<String>(); | |
Stack<String> temp2 = new Stack<String>(); | |
// Split the deck in two | |
this.transfer(this.cards, temp1, half); | |
this.transfer(this.cards, temp2); // move everything else | |
// Take one card at a time from each half and add it back | |
for (int j = 0; j < half; j++) { | |
this.cards.push(temp1.pop()); | |
this.cards.push(temp2.pop()); | |
} | |
// Take care of the last card if we have an odd number of cards | |
if (!temp2.isEmpty()) { | |
this.cards.push(temp2.pop()); | |
} | |
} | |
/** | |
* Returns a copy of the contents of the card as a list without modifying | |
* the deck itself. | |
* | |
* <p>The card at the top of the deck will be placed at the end of the list. | |
*/ | |
public List<String> toList() { | |
Stack<String> temp = new Stack<String>(); | |
List<String> output = new ArrayList<String>(); | |
// Move cards to temp stack, reversing it. The bottom card is now | |
// at the top of the stack. | |
this.transfer(this.cards, temp); | |
// Moves everything back, and adds to the list in the correct order | |
while (!temp.isEmpty()) { | |
String card = this.move(temp, this.cards); | |
output.add(card); | |
} | |
return output; | |
} | |
/** | |
* Returns a string representing this deck. | |
* | |
* <p>Example output: | |
* | |
* <p>{@code [King of Spades, 9 of Hearts, Ace of Clubs, 4 of Spades, ...]} | |
* | |
* @return a String representing this stack, where each card is separated by | |
* comma, surrounded by brackets. The card at the top of the deck will | |
* be placed at the end of the string. | |
*/ | |
public String toString() { | |
if (this.isEmpty()) { | |
return "[]"; | |
} else { | |
Stack<String> temp = new Stack<String>(); | |
String output = this.move(this.cards, temp); | |
// Note: adds to the back of the string, not the front | |
// (so I can fencepost) | |
while (!this.cards.isEmpty()) { | |
String card = this.move(cards, temp); | |
output = card + ", " + output; | |
} | |
// Restores the stack | |
this.transfer(temp, this.cards); | |
return "[" + output + "]"; | |
} | |
} | |
/** | |
* Transfers everything in the 'src' stack to the 'dest' stack. | |
* | |
* <p>Neither deck can be null. | |
* | |
* @param src the stack to grab elements from | |
* @param dest the stack to add elements to | |
*/ | |
private void transfer(Stack<String> src, Stack<String> dest) { | |
this.transfer(src, dest, src.size()); | |
} | |
/** | |
* Transfers the top 'amount' of elements from the 'src' stack to | |
* the 'dest' stack. | |
* | |
* @param src the stack to grab elements from | |
* @param dest the stack to add elements to | |
* @param amount the amount of elements to transfer (amount must be less | |
* then or equal to the number of elements in src and cannot | |
* be negative) | |
*/ | |
private void transfer(Stack<String> src, Stack<String> dest, int amount) { | |
for (int i = 0; i < amount; i++) { | |
dest.push(src.pop()); | |
} | |
} | |
/** | |
* Moves one element from 'src' to 'dest', but returns that one element. | |
* | |
* <p>Neither stack can be null. | |
* | |
* @param src the stack to grab elements from (most contain at least | |
* one element) | |
* @param dest the stack to add elements to | |
* | |
* @return the item at the top of the 'src' stack | |
*/ | |
private String move(Stack<String> src, Stack<String> dest) { | |
String card = src.pop(); | |
dest.push(card); | |
return card; | |
} | |
/** | |
* Throws an NoSuchElementException if it is not possible to remove | |
* "n" cards from the deck, otherwise does nothing. | |
* | |
* @param n the number of elements to try checking | |
*/ | |
private void failIfUnableToRemove(int n) { | |
if (this.size() < n) { | |
throw new NoSuchElementException("Deck doesn't contain enough cards"); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment