Poker Demo

<< Object Space Demo | Applets | Removing Windoze Flicker >>

Card.java

package poker;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import javax.swing.JApplet;
import java.awt.*;

/**
 * class Card here represents a playing card
 * 
 * @author Chris Thiel 
 * @version 28 Sept 2008
 */
public class Card 
{
    //some handy constants
    public static final int SPADES=3;
    public static final int HEARTS=2;
    public static final int DIAMONDS=1;
    public static final int CLUBS=0;
    /**
     * suitName is an array contains the name of the Suit 
     * so that the index matches the suit number
     */
    public static final String[] suitName={"Clubs","Diamonds","Hearts","Spades" };
    /**
     * suitSymbol Have the unicode values to print the correct symbol, 
     * arranges so thet the index matches the suit number
     */
    public static final String[] suitSymbol={"\u2663", "\u2666","\u2665","\u2660"};
    /**
     * pipName is an array that contains the name of the card's pips 
     * so that the index matches the number of the card.
     * For example pipName[1] has a "Ace"
     */
    public static final String[] pipName={"-","Ace","2","3","4","5","6","7","8","9","10",
                                    "Jack","Queen","King"};
    // instance variables - or Card Attributes
    /**
     * suit contains the suit (0 to 3)
     */
    private int suit; 
    /**
     * pips contains the number of pips of the card (1-13)
     * Ace is 1 and 13 is King
     */
    private int pips;
    /**
     * faceUp is true is the card is exposed
     * and false otherwise.  
     */
    private boolean faceUp;

    /**
     * Default Constructor for objects of class Card
     * is a random card of a random suit
     */
    public Card()
    {
        // The default card is randomly chosen
        suit = (int)(Math.random()*4);
        pips = 1+(int)(Math.random()*13);
        faceUp=false;
    }
    /**
     * A Card can be constructed with a determined 
     * number of pips (and integer 1-13) 
     * and suit (an integer from 0-3)
     */
    public Card(int p, int s)
    {
        if (s>=0 && s<4) suit = s;
        if (p>0 && p<14) pips = p;
        faceUp=false;
    }
    /**
     * A Card can be constructed with a determined 
     * number of pips (a String "Ace" to "King") 
     * and suit (a String "Clubs" to "Spades")
     */
    public Card(String p, String s)
    {
        suit = indexOf(suitName, s);
        pips = indexOf(pipName, p);
        faceUp=false;
    }
    /**
     * indexOf returns the index of the String s
     * in the String Array a
     * (it returns -1 if not found). This method
     * ignores case.
     */
    public int indexOf(String[] a, String s)
    {
        int idx=-1;
        for (int i=0; i< a.length; i++)
           if (a[i].toLowerCase().equals(s.toLowerCase())) idx=i;
        return idx;
    }
    /**
     * @return getSuit returns the Card's suit,
     * an int from 0 to 3
     */
    public int getSuit()
    {

        return suit;
    }
    /**
     * setSuit changes the Card's suit,
     * @param  the suit 0 to 3.  You can use the 
     * predefined integer constants 
     * SPADES, HEARTS, DIAMONDS and CLUBS
     * from the Card class.
     */

    public void setSuit(int s)
    {      
        if (s>=0 && s<4) suit=s;
    }
    /**
     * @return getPips returns the Card's pips,
     * an int from 1 to 13 where an Ace is a 1
     * and a King is a 13.
     */
    public int getPips()
    {

        return pips;
    }
    public int getPipsAceHigh()
    {
        if (pips==1) return 14;
        return pips;
    }
    /**
     * setPips changes the Card's pips,
     * @param  the pips are an integer from 1 to 13,  
     * where 1 is an Ace and 13 is a King.
     */
    public void setPips(int p)
    {
        // put your code here
        if (p>0 && p<14) pips=p;
    }

