/**********************************************************\ * hand.java * * by Daniel Wedul * * last modified 5/26/02 * >**********************************************************< * This class defines a full hand in Texas Hold'em * * There are seven cards in each hand * * only five are 'played' * * this class uses a 14x4 array to test hands, * * the 14 comes from the 13 cards plus one, since the ace * * can be either high or low. * >**********************************************************< * Private in this class is the hand value testers * * i.e. isroyalflush etc. * * note that they are listed in order, best hand first * >**********************************************************< * the joker is good for aces straits and flushes * * technically speaking this means that it adds one to the * * number of aces, and it makes it so that only four cards * * are needed for straits or flushes. * \**********************************************************/ class hand { private card[] all = new card[7]; private int rank = 0; private String handname = ""; private int joker = 0; //variables to be set during construction so testing // only needs to be done once a hand private boolean royalflush = false; private int straitflush = -1; private int fourofakind = -1; private int[] fullhouse = {-1,-1}; private int flush = -1; private int strait = -1; private int threeofakind = -1; private int[] twopair = {-1,-1}; private int pair = -1; private int[][] handarray = { {0,0,0,0}, {0,0,0,0}, {0,0,0,0}, {0,0,0,0}, {0,0,0,0}, {0,0,0,0}, {0,0,0,0}, {0,0,0,0}, {0,0,0,0}, {0,0,0,0}, {0,0,0,0}, {0,0,0,0}, {0,0,0,0}, {0,0,0,0} }; // all[] in this class is an image of the cards // rank is an integer value that is associated with the hand // handarray[] is the 14x4 array mentioned in the beginning comments // constructor, a hand must have 7 cards // with all seven cards public hand(card a, card b, card c, card d, card e, card f, card g) { all[0] = a; all[1] = b; all[2] = c; all[3] = d; all[4] = e; all[5] = f; all[6] = g; prepare(); } // end constructor //constructor with two cards (the pocket) // and an array of five(the board) public hand(card a, card b, card [] c) { for(int i=0;i<5;i++) all[i] = c[i]; all[5] = a; all[6] = b; prepare(); } // end constructor //constructor, with an array of seven cards public hand(card [] a) { for (int i=0;i<7;i++) all[i] = a[i]; prepare(); } // end constructor // a void called by the constuctor to prepare the arrays for use private void prepare() { // sort all[] sort(); // prepare handarray for(int i=0;i<7;i++) { if ((all[i].getvalue() == 15) || (all[i].getsuit() == 5)) joker = 1; else handarray[all[i].getvalue()-1][all[i].getsuit()-1] = 1; } // the aces go in two columns for(int j=0;j<4;j++) handarray[13][j] = handarray[0][j]; //do all of the testing (and sorting) pair = ispair(); twopair = istwopair(); threeofakind = isthreeofakind(); strait = isstrait(); flush = isflush(); fullhouse = isfullhouse(); fourofakind = isfourofakind(); straitflush = isstraitflush(); royalflush = isroyalflush(); //calculate rank rank = calculaterank(); } // end void prepare // a void to get the hands rank public int getrank() { return rank; } // end getrank // A method to rank the hand // I will use a boolean variable 'done' to keep from having // a huge if/elseif/elseif/... statement /*****************************************\ * a hands rank is as follows * * royal flush: 1 - ~ * * Strait Flush: 2 - 10 * * Four of a Kind: 11 - 249 * * Full House: 250 - 499 * * Flush: 500 - 299,999 * * Strait: 300,000 - 300,019 * * Three of a kind: 300,020 - 302,499 * * Two pair: 302,500 - 304,999 * * pair: 305,000 - 349,999 * * other: 350,000 - ~ * * a hands rank also includes its kickers * >*****************************************< * formula for calculating hands: * * find number of values needed to * * distinguish one hand from another * * (include all kickers) * * look up formula below. * * 1: _ m:14 * * 2: _+13*_ m:196 * * 3: _+12*(_+13*_) m:2366 * * 4: _+11*(_+12*(_+13*_)) m:26040 * * 5: _+10*(_+11*(_+12*(_+13*_))) m:260414 * * note: the m value is calculated by * * putting 14 in each blank, it is the * * maximum that each formula can have * * insert important values in spaces with * * the least important number in the * * first space followed by the second * * etc. Call this number n. * * finally use the first table and find * * the beginning for the hand * * for example, if it's two pair, the * * beginning is 302,500. * * finally, * * retval = beginning + m - n * \*****************************************/ private int calculaterank() { int retval = 0; int a = 0; int [] b = {-1,-1}; boolean done = false; //start with checking for a royal flush if (royalflush) // 1 { retval = 1; handname = " Royal Flush"; done = true; } a = straitflush; if (!done && (a != -1)) // 2 - 10 { retval = 2 + 13 - a; handname = " Strait Flush"; done = true; } //four of a kind a = fourofakind; if (!done && (a != -1)) // 11 - 249 { //find the highest of the remaining 3 cards int hi = 0; for(int i=0;i<7;i++) { int t = all[i].getvalue(); if (t==1 || t==15) t = 14; if ((t != a) && (t > hi)) hi = t; } a = hi + 13 * a; retval = 11 + 196 - a; handname = " Four of a kind"; done = true; } //a full house b = fullhouse; if (!done && (b[0] != -1) && (b[1] != -1)) // 250 - 499 { a = 13*b[0] + b[1]; retval = 250 + 196 - a; handname = " Full House"; done = true; } //a flush a = flush; if (!done && (a != -1)) //500 - 299,999 { a = all[4].getvalue() + 10 * (all[3].getvalue() + 11 * (all[2].getvalue() + 12 * (all[1].getvalue() + 13 * a ))); retval = 500 + 260414 - a; handname = " Flush"; done = true; } //a strait a = strait; if (!done && (a != -1)) //300,000 - 300,019 { retval = 300000 + 14 - a; handname = " Strait"; done = true; } //three of a kind a = threeofakind; if (!done && (a != -1)) // 300,020 - 302,499 { //find the other two cards that play int index = 0; int hi = all[0].getvalue(); int lo = all[1].getvalue(); for(int i=6;i>=0;i--) if (all[i].getvalue() == a) index = i; if (index == 0) { hi = all[3].getvalue(); lo = all[4].getvalue(); } if (index == 1) { lo = all[4].getvalue(); } if (hi == 1) hi = 14; a = lo + 12 * (hi + 13 * a); retval = 300020 + 2366 - a; handname = "Three of a kind"; done = true; } //two pair b = twopair; if (!done && (b[0] != -1) && (b[1] != -1)) // 302,500 - 304,999 { //find the kicker int kicker = 0; for(int i=0;i<7;i++) { int t = all[i].getvalue(); if (t == 1) t=14; if ( (t != b[0]) && (t != b[1]) ) { kicker = t; i = 7; } } a = kicker + 12 * (b[1] + 13 * b[0]); retval = 302500 + 2366 - a; handname = " Two pair"; done = true; } //a pair a = pair; if (!done && (a != -1)) // 305,000 - 349,999 { //find the three kickers int [] k = { all[0].getvalue() , all[1].getvalue() , all[2].getvalue() }; int index = 0; for(int i=6;i>=0;i--) if (all[i].getvalue() == a) index = i; if (index == 0) { k[0] = all[2].getvalue(); k[1] = all[3].getvalue(); k[2] = all[4].getvalue(); } if (index == 1) { k[1] = all[3].getvalue(); k[2] = all[4].getvalue(); } if (index == 2) { k[2] = all[4].getvalue(); } if (k[0] == 1) k[0] = 14; a = k[2] + 11 * (k[1] + 12 * (k[0] + 13*a)); retval = 305000 + 26040 - a; handname = " Pair"; done = true; } //highcard if (!done) //350,000 - ~ { a = all[0].getvalue(); if (a==1) a = 14; a = all[4].getvalue() + 10 * (all[3].getvalue() + 11 * (all[2].getvalue() + 12 * (all[1].getvalue() + 13 * a ))); retval = 350000 + 260414 - a; handname = " High Card"; } return retval; } // end calculaterank // a method to get the string name public String gethandname() { return handname; } // a method to print the hand array // this is mainly for debugging public void printhandarray() { for(int i=0;i<14;i++) { for(int j=0;j<4;j++) { System.out.print (" " + handarray[i][j]); } System.out.println(" "); } } // a method to sort the seven cards from highest to lowest private void sort() { for(int i=0;i<6;i++) { for (int j=i;j<7;j++) { if (all[j].isgt(all[i])) { card temp = all[i]; all[i] = all[j]; all[j] = temp; } } } } // end sort // a method to print the cards in the hand public void printhand() { for(int i = 0;i<7;i++) { all[i].printcard(); System.out.print (" "); } } // end printhand // a method to print the cards in the hand with carriage return public void printhandln() { printhand(); System.out.println(""); } // end printhand /**************************\ * BEGIN TEST METHODS * \**************************/ // royal flush, A, K, Q, J, T, of same suit // a royal flush is the same no matter what suit // for that reason it we only need a boolean to return it private boolean isroyalflush() { return (straitflush == 14); } // end boolean isroyalflush // strait flush five cards in a row of the same suit // i.e. 4H, 5H, 6H, 7H, 8H // this will return the value of the highest card in the strait private int isstraitflush() { int retval = -1; if (flush <= -1) return retval; int straitstart = strait - 1; if (straitstart <= -1) return retval; for (int j=0;j<4;j++) { for (int i=13;i>=4;i--) { int counter = 0; int tempjoker = joker; for (int k=0;k<5;k++) { if ((handarray[i-k][j] == 1) || (tempjoker == 1)) { if (handarray[i-k][j] != 1) tempjoker = 0; counter++; } else { counter = 0; k = 6; } } if (counter == 5) { retval = i; i = -1; j = 5; } } //end i loop } //end j loop if (retval != -1) retval++; return retval; } // end int isstraitflush // four of a kind, four cards with the same value // returns value of card in four of a kind private int isfourofakind() { int retval = -1; for(int i=13;i>=0;i--) { int counter = 0; for(int j=0;j<4;j++) counter = counter + handarray[i][j]; if (counter == 4) { retval = i; i = 0; } } if (retval != -1) retval++; return retval; } // end int isfourofakind // full house, three cards of one value and two of another // returns an array of size 2 // retval[0] = value of three of a kind // retval[1] = value of pair private int[] isfullhouse() { int[] retval = {-1,-1}; //find the three of a kind if there is one retval[0] = threeofakind; if (retval[0] == -1) return retval; //find the pair if there's a three of a kind //a full house is also two pair // the pair needed must be one of those pairs //return if there was no two pair if (twopair[0] == -1) { retval[0] = -1; return retval; } //find out which pair to use if (twopair[1] != retval[0]) retval[1] = twopair[1]; else if (twopair[0] != retval[0]) retval[1] = twopair[0]; else retval[0] = -1; return retval; } // end int isfullhouse // flush, five cards of the same suit // returns highest card of the flush in first element // This method also puts the top five cards of the flush // in the first 5 elements of all[] (for ranking) private int isflush() { int suit = -1; for(int j=0;j<4;j++) { int counter = 0; for(int i=1;i<14;i++) counter = counter + handarray[i][j]; if (counter >= 5-joker) { suit = j; j=4; } } if (suit == -1) return -1; // we have a flush, find the five highest cards of it suit++; //because card's suits go 1-4 not 0-3 //create a new card that has the same suit as the flush card tempsuited = new card(2,suit); for(int i=0; i<5;i++) { //find highest card of flush suit int highindex = i; while(!all[highindex].issuitedwith(tempsuited) && (highindex < 7)) highindex++; for (int j=i+1;j<7;j++) { if (all[j].issuitedwith(tempsuited)) { if ( all[j].isgt(all[highindex]) ) { highindex = j; } } } //swap it to current position of needed if (highindex != i) { card temp = all[i]; all[i] = all[highindex]; all[highindex] = temp; } } int retval = all[0].getvalue(); //take care of the ace and joker; if ((retval == 1) || (retval == 15)) retval = 14; return retval; } // end int isflush // strait, five cards in a row // i.e. 9, T, J, Q, K // returns highest card of the strait private int isstrait() { int retval = -1; for(int i=13;i>=4;i--) { int counter = 0; boolean tempjoker = (joker == 1); for (int j=0;j<5;j++) { boolean cardfound = false; for(int k=0;k<4;k++) if (handarray[i-j][k]==1) cardfound = true; if (!cardfound && tempjoker) { cardfound = true; tempjoker = false; } if (cardfound) counter++; } if (counter == 5) { retval = i; i = 0; } } if (retval != -1) retval++; return retval; } // end int isstrait // three of a kind, three cards of the same value // returns value of the three of a kind private int isthreeofakind() { int retval = -1; int counter = joker; for(int i=13;i>0;i--) { for(int j=0;j<4;j++) counter = counter + handarray[i][j]; if (counter >= 3) { retval = i; i = 0; } counter = 0; } if (retval != -1) retval++; return retval; } // end int isthreeofakind // two pairs, 2 cards of one value and 2 cards of another value // returns an array of size 2 that is the value of each pair private int[] istwopair() { int [] retval = {-1,-1}; int pairsfound = 0; int counter = joker; for(int i=13;i>0;i--) { for(int j=0;j<4;j++) counter = counter + handarray[i][j]; if (counter >= 2) { retval[pairsfound] = i; pairsfound++; if (pairsfound == 2) i = 0; else if (counter == 4) { retval[pairsfound] = i; pairsfound = 2; i = 0; } } counter = 0; } // take care of when only one pair is found if (retval[1] == -1) retval[0] = -1; if (retval[0] != -1) retval[0]++; if (retval[1] != -1) retval[1]++; return retval; } // end int[] istwopair // two cards of the same value // returns value of pair private int ispair() { int retval = -1; int counter = joker; for(int i=13;i>0;i--) { for(int j=0;j<4;j++) counter = counter + handarray[i][j]; if (counter >= 2) { retval = i; i = 0; } counter = 0; } if (retval != -1) retval++; return retval; } // end int ispair /**************************\ * END TEST METHODS * \**************************/ // a method that runs all test methods on a hand and // displayes each's results public void showhandstrength() { System.out.print ("\n "); printhand(); System.out.println("\n"); System.out.println(" Royal Flush: " + royalflush ); System.out.println(" Strait Flush: " + straitflush ); System.out.println(" Four of a kind: " + fourofakind ); System.out.println(" Full house: " + fullhouse[0] + ", " + fullhouse[1] ); System.out.println(" Flush: " + flush ); System.out.println(" Strait: " + strait ); System.out.println("Three of a kind: " + threeofakind ); System.out.println(" Two pair: " + twopair[0] + ", " + twopair[1] ); System.out.println(" Pair: " + pair ); System.out.println(" "); System.out.println(" Rank: " + rank ); System.out.println(" "); } // end showhandstrength } // end class hand // end hand.java