Skip to content

Instantly share code, notes, and snippets.

@Michael0x2a
Created November 3, 2015 23:58
Show Gist options
  • Save Michael0x2a/f581e1afb1203708f2e1 to your computer and use it in GitHub Desktop.
Save Michael0x2a/f581e1afb1203708f2e1 to your computer and use it in GitHub Desktop.
// Michael Lee
// Section AP
// Tuesday, April 14, 2015
// Sample program: ListDeck.java
//
// This class represents a deck of cards, which you can shuffle
// and manipulate.
import java.util.*;
public class ListDeck implements Deck {
private List<String> cards;
private Random random;
// Creates an empty deck of cards.
public ListDeck() {
this.cards = new ArrayList<String>();
this.random = new Random();
}
// Returns the number of cards in the deck.
public int size() {
return this.cards.size();
}
// Returns 'true' if the deck contains no cards, returns 'false' otherwise.
public boolean isEmpty() {
return this.cards.isEmpty();
}
// Removes and returns the card currently at the top of the deck.
//
// Preconditions:
// - The deck is not empty (otherwise throws NoSuchElementException)
public String dealCard() {
this.failIfUnableToRemove(1);
return this.cards.remove(this.cards.size() - 1);
}
// Returns the requested amount of cards from the top of the deck.
//
// Preconditions:
// - "amount" must not be negative (otherwise throws IllegalArgumentException)
// - "amount" must not exceed the size of the deck
// (otherwise throws NoSuchElementException)
//
// Postconditions:
// - Returns a new Deck containing the 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);
Deck output = new ListDeck();
// Cycle through cards to transfer them
for (int i = 0; i < amount; i++) {
output.addCard(this.dealCard());
}
return output;
}
// Adds a card to the top of the deck.
//
// Preconditions:
// - The card is not null
public void addCard(String card) {
this.cards.add(card);
}
// Moves all the cards in the other deck to this one.
//
// Preconditions:
// - "other" must not be null
//
// Postconditions:
// - The other deck will be emptied of all cards
public void mergeDeck(Deck other) {
while (!other.isEmpty()) {
this.cards.add(other.dealCard());
}
}
// Randomly shuffles the cards in the deck in place.
public void shuffle() {
// Implements the Fisher-Yates shuffle algorithm
// http://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle
for (int currIndex = 0; currIndex < this.cards.size(); currIndex++) {
// Selects a random card beyond this one (apparently, selecting
// literally any card results in an imperfect, not fully random
// shuffle, according to math).
int randIndex = this.randomInt(currIndex, this.cards.size() - 1);
this.swap(currIndex, randIndex);
}
}
// Returns a copy of the contents of the card as a list without modifying
// the deck itself.
//
// Postconditions:
// - The card at the top of the deck will be placed at the end of the list.
public List<String> toList() {
// Making a copy so that if the client modifies the returned list,
// they won't modify the field.
return new ArrayList<String>(this.cards);
}
// Returns a string representing this deck.
//
// Postconditions:
// - Each card will be separated by comma, surrounded by brackets
// - The card at the top of the deck will be placed at the end of the string.
//
// Example of output:
//
// [King of Spades, 9 of Hearts, Ace of Clubs, 4 of Spades, ...]
//
public String toString() {
return this.cards.toString();
}
// Swaps the two cards at the given indexes.
//
// Preconditions:
// - The two indexes must be valid indexes (ie 0 <= index < size)
private void swap(int indexA, int indexB) {
String cardA = this.cards.get(indexA);
String cardB = this.cards.get(indexB);
this.cards.set(indexA, cardB);
this.cards.set(indexB, cardA);
}
// Returns a random int from min to max, inclusive.
//
// Preconditions:
// - 'max' must be greater then or equal to min.
//
// Postcondition:
// - Returns a random int from min <= output <= max
private int randomInt(int min, int max) {
// Adding '1' to make sure the output is completely inclusive.
return this.random.nextInt((max - min) + 1) + min;
}
// Throws an NoSuchElementException if it is not possible to remove
// "n" cards from the deck, otherwise does nothing.
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