CS 124, Spring 2013
Lab 13: Arrays and Video Poker

The new topic for the last two labs is arrays. This week, you will work on a GUI program that implements a "video poker slot machine" in which an array is used to store the cards in a poker hand. The lab asks you to create the GUI program from scratch. It will use much of what you have learned about GUI programming in the last few weeks. Next week's lab will be a short exercise on two-dimensional arrays that you are expected to finish in the lab period. Both labs will be due together by noon on Saturday, May 4.

To begin the lab, start a new project named lab13. You will need to add all the files from /classes/cs124/lab13-files to the src directory of the project: PokerCard.java, PokerDeck.java, PokerRank.java, and cards.png. These files implement many aspects of the poker game that you are not responsible for writing yourself.

Video Poker

In video poker, a player is dealt a hand of five playing cards. The user selects some cards in the hand to be discarded. (The user can select anywhere from 0 to all 5 cards to discard.) The selected cards are replaced by new cards to give the final poker hand. The user places a bet on each hand. Different kinds of hands give different payouts on the bet. To win anything, the user must have a pair of Jacks or better. Here is a table of the payouts, taken from the Wikipedia Video Poker article:

HandPayout
Royal Flush250
Straight Flush50
Four-of-a-kind25
Full House9
Flush6
Straight4
Triple3
Two Pair2
Pair, Jacks or Better1

For example, if the hand is a Straight, then the user receives four times the amount of their bet as a payout. (This is after their bet has already been placed, so they really get their bet back, plus 3 times their bet.) For a pair of Jacks or better, the user just gets their bet back.

Your assignment is to simulate Video Poker in a GUI program. The program should look approximately like this:

The amount of the user's bet is given by the contents of a JTextField at the bottom of the window. The user clicks a "DEAL" button to begin the game and receive five new cards. At this time, the user's bet amount is subtracted from the user's money. The user can select a card to be discarded by clicking on it; the card is turned face down. If the clicks a face-down card, it is turned face up again and is not discarded. The user then clicks "DRAW" to get replacements for the cards they have discarded. This ends the game. The user's hand is evaluated, and any payout is added to the user's money. Note that the "DEAL" button is only enabled between games, and the "DRAW" button is only enabled during a game.

My solution to this lab can be found in /classes/cs124/VideoPoker.jar. You should try it out. Make sure that you understand how the game is supposed to work.

You should create your program from scratch, but you can certainly look back at examples that do similar things. In particular, you might look at the Hangman program from Lab 12 and the drawing example that we looked at in class, /classes/cs124/LineDraw.java.

Some Code

You won't need to understand much about poker to complete this assignment. The knowledge of poker is provided in the three files PokerCard.java, PokerDeck.java, and PokerRank.java. A PokerCard represents one playing card. Your program will need an array of five PokerCards to hold the user's cards. A PokerDeck represents a deck of cards. You will need two methods from this class: If deck is of type PokerDeck, then

An object of type PokerRank is used to check a poker hand to determine its value. It is only used in the following method, which you can copy into your program:

/**
 * Evaluates a hand of five poker cards.  The return value is the hand's "rank",
 * which is one of the following constants:  PokerRank.NOTHING, PokerRank.PAIR,
 * PokerRank.TWO_PAIR, PokerRank.TRIPLE, PokerRank.STRAIGHT, PokerRank.FLUSH, 
 * PokerRank.FULL_HOUSE, PokerRank.FOUR_OF_A_KIND, PokerRank.STRAIGHT_FLUSH, or 
 * PokerRank.ROYAL_FLUSH.  Note that PokerRank.PAIR is only returned for a pair 
 * of Jacks or better.  PokerRank.NOTHING is returned for a hand that is less 
 * than a pair of Jacks, which gets no payout in this game.
 */
private int getPokerRank( PokerCard[] cards ) {
    PokerRank ranker = new PokerRank();
    for (int i = 0; i < 5; i++)
        ranker.add(cards[i]);
    int rank = ranker.getHandType();
    if (rank == PokerRank.PAIR) {
           // if it's not at least a pair of Jacks, return NOTHING rather than PAIR
        PokerCard c = ranker.getCards().get(0);
        if ( c.getValue() < PokerCard.JACK )
            rank = PokerRank.NOTHING;
    }
    return rank;
}

Another difficult part of the program is painting the cards onto the screen. The card images are in the file cards.png. To use this file, you have to load it into an "Image." Add the following instance variable to your program:

private Image cardImage;

To load the images, add the following code to your class's constructor:

try {
    cardImage = ImageIO.read(getClass().getClassLoader().getResource("cards.png"));
}
catch (Exception e) {
    cardImage = null;
}

(You will have to import javax.imageio.ImageIO.) For drawing the cards, you can use the following two methods:

/**
 * Draws a specified PokerCard in the Graphics context g, with its upper-left
 * corner at the point (x,y).  The card is 79 pixels wide and 123 pixels tall.
 */
private void drawCard(Graphics g, PokerCard card, int x, int y) {
    int cx;    // x-coord of upper left corner of the card inside cardsImage
    int cy;    // y-coord of upper left corner of the card inside cardsImage
    if (card.getValue() == 14)
        cx = 0;
    else
        cx = (card.getValue()-1)*79;
    switch (card.getSuit()) {
    case PokerCard.CLUBS:    
        cy = 0; 
        break;
    case PokerCard.DIAMONDS: 
        cy = 123; 
        break;
    case PokerCard.HEARTS:   
        cy = 2*123; 
        break;
    default:  // spades   
        cy = 3*123; 
        break;
    }
    g.drawImage(cardImage,x,y,x+79,y+123,cx,cy,cx+79,cy+123,this);
}

/**
 * Draws a face-down card in the Graphics context g with its upper left
 * corner at the point (x,y).
 */
private void drawFaceDownCard(Graphics g, int x, int y) {
    int cx;    // x-coord of upper left corner of the card inside cardsImage
    int cy;    // y-coord of upper left corner of the card inside cardsImage
    cy = 4*123;   // coords for a face-down card.
    cx = 2*79;
    g.drawImage(cardImage,x,y,x+79,y+123,cx,cy,cx+79,cy+123,this);
}

Note that the cards are 79 pixles by 123 pixels. You will have to calculate where you want to put the top left corners of each of the five cards, and you will have to decide how big to make the display area in order to hold the cards and whatever messages you want to show to the user. When the user clicks on the display, you will have to determine which card the click is inside, if any, which requires just a little bit of math. You do not have to do anything with the variable cardsImage outside the code that is given here.

Of course, one of the major topics of the lab is arrays. You will need an array of PokerCards to hold the user's cards. At the start of a game, you will deal cards from a PokerDeck into the user's hand. You will also use the deck later, when you replace the user's discarded cards. You will find that you also need to keep track of whether each card is face-up or face-down. For that, I suggest using an array of booleans. So, you should add the following three instance variables to your class:

private PokerDeck deck = new PokerDeck();
private PokerCard[] cards = new PokerCard[5];
private boolean[] faceUp = new boolean[5];

And that's it! We will go over some relevant examples of using arrays in class on Wednesday, and you are welcome to ask me questions about how to write the program, but it's up to you to write the rest of the program.