    /**
     * @return getSuit returns the Card's suit,
     * an int from 0 to 3
     */
    public int getValue()
    {
        if (pips>9) return 10;
        return pips;
    }
    /**
     * Two cards are equal if they have
     * the same number of pips.  The suit is ignored
     * with this comparison
     * 
     * @return true if they match the number of pips
     */
    public boolean equals(Card c)
    {
        if (c.getPips()==pips) return true;
        return false;
    }
    /**
     * toString will return the contents of the card 
     * in a string format
     * @return The pips and suit of a card
     */
    public String toString()
    {
        return pipName[pips]+" of "+suitName[suit];
    }
    /**
     * info will return the contents of the card 
     * in a short two character string
     * @return The pips and suit of a card
     */
    public String info()
    {
        if (pips==10) return pipName[pips].substring(0,2)+suitSymbol[suit];
        return pipName[pips].substring(0,1)+suitSymbol[suit];
    }
    /**
     * comparePips will return the difference between 
     * two cards' number of pips.  The suit is ignored
     * with this comparison.  Here the ace is low.
     * If the two cards happen to have the same
     * number of pips, it returns the integer 0. 
     * 
     * If, for example,
     * card1 is a 2 of clubs and card2 is a 6 of spades, 
     * then card1.comparePips(card2) returns -4, since
     * card1 has four less pips than card2.
     * 
     * @return the difference between number of pips
     */
    public int comparePips( Card c )
    {
        return pips-c.getPips();
    }
    /**
     * comparePipsAceHigh will return the difference between 
     * two cards' number of pips, Ace High.  The suit is ignored
     * with this comparison, but the Ace is above a King.
     * If the two cards happen to have the same
     * number of pips, it returns the integer 0. 
     * 
     * If, for example,
     * card1 is an ace of clubs and card2 is a queen of spades, 
     * then card1.comparePips(card2) returns 2, since
     * card1 is two larger than card2.
     * 
     * @return the difference between number of pips
     */
    public int comparePipsAceHigh( Card c )
    {
        // This needs to be be implemented
        int myPips=pips;
        int theirPips=c.getPips();
        if (myPips==1) myPips=14;
        if (theirPips==1) theirPips=14;

    	return myPips-theirPips;
    }
    /**
     * isLessThan will compare two cards by pips, and in case of 
     * a match, will compare the suit.  If the number
     * of pips match, then the higher suit is considered.
     * 
     * The the order of the suits
     * (from high to low) is SPADES, HEARTS, DIAMONDS, CLUBS
     * 
     * The Ace is low, and is considered to be below a 2.
     * 
     * If the two cards happen to have the same
     * number of pips, it then compares the suit returns the integer 0. 
     * 
     * If, for example,
     * card1 is an ace of clubs and card2 is a 2 of spades, 
     * then card1.comparePips(card2) returns true, since
     * card1 is less than card2.
     * 
     * If card1 is a 6 of hearts and card2 is a 6 of clubs,
     * than card1.isLessThan(card2) returns false,
     * since hearts is greater than clubs
     * 
     * @return the difference between number of pips
     */
    public boolean isLessThan( Card c )
    {

    	if (pips>c.getPips()) return false;
    	if (pips<c.getPips()) return true;
    	//if we got this far, its the same number of pips
    	if (suit <c.getSuit()) return true;
    	// if we got this far, it must have same suit or more
        return false;
    }
    public boolean isLessThanAceHigh( Card c )
    {
    	int myPips=pips;
        int theirPips=c.getPips();
        if (myPips==1) myPips=14;
        if (theirPips==1) theirPips=14;
    	if (myPips>theirPips) return false;
    	if (myPips<theirPips) return true;
    	//if we got this far, its the same number of pips
    	if (suit <c.getSuit()) return true;
    	// if we got this far, it must have same suit or more
        return false;
    }
    public void turnUp(){
    	faceUp=true;
    }
    public void turnDown(){
    	faceUp=false;
    }
    public void turnOver(){
    	faceUp=!faceUp;
    }
    public boolean isFaceUp(){
    	return faceUp;
    }
    public void draw(Graphics g, int x, int y){
    	g.setColor(Color.WHITE);

		Rectangle loc=new Rectangle(x,y,60,80);
		if (faceUp){
			g.setFont(new Font("Helvetica", Font.BOLD,  20));
			g.setColor(Color.WHITE);
			g.fillRect(loc.x,loc.y,loc.width,loc.height);
			g.setColor(Color.BLACK);
			g.drawRect(loc.x,loc.y,loc.width,loc.height);
			if (suit>0 && suit<3) 
			g.setColor(Color.RED);
			g.drawString(this.info(), loc.x+8,loc.y+23);
		} else {
			g.setColor(Color.BLUE);
			g.fillRect(loc.x,loc.y,loc.width,loc.height);
			g.setColor(Color.BLACK);
			g.drawRect(loc.x,loc.y,loc.width,loc.height);
			g.setColor(Color.WHITE);
			for (int i=2; i<25; i+=5)
				g.drawRoundRect(loc.x+i, loc.y+i, loc.width-i*2, loc.height-i*2,
						i, i);
		}

    }
    public void draw(Graphics2D g2, Rectangle loc){
    	g2.setColor(Color.WHITE);
		int letterSize=5*loc.width/12;
		if (faceUp){
			g2.setFont(new Font("Helvetica", Font.BOLD,  letterSize));
			g2.setColor(Color.WHITE);
			g2.fill(loc);
			g2.setColor(Color.BLACK);
			g2.draw(loc);
			if (suit>0 && suit<3) 
			g2.setColor(Color.RED);
			g2.drawString(this.info(), loc.x+8,loc.y+7*letterSize/6);
		} else {
			g2.setColor(Color.BLUE);
			g2.fill(loc);
			g2.setColor(Color.BLACK);
			g2.draw(loc);
			g2.setColor(Color.WHITE);
			for (int i=2; i<25; i+=5)
				g2.drawRoundRect(loc.x+i, loc.y+i, loc.width-i*2, loc.height-i*2,
						i, i);
		}

    }
    public void draw(Graphics2D g2, Rectangle loc, Image cardBack, JApplet a){
    	g2.setColor(Color.WHITE);
		int letterSize=5*loc.width/12;
		if (faceUp){
			g2.setFont(new Font("Helvetica", Font.BOLD,  letterSize));
			g2.setColor(Color.WHITE);
			g2.fill(loc);
			g2.setColor(Color.BLACK);
			g2.draw(loc);
			if (suit>0 && suit<3) 
			g2.setColor(Color.RED);
			g2.drawString(this.info(), loc.x+8,loc.y+7*letterSize/6);
		} else {
			g2.drawImage(cardBack, loc.x, loc.y, loc.width, loc.height,a);

		}

    }
}

