diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..939390a --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +*.prefs +*.project +*.classpath +target/ +*/target/* +*/target/** \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..430e654 --- /dev/null +++ b/README.md @@ -0,0 +1,36 @@ +Deck-o-Cards +========= + +## Description + +Following the principle of least surprise, this project represents a simple poker-style playing cards which has made reasonable decisions regarding implementation, in the possibility that it would become a foundational part of an application in the future. + +This implementation will randomly traverse and reorder all cards in deck using an in memory technique over a single pass of the deck. A card will be randomly selected and inserted at random at the end of the deck. + +## Installation +Then you can download this repository with the following command: + + git clone https://github.com/amadib/deck-o-cards.git + +## MainClass +The main class of this project is `Dealer` and can be found in Dealer.java. + +## Dependencies +This project has dependencies on log4j and can be built and ran using [Maven](http://maven.apache.org/download.cgi). + +The project may be built and executed with maven by running the following command: + + mvn install exec:java -Dmaven.test.skip=true + +Importing the project as an *Existing Maven Project* within eclipse with the [M2eclipse](https://www.eclipse.org/m2e/) plugin installed and running the following goal: + + install exec:java -Dmaven.test.skip=true + +*Note: log4j logging has been turned off by default.* + +###Version + +1.0 + +### Deprecated +Parts of the **com.appian.cards.Card** class have been deprecated in favor of a *"better"* solution. diff --git a/pom.xml b/pom.xml index f44b732..d412cd6 100644 --- a/pom.xml +++ b/pom.xml @@ -5,11 +5,46 @@ cards 0.0.1-SNAPSHOT Deck of Cards + + + + org.codehaus.mojo + exec-maven-plugin + 1.2.1 + + + default-cli + + java + + + com.appian.players.Dealer + + + + + + - org.apache.commons - commons-io - 1.3.2 + log4j + log4j + 1.2.15 + + + com.sun.jmx + jmxri + + + com.sun.jdmk + jmxtools + + + javax.jms + jms + + + \ No newline at end of file diff --git a/src/main/java/com/appian/cards/Card.java b/src/main/java/com/appian/cards/Card.java index 5e302cd..42832c0 100644 --- a/src/main/java/com/appian/cards/Card.java +++ b/src/main/java/com/appian/cards/Card.java @@ -18,14 +18,22 @@ public Card(Suit suit, Face face, Card previous, Card next) { } @Override public String toString(){ + if (face.ordinal() == 0 || face.ordinal() >= 10 ){ + return face.name() + " of " + suit.name(); + } else { + return (face.ordinal()+1) + " of " + suit.name(); + } + } + + public String printFaceFirst(){ return Utils.padRight(face.name(), 5) + " " + suit.name(); } - public String toStringBackwards() { + public String printSuitFirst() { return Utils.padRight(suit.name(), 8) + " " + face.name(); } - /* - * Deprecated methods + /** + * Deprecated methods */ @Deprecated private Card next = null; diff --git a/src/main/java/com/appian/cards/utils/Utils.java b/src/main/java/com/appian/cards/utils/Utils.java index 1fdf5d4..cc5a40d 100644 --- a/src/main/java/com/appian/cards/utils/Utils.java +++ b/src/main/java/com/appian/cards/utils/Utils.java @@ -3,29 +3,55 @@ import java.math.BigInteger; import java.util.Random; +import org.apache.log4j.Logger; + public class Utils { - + private static final Logger logger = Logger.getLogger(Utils.class); + + /** + * Returns true or false at random. + * + * @return true or false randomly + */ public static boolean rightOrLeft(){ -// int d = (int) (Math.random() * 100); -// System.out.println("random number is: " + d); - return ( (int) (Math.random() * 100) % 2 == 0 ) ? true : false; + int d = (int) (Math.random() * 100); + logger.debug("random number is: " + d); + return ( d % 2 == 0 ) ? true : false; } - private static int BITLENGTH = 17; - static Random rnd = new Random(); - static int previous = (int)Math.random() ; - public static int randomPostionBtw(int max){ + /** + * Returns a random number between a range; bounded by 0 and {@code max}. + * + * Randomly selects a number between 0-100, and uses the number to get a large prime number. + * Multiplies the prime number and the random number, takes the absolute + * value of the product and modulo {@code max}. + * + * @param max - the ceiling of randomly + * @return 0 if the maximum number is 0; + */ + public static int randomPostionBtwn(int max){ if (max == 0 ){ + logger.debug("randomPostionBtwn 0-" + padLeft(max + "", 2) +" => " + 0); return 0; } - int e = ( BigInteger.probablePrime(BITLENGTH, rnd)).intValue() ; - int d = ( (int) (Math.random() *(100)) * e % max); - previous = d; -// System.out.println("random number is: " + d ); - return d; + Random rnd = new Random(); + int randomNumber = (int) (Math.random() *(100)) ; + int BITLENGTH = randomNumber + 2; + int prime = (BigInteger.probablePrime(BITLENGTH, rnd)).intValue() ; + int randomPositionBtwn = Math.abs((randomNumber * prime) % max); + logger.debug("random number is: " + padLeft(randomNumber +"" , 2) + + ", the prime number:" + padLeft(prime+"", 7) + + ", randomPostionBtwn 0-" + padLeft(max + "", 2) +" => " + padLeft(randomPositionBtwn + "", 2)); + return Math.abs(randomPositionBtwn); } + public static String padRight(String s, int n) { return String.format("%1$-" + n + "s", s); } + + public static String padLeft(String s, int n) { + return String.format("%1$" + n + "s", s); + } + } diff --git a/src/main/java/com/appian/decks/DeckArrayList.java b/src/main/java/com/appian/decks/DeckArrayList.java index f0bc32f..88560d8 100644 --- a/src/main/java/com/appian/decks/DeckArrayList.java +++ b/src/main/java/com/appian/decks/DeckArrayList.java @@ -4,6 +4,8 @@ import java.util.Arrays; import java.util.List; +import org.apache.log4j.Logger; + import com.appian.cards.Card; import com.appian.cards.Face; import com.appian.cards.Suit; @@ -11,6 +13,7 @@ public class DeckArrayList implements IDeck{ + private static final Logger logger = Logger.getLogger(DeckArrayList.class); private List deck; static Card[] deckOfCards = new Card[52]; static { @@ -32,51 +35,85 @@ private DeckArrayList(){ deck = new ArrayList(Arrays.asList(deckOfCards)); } + /** + * Randomly reorders cards in deck using in memory technique over a single pass. + * + * Each card will be randomly selected and inserted at random at the end of the deck. + */ public void shuffle() { + if (deck.size() == 0){ + logger.warn("Deck is empty."); + return; + } boolean first = true; - for (int numberOfCards = deck.size()+1; numberOfCards >= 0; numberOfCards--){ - Card c = deck.remove(Utils.randomPostionBtw(numberOfCards)); - if (first){ - deck.add(c); + for (int numberOfCards = deck.size()-1; numberOfCards >= 0; numberOfCards--) + { + Card c = deck.remove(Utils.randomPostionBtwn(numberOfCards)); + if (first) { + deck.add(c); first = false; - } else { - int i = Utils.randomPostionBtw((deck.size())-numberOfCards); - deck.add((numberOfCards - 1) + i, c); + } + else { + int index = -1; + index = (numberOfCards - 1) + Utils.randomPostionBtwn((deck.size()) - numberOfCards); + if(index < 0){ + index *= index; + } + deck.add(index, c); } } } - + /** + * Returns one card from deck + * + * @return the topmost card; null if the deck is empty + */ public Card dealOneCard() { if(deck.size() > 0){ return deck.remove(0); } else { - System.err.println("Deck has no more cards."); + logger.warn("Deck has no more cards."); return null; } } + + @Override + public String toString(){ + if (deck.size() == 0 ){ + logger.warn("Deck is empty."); + return "Deck is empty."; + } + StringBuilder sb = new StringBuilder(); + int count = 1; + for(Card c : deck){ + sb.append(c.toString() + ((count < deck.size()) ? ", " : "")); + count++; + } + return sb.toString(); + } public void printSuitFirst() { for(Card c : deck){ - System.out.println(c.toStringBackwards()); + System.out.println(c.printSuitFirst()); } } - public void printSuitFirstBackwards() { + public void printBackwardsSuitFirst() { for(int i = deck.size(); i >= 0; i--){ - System.out.println(deck.get(i).toStringBackwards()); + System.out.println(deck.get(i).printSuitFirst()); } } - public void printBackwards() { + public void printBackwardsFaceFirst() { for(int i = deck.size(); i >= 0; i--){ - System.out.println(deck.get(i).toString()); + System.out.println(deck.get(i).printFaceFirst()); } } - public void print() { + public void printFaceFirst() { for(Card c : deck){ - System.out.println(c.toString()); + System.out.println(c.printFaceFirst()); } } } diff --git a/src/main/java/com/appian/decks/IDeck.java b/src/main/java/com/appian/decks/IDeck.java index 59b175b..d325166 100644 --- a/src/main/java/com/appian/decks/IDeck.java +++ b/src/main/java/com/appian/decks/IDeck.java @@ -20,9 +20,9 @@ public interface IDeck { public Card dealOneCard(); public void printSuitFirst(); - public void printSuitFirstBackwards(); + public void printBackwardsSuitFirst(); - public void printBackwards(); + public void printFaceFirst(); + public void printBackwardsFaceFirst(); - public void print(); } diff --git a/src/main/java/com/appian/players/Dealer.java b/src/main/java/com/appian/players/Dealer.java index e9e29db..4d96008 100644 --- a/src/main/java/com/appian/players/Dealer.java +++ b/src/main/java/com/appian/players/Dealer.java @@ -1,22 +1,42 @@ package com.appian.players; +import org.apache.log4j.Logger; + import com.appian.cards.Card; import com.appian.decks.DeckArrayList; import com.appian.decks.IDeck; - +/** + * Main class of Deck-o-Cards + * + * Dealer will get a deck of cards and proceed to shuffle twice + * before dealing out the entire deck. + * + */ public class Dealer { - static IDeck deck = DeckArrayList.getNewDeck(); - + private static final Logger logger = Logger.getLogger(Dealer.class); + public static void main(String[]args){ - deck.print(); - System.out.println("============Shuffle=============="); + IDeck deck = DeckArrayList.getNewDeck(); + deck.printFaceFirst(); + System.out.println("============First Shuffle==============="); deck.shuffle(); deck.printSuitFirst(); + System.out.println("============Second Shuffle=============="); + deck.shuffle(); + System.out.println(deck); System.out.println("============Empty The Deck=============="); int i = 54; while(i-- != 0){ Card card = deck.dealOneCard(); - System.out.println("Drew " + card); + if (card == null){ + System.out.println("No Jokers here!"); + } else { + System.out.println("Drew " + card); + } } + System.out.println(deck); + System.out.println("========Shuffle an Empty Deck========"); + deck.shuffle(); + System.out.println(deck); } } diff --git a/src/main/resources/log4j.xml b/src/main/resources/log4j.xml new file mode 100644 index 0000000..f1ebc63 --- /dev/null +++ b/src/main/resources/log4j.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file