import java.util.*; /** * Aces High. Functional Solution. * Sample Output: http://pastebin.com/raw.php?i=RN5UrCXY * @author jdalbey * @version Sep 2015 */ public class AcesHighFunctional { private Scanner scanner = new Scanner(System.in); private final static int kNumPiles = 4; /* The four piles of cards */ private Stack[] cardPiles; /* The deck of 52 playing cards */ private Stack deck; /** Construct the application */ @SuppressWarnings("unchecked") public AcesHighFunctional() { // Initialize the card piles cardPiles = (Stack[]) new Stack[kNumPiles]; } /** Entry point for the application. * @param args ignored */ public static void main(String[] args) { // Instantiate this class AcesHighFunctional app = new AcesHighFunctional(); // See if a command line argument was given if (args.length != 0) { // Create deck from a single string of 52 card names with NO embedded blanks app.createDeckFromString(args[0]); } else { // create a random deck app.createRandomDeck(); } // run the game app.run(); } /** Play the game until the user quits or the game is over. */ public void run() { // Initialize the Piles of cards initPiles(); // Deal four cards dealFour(); // Show Welcome message System.out.println("See rules at: http://pastebin.com/raw.php?i=dhsNmQeq"); System.out.println("Welcome to Aces High"); // Display the table printTable(); char userAction; boolean notDone = true; // repeat until game over do { // Display the prompt System.out.println("Enter pile number 1-4, D for draw, Mx for Move, or Q for quit"); // Obtain user's turn String line = scanner.next(); userAction = Character.toLowerCase(line.charAt(0)); // IF User wants to draw THEN if (userAction == 'd') { // deal four cards notDone = dealFour(); } // IF user wants to move a card THEN else if (userAction == 'm') { // Move a card to an empty space char choice = Character.toLowerCase(line.charAt(1)); int pile = choice - '1'; move(pile); } // IF user isn't quitting THEN else if (userAction != 'q') { // assume user wants to discard from a given pile int pile = userAction - '1'; discard(pile); } // Display table printTable(); } while (userAction != 'q' && notDone); // Display score System.out.println("Your score is " + getScore()); } /** Perform a discard. * @pile desired pile from which to discard the top card */ public void discard(int pile) { // is legal pile number if (pile >= 0 && pile < kNumPiles) { // is it legal to discard the top card on this pile? if (canDiscard(pile)) { // remove the top card from the pile removeTop(pile); } } else { System.out.println("Sorry, pile must be between 1 and 4."); } } /** Perform move to empty spot. * @param desired pile from which to move the top card */ public void move(int pile) { // if the chosen pile is legal if (pile >= 0 && pile < kNumPiles) { // if there is an available spot if (canMove(pile) > -1) { // move the top card to the empty pile moveTop(pile); } } // ELSE show an error message else { System.out.println("Sorry, pile must be between 1 and 4."); } } /** Create the empty card piles */ public void initPiles() { // Create four empty stacks of cards for (int pile = 0; pile < cardPiles.length; pile++) { cardPiles[pile] = new Stack(); } } /** Deal one card from the deck onto each pile. * @return false if unable to deal all four cards. */ public final boolean dealFour() { boolean result = true; // place a card on each pile from the deck try { cardPiles[0].push(dealCard()); cardPiles[1].push(dealCard()); cardPiles[2].push(dealCard()); cardPiles[3].push(dealCard()); } catch (EmptyStackException ex) { result = false; } return result; } /** See if the card on top of pileNum can be discarded. * @param pileNum the number of the pile selected for discard. * @pre 0 <= pileNum < 4 * @return true if there exists another visible card of the same suit * with a higher rank than the top card of selected pile. */ public boolean canDiscard(int pileNum) { boolean result = false; // is the chosen pile occupied? if (!cardPiles[pileNum].isEmpty()) { int chosen = cardPiles[pileNum].peek(); // consider each pile for (int pile = 0; pile < cardPiles.length; pile++) { // is another pile occupied? if (pile != pileNum && !cardPiles[pile].isEmpty()) { // is the visible card of the same suit and higher rank? if (lessThan(chosen, cardPiles[pile].peek())) { // result is true result = true; } } } } // return result return result; } /** Remove the top card from selected pile. * @param pileNum selected pile * @pre cardPiles[pileNum].size() > 0 */ public void removeTop(int pileNum) { cardPiles[pileNum].pop(); } /** See if the card on top of pileNum can be moved. * @param pileNum the number of the pile selected for discard. * @pre 0 <= pileNum < 4 * @return the available pilenumber, if it exists, otherwise -1 */ public int canMove(int pileNum) { int result = -1; // consider all the piles for (int pile = 0; pile < cardPiles.length; pile++) { // is there an empty pile? if (pile != pileNum && cardPiles[pile].isEmpty()) { // store this pile as the one we want result = pile; } } // return target pile return result; } /** Move the top card from selected pile to an empty pile. * @param pileNum selected pile * @param emptyPile the pile number of the empty pile * @pre canMove(pileNum) > -1 */ public void moveTop(int pileNum) { cardPiles[canMove(pileNum)].push(cardPiles[pileNum].pop()); } /** Compute the score; how many cards are left on the table. * @return the table score. */ public int getScore() { int total = 0; // Accumulate the number of cards in each pile for (int pile = 0; pile < cardPiles.length; pile++) { total += cardPiles[pile].size(); } return 52 - total; } /** Print the table. */ public void printTable() { String result = ""; // Get each pile in turn for (int pile = 0; pile < cardPiles.length; pile++) { String line = ""; // Get each card from this pile for (Integer card: cardPiles[pile]) { // Add this card's symbol to the line line = line + getCard(card) + ' '; } result += line + "\n"; } // show the result System.out.println(result); } /** Construct a deck of cards in random order. */ public void createRandomDeck() { deck = new Stack(); // add 52 cards to the deck for (int card = 0; card <= 51; card++) { // pust this number onto the deck deck.push(new Integer(card)); } // shuffle the deck Collections.shuffle(deck); } /** Construct a deck of cards in the order specified. @param cardInput a string of 52 card abbreviations with no blanks, E.g., "2C5HTJ..." */ public void createDeckFromString(String cardInput) { deck = new Stack(); for (int x = 0; x < cardInput.length(); x = x + 2) { char rank = cardInput.charAt(x); char suit = cardInput.charAt(x+1); int rankNum = rankSymbols.indexOf(rank); int suitNum = suitSymbols.indexOf(suit); int cardvalue = suitNum * 13 + rankNum; deck.push(cardvalue); } } /** Deal (remove and return) the top card from the deck. * @return the top card */ public int dealCard() { return deck.pop(); } /** Determine if the deck has no more cards. * @return true if the deck is empty. */ public boolean isEmpty() { return deck.empty(); } /* * Card represents one of the 52 cards in a * standard deck of playing cards. Each card has a suit and a rank. * The card is represented as an integer between 0 and 51 inclusive. */ //private final String suits = "CCCCCCCCCCCCCDDDDDDDDDDDDDSSSSSSSSSSSSSHHHHHHHHHHHHH"; private final static String rankSymbols = "23456789TJQKA"; private final static String suitSymbols = "CDSH"; /** Accessor to the rank symbol of a card. * @param card the card for which the rank is extracted */ public char getRank(int card) { // ranks go from 2 to K then Ace, which correspond to ints 0 - 12. return rankSymbols.charAt(card % 13); } /** Accessor to the suit symbol of a card. * @param card the card for which the suit is extracted */ public char getSuit(int card) { return suitSymbols.charAt(card / 13); } /** Return a printable representation of this card. * This implementation returns a 2 letter abbreviation. * @return abbrevation of the card, e.g., "2C" */ public String getCard(int card) { //return "" + getRank(card) + suits.charAt(card); return "" + getRank(card) + getSuit(card); } /** Does this card have the same suit and a lower rank * than Other card. * @param card1 first card to be compared * @param card2 other card to be compared * @return true if card1 is less than card2 */ public boolean lessThan(int card1, int card2) { boolean result = false; // Suits equal? if (getSuit(card1) == getSuit(card2)) { // rank lower? if (card1 < card2) { // indicate it's good! result = true; } } // return result return result; } //"2C3C4C5C6C7C8C9CTCJCQCKCAC2D3D4D5D6D7D8D9DTDJDQDKDAD2H3H4H5H6H7H8H9HTHJHQHKHAH2S3S4S5S6S7S8S9STSJSQSKSAS" //"2C 3C 4C 5C 6C 7C 8C 9C TC JC QC KC AC 2D 3D 4D 5D 6D 7D 8D 9D TD JD QD KD AD 2H 3H 4H 5H 6H 7H 8H 9H TH JH QH KH AH 2S 3S 4S 5S 6S 7S 8S 9S TS JS QS KS AS " }