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); } }