Deck.java

package poker;

import java.util.ArrayList;

/**
 * 
 * @author Chris Thiel, OFMCap 
 * @version 16 May 2012
 */
public class Deck 
{
	private ArrayList<Card> deck;
	public Deck(){
		deck=new ArrayList<Card>();
		for (int s=0;s<4;s++)
			for(int p=1;p<=13;p++)
				deck.add(new Card(p,s));
		shuffle();
	}
	public void shuffle(){
		for (int i=0; i<400;i++){
			int a=(int)(deck.size()*Math.random());
			int b=(int)((deck.size()-1)*Math.random());
			Card temp=deck.get(a);
			deck.remove(temp);
			deck.add(b, temp);
		}
	}
	public Card deal(){
		Card result=deck.get(0);
		deck.remove(0);
		return result;
	}

}

PokerHand.java


package poker;

import java.util.ArrayList;
/**
 * PokerHand evaluates poker hands.
 * it requires the Card class.
 * 
 * @author Chris Thiel, OFMCap 
 * @version 28 Nov 2009
 */
public class PokerHand
{
    private Card[] hand;
    private Card highCard;
    private double score;
    /**
     * Constants
     * 
     */
    final String[] r={"High Card","One Pair", "Two Pair", "Three of a Kind","Straight", "Flush", "Full House", "Four of a Kind", "Straight Flush", "Royal Flush"}; 
    /**
     * Constructors
     */

