Java

The Java code below calculates the probability a specific pre-flop hand will win given a number of players in Texas Hold’em.

To make the code below into an executable jar in a linux environment do the following steps:
1. Create a directory for this project in a place you choose with a name you choose.
2. In that directory create a directory org.
3. Create a directory org/dealhands.
4. In org/dealhands create the 2 source files below.
5. Create a manifest - echo Main-Class: org.dealhands.Hand>manifest.txt
6. Compile the source - javac org/dealhands/*.java
7. Make the jar file - jar cvfm Deal.jar manifest.txt org/dealhands/*.class
8. To execute it - java -jar Deal.jar

Deck.java
package org.dealhands;

import java.util.Random;

public class Deck {
	int[] cards;
		
	public Deck(){
		boolean noMatch;
		int cardIndex;
		int dealtCardIndex;
		int randHold;
		cards = new int[52];
		Random randGen = new Random();
		cards[0] = randGen.nextInt(52);
		for(cardIndex=1;cardIndex<52;++cardIndex){
			while(true){
				noMatch=true;
				randHold=randGen.nextInt(52);
				for(dealtCardIndex=0;dealtCardIndex<cardIndex;++dealtCardIndex){
					if(cards[dealtCardIndex]==randHold){
						noMatch=false;
						break;
					}
				}
				if(noMatch){
					cards[cardIndex]=randHold;
					break;
				}
			}
		}
	}

	public int[] getDeck() {
		return cards;
	}
}

Hand.java
package org.dealhands;

public class Hand {
	public static final int ACE          =          12;
	public static final int DEUCE        =           0;
	public static final int THREE        =           1;
	public static final int FOUR         =           2;
	public static final int FIVE         =           3;
	public static final int SIX          =           4;
	public static final int SEVEN        =           5;
	public static final int EIGHT        =           6;
	public static final int NINE         =           7;
	public static final int TEN          =           8;
	public static final int JACK         =           9;
	public static final int QUEEN        =          10;
	public static final int KING         =          11;
	public static final long HANDTYPE    = 10000000000L;
	public static final int FIRSTKICKER  =   100000000;
	public static final int SECONDKICKER =     1000000;
	public static final int THIRDKICKER  =       10000;
	public static final int FOURTHKICKER =         100;
	public static final int FIFTHKICKER  =           1;
	public static final int SFLUSH       =           9;
	public static final int QUADS        =           8;
	public static final int BOAT         =           7;
	public static final int FLUSH        =           6;
	public static final int STRAIGHT     =           5;
	public static final int TRIPS        =           4;
	public static final int TWOPAIR      =           3;
	public static final int ONEPAIR      =           2;
	public static final int HIGHCARD     =           1;
	public static final int UNKNOWN      =           0;
	public static final String[] cards  = {"2c", "2d", "2h", "2s",
		      "3c", "3d", "3h", "3s",
		      "4c", "4d", "4h", "4s",
		      "5c", "5d", "5h", "5s",
		      "6c", "6d", "6h", "6s",
		      "7c", "7d", "7h", "7s",
		      "8c", "8d", "8h", "8s",
		      "9c", "9d", "9h", "9s",
		      "Tc", "Td", "Th", "Ts",
		      "Jc", "Jd", "Jh", "Js",
		      "Qc", "Qd", "Qh", "Qs",
		      "Kc", "Kd", "Kh", "Ks",
		      "Ac", "Ad", "Ah", "As"};
	public static final String[] cardRank={"2", "3", "4", "5", "6", "7", "8", "9", "T", "J", "Q", "K", "A"};
	private int sortedCards[]=new int[7];
	private int cardIndex;
	private long handValue[];
	private int suits[];
	private int i;
	private int handCards[][];
	private int highCard;
	private int cardCount[];
	private int kicker1;
	private int kicker2;
	private int kicker3;
	private int handsPerGame;
	private int flop[]=new int [5];
	private boolean handIsSuited[];
	private int handKey[];
	private int orderedHand[][];
	private long winningHand;
	
	public Hand(int handsPerGame){
		if(handsPerGame < 2 || handsPerGame > 10){
			throw new IllegalArgumentException("Error: Valid number of players is between 2 and 10.\n");
		}
		this.handsPerGame=handsPerGame;
		handCards=new int[handsPerGame][7];
		handValue=new long[handsPerGame];
		handIsSuited=new boolean[handsPerGame];
		orderedHand=new int[handsPerGame][2];
		handKey=new int[handsPerGame];
		int cardNo = 0;
		int playerIndex;
		int shuffDeck[];
		int card1;
		int card2;
		int hold;
		Deck d = new Deck();
		shuffDeck=d.getDeck();
		for(cardIndex=0;cardIndex<2;++cardIndex){
            for(playerIndex=0;playerIndex<handsPerGame;++playerIndex){
                handCards[playerIndex][cardIndex]=shuffDeck[cardNo++];
            }
        }
		cardNo++; //burn - the burns probably don't affect the outcome but it follows the way the game is played
        flop[0]=shuffDeck[cardNo++];
        flop[1]=shuffDeck[cardNo++];
        flop[2]=shuffDeck[cardNo++];
        cardNo++; //burn
        flop[3]=shuffDeck[cardNo++];
        cardNo++; //burn
        flop[4]=shuffDeck[cardNo++];
        for(playerIndex=0;playerIndex<handsPerGame;++playerIndex){
            for(cardIndex=2;cardIndex<7;++cardIndex){
                    // Add the board cards to each players hand to be used in valuing the hand
                    handCards[playerIndex][cardIndex]=flop[cardIndex-2];
            }
        }
        setWinningHand(0);
        for(playerIndex=0;playerIndex<handsPerGame;++playerIndex){
        	card1=handCards[playerIndex][0];
        	card2=handCards[playerIndex][1];
            orderedHand[playerIndex][0]=card1;
            orderedHand[playerIndex][1]=card2;
        	handIsSuited[playerIndex]=false;
        	if((card1 % 4) == (card2 % 4)){
                handIsSuited[playerIndex]=true;
            }
        	card1=card1/4;
            card2=card2/4;
            //  Once we've removed suit from the card value we want the relativly
            //  higher ranked card to always be the first card (does not matter
            //  for pairs
            if(card1<card2){
                    hold=card1;
                    card1=card2;
                    card2=hold;
            }
            handKey[playerIndex]=(card1*100)+card2;
        	computeHandvalue(playerIndex);
        	if(handValue[playerIndex]>getWinningHand()){
        		setWinningHand(handValue[playerIndex]);
        	}
        }
	}

	private void computeHandvalue(int playerIndex) {
		handValue[playerIndex]=UNKNOWN;
        // Makes sense to check for a flush first, if a flush exists within the seven cards
        // the only higher possible hand is a straight flush which is easy to check for
        // using the same code that will check for a straight
        isThereAFlush(playerIndex);
        if(handValue[playerIndex]==UNKNOWN){
                if(!isThereQuads(playerIndex)){
                        if(!isThereABoat(playerIndex)){
                                if(!isThereAStraight(playerIndex)){
                                        if(!isThereTrips(playerIndex)){
                                                if(!isThereTwoPairs(playerIndex)){
                                                        if(!isThereOnePair(playerIndex)){
                                                                for(cardIndex=0;cardIndex<7;cardIndex++){
                                                                        sortedCards[cardIndex]=handCards[playerIndex][cardIndex]/4;
                                                                }
                                                                sortCards();
                                                                handValue[playerIndex]=(HANDTYPE*HIGHCARD)+(FIRSTKICKER*sortedCards[0])
                                                                                                          +(SECONDKICKER*sortedCards[1])
                                                                                                          +(THIRDKICKER*sortedCards[2])
                                                                                                          +(FOURTHKICKER*sortedCards[3])
                                                                                                          +(FIFTHKICKER*sortedCards[4]);
                                                                //print "Player playerIndex has high card handValue[playerIndex]<br>\n";
                                                        }
                                                }
                                        }
                                }
                        }
                }
        }

	}

	private void sortCards() {
		// simple bubble sort
		int i2;
		int i3;
		int holdCard;
        for(i = 0;i<6;i++){
            for(i2 = 0;i2<6;i2++){
                    i3 = i2+1;
                    if(sortedCards[i2]<sortedCards[i3]){
                            holdCard = sortedCards[i2];
                            sortedCards[i2]=sortedCards[i3];
                            sortedCards[i3]=holdCard;
                    }
            }
        }
	}

	private boolean isThereOnePair(int playerIndex) {
		loadCardCount(playerIndex);
        int pair=-1;
        kicker1=-1;
        kicker2=-1;
        kicker3=-1;
        for(i=12;i>-1;i--){
                if(cardCount[i]==2){
                        pair=i;
                        break;
                }
        }
        if(pair>-1){
                for(i=12;i>-1;i--){
                        if(i!=pair){
                                if(cardCount[i]>0){
                                        if(kicker1==-1){
                                                kicker1=i;
                                        }
                                        else{
                                                if(kicker2==-1){
                                                        kicker2=i;
                                                }
                                                else{
                                                        kicker3=i;
                                                        handValue[playerIndex]=(HANDTYPE*ONEPAIR)+(FIRSTKICKER*pair)+(SECONDKICKER*kicker1)+
                                                                                 (THIRDKICKER*kicker2)+(FOURTHKICKER*kicker3);
                                                        //print "Player playerIndex has 1 pair handValue[playerIndex]<br>\n";
                                                        return true;
                                                }
                                        }
                                }
                        }
                }
        }
        return false;

	}

	private boolean isThereTwoPairs(int playerIndex) {
		loadCardCount(playerIndex);
        int highPair=-1;
        int lowPair=-1;
        kicker1=-1;
        for(i=12;i>-1;i--){
                if(cardCount[i]==2){
                        highPair=i;
                        break;
                }
        }
        if(highPair>-1){
                for(i=12;i>-1;i--){
                        if(i != highPair){
                                if(cardCount[i]==2){
                                        lowPair=i;
                                        break;
                                }
                        }
                }
        }
        if(highPair>-1 && lowPair>-1){
                for(i=12;i>-1;i--){
                        if(i != highPair && i != lowPair){
                                if(cardCount[i]>0){
                                        kicker1=i;
                                        handValue[playerIndex]=(HANDTYPE*TWOPAIR)+(FIRSTKICKER*highPair)+(SECONDKICKER*lowPair)+(THIRDKICKER*kicker1);
                                        // print "Player playerIndex has 2 pair handValue[playerIndex]<br>\n";
                                        return true;
                                }
                        }
                }
        }
        return false;
	}

	private boolean isThereTrips(int playerIndex) {
		loadCardCount(playerIndex);
        int highTrips=-1;
        kicker1=-1;
        kicker2=-1;
        for(i=12;i>-1;i--){
                if(cardCount[i]==3){
                        highTrips=i;
                        break;
                }
        }
        if(highTrips>-1){
                for(i=12;i>-1;i--){
                        if(i!=highTrips){
                                if(cardCount[i]>0){
                                        if(kicker1==-1){
                                                kicker1=i;
                                        }
                                        else{
                                                kicker2=i;
                                                handValue[playerIndex]=(HANDTYPE*TRIPS)+(FIRSTKICKER*highTrips)+
                                                                         (SECONDKICKER*kicker1)+(THIRDKICKER*kicker2);
                                                //print "Player playerIndex has trips handValue[playerIndex]<br>\n";
                                                return true;
                                        }
                                }
                        }
                }
        }
        return false;

	}

	private boolean isThereAStraight(int playerIndex) {
		loadCardCount(playerIndex);
        highCard=0;
        if(cardCount[FIVE] > 0 && cardCount[FOUR] > 0 && cardCount[THREE] > 0 && cardCount[DEUCE] > 0 && cardCount[ACE] > 0){
                highCard=FIVE;
        }
        if(cardCount[SIX] > 0 && cardCount[FIVE] > 0 && cardCount[FOUR] > 0 && cardCount[THREE] > 0 && cardCount[DEUCE] > 0){
                highCard=SIX;
        }
        if(cardCount[SEVEN] > 0 && cardCount[SIX] > 0 && cardCount[FIVE] > 0 && cardCount[FOUR] > 0 && cardCount[THREE] > 0){
                highCard=SEVEN;
        }
        if(cardCount[EIGHT] > 0 && cardCount[SEVEN] > 0 && cardCount[SIX] > 0 && cardCount[FIVE] > 0 && cardCount[FOUR] > 0){
        		highCard=EIGHT;
        }
        if(cardCount[NINE] > 0 && cardCount[EIGHT] > 0 && cardCount[SEVEN] > 0 && cardCount[SIX] > 0 && cardCount[FIVE] > 0){
                highCard=NINE;
        }
        if(cardCount[TEN] > 0 && cardCount[NINE] > 0 && cardCount[EIGHT] > 0 && cardCount[SEVEN] > 0 && cardCount[SIX] > 0){
                highCard=TEN;
        }
        if(cardCount[JACK] > 0 && cardCount[TEN] > 0 && cardCount[NINE] > 0 && cardCount[EIGHT] > 0 && cardCount[SEVEN] > 0){
                highCard=JACK;
        }
        if(cardCount[QUEEN] > 0 && cardCount[JACK] > 0 && cardCount[TEN] > 0 && cardCount[NINE] > 0 && cardCount[EIGHT] > 0){
                highCard=QUEEN;
        }
        if(cardCount[KING] > 0 && cardCount[QUEEN] > 0 && cardCount[JACK] > 0 && cardCount[TEN] > 0 && cardCount[NINE] > 0){
                highCard=KING;
        }
        if(cardCount[ACE] > 0 && cardCount[KING] > 0 && cardCount[QUEEN] > 0 && cardCount[JACK] > 0 && cardCount[TEN] > 0){
                highCard=ACE;
        }
        if(highCard>0){
                handValue[playerIndex]=(HANDTYPE*STRAIGHT)+(FIRSTKICKER*highCard);
                //print "Player playerIndex has a straight handValue[playerIndex]<br>\n";
                return true;
        }
        return false;

	}

	private boolean isThereABoat(int playerIndex) {
		loadCardCount(playerIndex);
        int highTrips=-1;
        int highPair=-1;
        for(i=12;i>-1;i--){
                if(cardCount[i]==3){
                        highTrips=i;
                        break;
                }
        }
        if(highTrips>-1){
                for(i=12;i>-1;i--){
                        if(i != highTrips){
                                if(cardCount[i]>1){ // Could have 2 trips in which case second trips count as a pair
                                        highPair=i;
                                        handValue[playerIndex]=(HANDTYPE*BOAT)+(FIRSTKICKER*highTrips)+(SECONDKICKER*highPair);
                                        //print "Player playerIndex has a boat handValue[playerIndex]<br>\n";
                                        return true;
                                }
                        }
                }
        }
        return false;
	}

	private boolean isThereQuads(int playerIndex) {
		loadCardCount(playerIndex);
        for(i=0;i<13;i++){
                if(cardCount[i]==4){
                        //areQuads=true;
                        // FIRSTKICKER is what you have 4 of
                        // no need for a second kicker because 2 players can't
                        // have the same quads
                        handValue[playerIndex]=(HANDTYPE*QUADS)+(FIRSTKICKER*i);
                        //print "Player $playerIndex has quads $handValue[$playerIndex]<br>\n";
                        return true;
                }
        }
        return false;
	}

	private void loadCardCount(int playerIndex) {
		cardCount=new int [13];
        for(cardIndex=0;cardIndex<7;cardIndex++){
                if(handCards[playerIndex][cardIndex]!=-1){
                        cardCount[handCards[playerIndex][cardIndex]/4]++;
                }
        }
		
	}

	private boolean isThereAFlush(int playerIndex) {
		suits=new int [4];
		int flushSuit=-1;
        for(cardIndex=0;cardIndex<7;cardIndex++){
                suits[handCards[playerIndex][cardIndex]%4]++;
        }
        for(i=0;i<4;i++){
                if(suits[i]>4){
                        flushSuit=i;
                        break;
                }
        }
        if(flushSuit!=-1){
                // OK we have a flush is it a straight Flush?
                // first lets remove the unsuited cards so we check for a straight
                        for(cardIndex=0;cardIndex<7;cardIndex++){
                                if((handCards[playerIndex][cardIndex]%4)==flushSuit){
                                        sortedCards[cardIndex]=handCards[playerIndex][cardIndex]/4;
                                }
                                else{
                                        handCards[playerIndex][cardIndex]=-1;
                                        sortedCards[cardIndex]=-1;
                                }
                        }
                        if(isThereAStraight(playerIndex)){
                                // Wow a Straight Flush!
                                handValue[playerIndex]=(HANDTYPE*SFLUSH)+(FIRSTKICKER*highCard); // $highCard comes from isThereAStraight
                                //print "Player $playerIndex has a straight flush $handValue[$playerIndex]<br>\n";
                                return true;
                        }
                        else{
                                sortCards();
                                handValue[playerIndex]=(HANDTYPE*FLUSH)+(FIRSTKICKER*sortedCards[0])+(SECONDKICKER*sortedCards[1])+
                                                         (THIRDKICKER*sortedCards[2])+(FOURTHKICKER*sortedCards[3])+(FIFTHKICKER*sortedCards[4]);
                                //print "Player $playerIndex has a flush $handValue[$playerIndex]<br>\n";
                                return true;
                        }
        }
        return false;		
	}

	public void printHands() {
		System.out.print("Flop ");
		for(cardIndex=0;cardIndex<5;cardIndex++){
			System.out.print(cards[flop[cardIndex]]);
			System.out.print(" ");
		}
		System.out.print("\n");
		for(int playerIndex = 0;playerIndex<handsPerGame;++playerIndex){
			System.out.print("Player ");
			System.out.print(playerIndex);
			System.out.print(" ");
			System.out.print(cards[orderedHand[playerIndex][0]]);
			System.out.print(" ");
			System.out.print(cards[orderedHand[playerIndex][1]]);
			System.out.print(" ");
			System.out.print(handValue[playerIndex]);
			if(getWinningHand()==handValue[playerIndex]){
				System.out.print(" <--");
			}
			System.out.print("\n");
        }

	}

	public long getWinningHand() {
		return winningHand;
	}

	public void setWinningHand(long winningHand) {
		this.winningHand = winningHand;
	}

	public int getHandKey(int hand) {
		return handKey[hand];
	}

	public boolean getHandIsSuited(int hand) {
		return handIsSuited[hand];
	}
	private long getHandValue(int playerIndex) {
		return handValue[playerIndex];
	}
	public static void main(String[] args) {
		int suitedHandsDealt[]=new int[1213];
		int suitedHandsWon[]=new int[1213];
		int unsuitedHandsDealt[]=new int[1213];
		int unsuitedHandsWon[]=new int[1213];
		int handsToPlay = 0;
		int handsPerGame = 0;
		int i;
		int card1;
		int card2;
		float winPct;
		String hand;
		if(args.length!=2){
			usage();
		}
		try{
			handsToPlay=Integer.parseInt(args[0]);
		}
		catch(NumberFormatException e){
			usage();
		}
		try{
			handsPerGame=Integer.parseInt(args[1]);
		}
		catch(NumberFormatException e){
			usage();
		}
		if(handsPerGame < 2 || handsPerGame > 10){
			usage();
		}
		if(handsToPlay < 1){
			usage();
		}
		for(i=0;i<handsToPlay;i++){
			Hand h = new Hand(handsPerGame);
			//h.printHands();
			for(int playerIndex=0;playerIndex<handsPerGame;playerIndex++){
				if(h.getHandIsSuited(playerIndex)){
					suitedHandsDealt[h.getHandKey(playerIndex)]++;
					if(h.getWinningHand()==h.getHandValue(playerIndex)){
						suitedHandsWon[h.getHandKey(playerIndex)]++;
					}
				}
				else{
					unsuitedHandsDealt[h.getHandKey(playerIndex)]++;
					if(h.getWinningHand()==h.getHandValue(playerIndex)){
						unsuitedHandsWon[h.getHandKey(playerIndex)]++;
					}
				}
			}
		}
		System.out.print("Suited Hands\n");
		for(i=0;i<1213;i++){
			if(suitedHandsDealt[i]>0){
				card1=i/100;
				card2=i-(card1*100);
				hand=cardRank[card1]+cardRank[card2];
				System.out.print(hand);
				System.out.print(" ");
				System.out.print(suitedHandsDealt[i]);
				System.out.print(" ");
				System.out.print(suitedHandsWon[i]);
				winPct=(float)suitedHandsWon[i]/(float)suitedHandsDealt[i]*100;
				System.out.print(" ");
				System.out.format("%.2f", winPct);
				System.out.print("\n");
			}
		}
		System.out.print("Unsuited Hands\n");
		for(i=0;i<1213;i++){
			if(unsuitedHandsDealt[i]>0){
				card1=i/100;
				card2=i-(card1*100);
				hand=cardRank[card1]+cardRank[card2];
				System.out.print(hand);
				System.out.print(" ");
				System.out.print(unsuitedHandsDealt[i]);
				System.out.print(" ");
				System.out.print(unsuitedHandsWon[i]);
				winPct=(float)unsuitedHandsWon[i]/(float)unsuitedHandsDealt[i]*100;
				System.out.print(" ");
				System.out.format("%.2f", winPct);
				System.out.print("\n");
			}
		}
	}

	public static void usage(){
		System.out.print("deal requires 2 arguments - number of hands to play (>0) and number of players per hand (2 -10)\n");
		System.exit(1);
	}
}