    public PokerHand(Card c1, Card c2, Card c3, Card c4, Card c5)
    {
         hand = new Card[5];
         hand[0]=c1;
         hand[1]=c2;
         hand[2]=c3;
         hand[3]=c4;
         hand[4]=c5;
         highCard=hand[0];
         for (int i=1; i<5;i++)
            if (highCard.isLessThanAceHigh(hand[i])) 
                highCard=hand[i];
         sortAceHigh();
         score=computeScore();
    }
    public PokerHand(ArrayList<Card> list)
    {
        hand = new Card[5];
        highCard=list.get(0);
        for (int i=0;i<5;i++)
        {
            hand[i]=list.get(i);
            if (highCard.isLessThanAceHigh(hand[i]) )
              highCard=hand[i];
        }
        sortAceHigh();
       score=computeScore();
    }
     public PokerHand(Card[] h)
    {
        hand = new Card[5];
        highCard=h[0];
        for (int i=0;i<5;i++)
        {
            hand[i]=h[i];
            if (highCard.isLessThanAceHigh(hand[i]) )
              highCard=hand[i];
        }
        sortAceHigh();
        score=computeScore();
    } 
    /**
     * Accessor method that returns the high card
     * (Ace is considered the highest card,
     *  suit is ignored)
     * @return the highest card of the hand
     */
    public Card getHighCard()
    {
        return highCard;
    }
     public double getScore()
    {
        return score;
    }
    public String toString()
    {
        String result="";
        for(Card c:hand)
           result+=c.toString()+"\n";
        return result;
    }
    /**
     * mutator method that will arrage the hand in
     * descending order, Ace high
     */
    public void sortAceHigh()
    {

        for (int i=0;i<4;i++)
        {
            for(int j=i;j<5;j++)
               if (hand[i].isLessThanAceHigh(hand[j]) )
               {
                   Card h=hand[j];
                   hand[j]=hand[i];
                   hand[i]=h;
               }
        }
    }
    /**
     * mutator method that will arrange the hand in
     * descending order, Ace low
     * 
     */
     public void sortAceLow()
    {

        for (int i=0;i<4;i++)
        {
            for(int j=i;j<5;j++)
               if (hand[i].isLessThan(hand[j]) )
               {
                   Card h=hand[j];
                   hand[j]=hand[i];
                   hand[i]=h;
               }
        }
    }
    public boolean hasPair()
    {
        int i=0;
        while (i<4)
        {
            if (hand[i].comparePips(hand[i+1])==0 )
               return true;
            i++;
        }
        return false;
    }
    public boolean hasTwoPair()
    {
        int i=0;
        int pairCount=0;
        while(i<4)
        {
            if(hand[i].comparePips(hand[i+1])==0){
               pairCount++;
               i=i++;
            }
            i++;
        }
        if (pairCount>1)
           return true;
        return false;
    }
    public boolean hasThreeOfAKind()
    {
        int i=0;
        while (i<3)
        {
            if(hand[i].comparePips(hand[i+1])+hand[i+1].comparePips(hand[i+2])==0)
               return true;
            i++;
        }
        return false;
    }
    public boolean hasFourOfAKind()
    {
        int left = hand[0].comparePips(hand[1])+
                   hand[1].comparePips(hand[2])+
                   hand[2].comparePips(hand[3]);
        int right= hand[1].comparePips(hand[2])+
                   hand[2].comparePips(hand[3])+
                   hand[3].comparePips(hand[4]);
        if (left==0 || right==0)
            return true;
        return false;
    }
    public boolean hasFlush()
    {
        int i=0;
        while(i<4)
        {
            if(hand[i].getSuit()!=hand[i+1].getSuit() )
                return false;
            i++;
        }
        return true;
    }
    public boolean hasStraight()
    {
        boolean inOrder=true;
        sortAceLow();
        for(int i=0;i<4;i++)
            if(hand[i].comparePips(hand[i+1])!=1)
                inOrder=false;
        if (inOrder) return true;
        sortAceHigh();
        inOrder=true;
        for(int i=0;i<4;i++)
            if(hand[i].comparePipsAceHigh(hand[i+1])!=1)
                inOrder=false;
        return inOrder;
    }
    public boolean hasStraightFlush()
    {
        if (hasFlush()&&hasStraight())
         return true;
        return false;
    }
    public boolean hasRoyalFlush()
    {
        if (hasStraightFlush()&& hand[0].getPipsAceHigh()==14)
         return true;
        return false;
    }
    public boolean hasFullHouse()
    {
        if(hasThreeOfAKind() ){
           if (hand[2].equals(hand[4]) && hand[0].equals(hand[1]) ) 
               return true;
           if (hand[2].equals(hand[0]) && hand[3].equals(hand[4]) ) 
               return true;
        }
        return false;
    }
    public int highCardBonus(ArrayList<Card> c)
    {
        int s=0;
        int n=c.size();
        for (int j=0;j<n;j++)
          s=100*s+c.get(j).getPipsAceHigh();
        return s;
    }
    /**
     * sets score to determine the strength of the hand
     * precondition: hand is sorted in descending order
     */
    public double computeScore()
    {
        double score=0; 


        if (hasPair()){
            int pairValue=0;
            ArrayList<Card> c=new ArrayList<Card>();
            for (int j=0;j<5;j++)
                c.add(hand[j]);
            for (int j=0;j<4;j++)
                if (hand[j].equals(hand[j+1])){
                   c.remove(hand[j]);
                   c.remove(hand[j+1]);
                   pairValue=hand[j].getPipsAceHigh();
                }            
            score=1+pairValue/100.0+highCardBonus(c)/100000000.0;
        }
        if (hasTwoPair()){
            int pair1=0;
            int pair2=0;
            ArrayList<Card> c=new ArrayList<Card>();
            for (int j=0;j<5;j++)
                c.add(hand[j]);
            for (int j=0;j<4;j++)
                if (hand[j].equals(hand[j+1])){
                   c.remove(hand[j]);
                   c.remove(hand[j+1]);
                   if(pair1==0)
                       pair1=hand[j].getPipsAceHigh();
                   else
                       pair2=hand[j].getPipsAceHigh();
                }
            score=2+pair1/100.0+pair2/10000.0+highCardBonus(c)/1000000.0;
        }
        if (hasThreeOfAKind()) {//could be in 3 different positions
            int p3=hand[2].getPipsAceHigh();
            int p1a=hand[3].getPipsAceHigh();//presume 3k high
            int p1b=hand[4].getPipsAceHigh();
            if (p3==hand[4].getPipsAceHigh()){//3 K is low rank
                p1a=hand[0].getPipsAceHigh();
                p1b=hand[1].getPipsAceHigh();
            } else
            if (hand[1].getPipsAceHigh()==hand[3].getPipsAceHigh()){// 3K in middle
                p1a=hand[0].getPipsAceHigh();
                p1b=hand[4].getPipsAceHigh();
            }
            score=3+p3/100.00+p1a/10000.0+p1b/1000000.0;
        }
        if (hasStraight()) score=4+highCard.getPipsAceHigh()/100.0;
        if (hasFlush()) {
            int bonus=0;
            for(int j=0;j<5;j++)
               bonus=100*bonus+hand[j].getPipsAceHigh();
            score=5+bonus/10000000000.0;
        }
        if (hasFullHouse()){
            int p3=hand[2].getPipsAceHigh();
            int p2=hand[4].getPipsAceHigh();
            if (p3==p2) p2=hand[0].getPipsAceHigh();
            score=6+p3/100.0+p2/10000.0;
        }
        if (hasFourOfAKind()){
            int p4=hand[2].getPipsAceHigh();
            int p1=hand[4].getPipsAceHigh();
            if (p4==p1) p1=hand[0].getPipsAceHigh();
            score=7+p4/100.0+p1/10000.0;
        }
        if (hasStraightFlush()){
            score=8+highCard.getPipsAceHigh()/100.0;
        }
        if (hasRoyalFlush()) score=9;
        if (score<1.0){
            int bonus=0;
            for(int j=0;j<5;j++)
               bonus=100*bonus+hand[j].getPipsAceHigh();
            score=bonus/10000000000.0;
        }
        return score;
    }
    /**
     * compares One Poker hand to another,
     * taking into account total pips.
     * If positive, this hand is greater
     * than the other.
     */
    public double compareTo(PokerHand other)
    {
        return score - other.getScore();
    }
    public String display(){
        String result="";
        for (int i=0;i<5;i++)
           result+=hand[i].info()+" ";
        return result;
    }
    public String getInfo()
    {
        int rank=(int)score;
        return r[rank];
    }
}

VideoPoker.java


package poker;

import java.applet.Applet;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
/**
 * Video Poker is an applet
 * that requires the Card, Deck and PokerHand classes.
 * 
 * @author Chris Thiel, OFMCap 
 * @version 16 May 2012
 */
public class VideoPoker extends Applet implements MouseListener
{
	private PokerHand hand;
	private Deck deck;
	private Card[] cards;
	private Rectangle[] cardLoc;
	private Rectangle dealBox;
	public static final int WIDTH=800, HEIGHT=600;
	String message;
	private Image imgBuffer;
    private Graphics gBuffer;
    public void init()
	{
		imgBuffer = createImage(WIDTH,HEIGHT);
        gBuffer = imgBuffer.getGraphics();
        message="Video Poker";
        deck=new Deck();
        cards=new Card[5];
        cardLoc=new Rectangle[5];
        for (int i=0;i<5;i++){
        		cards[i]=deck.deal();
        		cards[i].turnUp();
        		cardLoc[i]=new Rectangle(20+i*70,80,60,80);
        }
		hand=new PokerHand(cards);
		dealBox=new Rectangle(120,175, 120,30);
		this.addMouseListener(this);
		repaint();
	}
    public void paint(Graphics g)
	{
		gBuffer.setColor(Color.WHITE);
		gBuffer.fillRect(0, 0, WIDTH, HEIGHT);
		gBuffer.setColor(Color.BLACK);
		gBuffer.setFont(new Font("Helvetica", Font.BOLD,  12));
		gBuffer.drawString(message, 20, 20);
		gBuffer.drawString(hand.display(), 20, 40);
		gBuffer.drawString(hand.getInfo(), 20, 60);
		for (int i=0;i<5;i++)
			cards[i].draw((Graphics2D)gBuffer, cardLoc[i]);
		gBuffer.setColor(Color.RED);
		gBuffer.fillRect(dealBox.x, dealBox.y, dealBox.width, dealBox.height);
		gBuffer.setColor(Color.BLUE);
		gBuffer.drawString("Deal", dealBox.x+20, dealBox.y+20);
		g.drawImage(imgBuffer,0,0,this);
	}
	public void update(Graphics g)
    {
        paint(g); 
    }
	@Override
	public void mouseClicked(MouseEvent e) {}

	@Override
	public void mouseEntered(MouseEvent e) {}

	@Override
	public void mouseExited(MouseEvent e) {}

	@Override
	public void mousePressed(MouseEvent e) {}

	@Override
	public void mouseReleased(MouseEvent e) {
		int x=e.getX();
		int y=e.getY();

		for (int i=0; i<5;i++){
			if (cardLoc[i].contains(x, y) ){
				cards[i].turnOver();

			}
		}
		if (dealBox.contains(x,y)){
			// user wants new cards...
		}
		repaint();
	}

}