Browse Source

Committing finished versions of all methods, plus some major bug fixes. All five tests passing now.

master
Charles Reid 8 years ago
parent
commit
72f3432b47
  1. 471
      054/Poker.java

471
054/Poker.java

@ -4,6 +4,84 @@ import java.io.*; @@ -4,6 +4,84 @@ import java.io.*;
public class Poker {
public static void main(String[] args) throws FileNotFoundException {
test1();
test2();
test3();
test4();
test5();
}
//////////////////////////////////////
// Tests
public static void test1() {
PokerHand h1 = new PokerHand("5H 5C 6S 7S KD");
PokerHand h2 = new PokerHand("2C 3S 8S 8D TD");
PokerCompare p = new PokerCompare();
if( p.compare( h1, h2 ) > 0 ) {
System.out.println("Test 1 correct.");
} else {
System.out.println("Test 1 failed.");
}
}
public static void test2() {
PokerHand h1 = new PokerHand("5D 8C 9S JS AC");
PokerHand h2 = new PokerHand("2C 5C 7D 8S QH");
PokerCompare p = new PokerCompare();
if(p.compare(h1,h2)<0) {
System.out.println("Test 2 correct.");
} else {
System.out.println("Test 2 failed.");
}
}
public static void test3() {
PokerHand h1 = new PokerHand("2D 9C AS AH AC");
PokerHand h2 = new PokerHand("3D 6D 7D TD QD");
PokerCompare p = new PokerCompare();
if(p.compare(h1,h2)>0) {
System.out.println("Test 3 correct.");
} else {
System.out.println("Test 3 failed.");
}
}
public static void test4() {
PokerHand h1 = new PokerHand("4D 6S 9H QH QC");
PokerHand h2 = new PokerHand("3D 6D 7H QD QS");
PokerCompare p = new PokerCompare();
if(p.compare(h1,h2)<0) {
System.out.println("Test 4 correct.");
} else {
System.out.println("Test 4 failed.");
}
}
public static void test5() {
PokerHand h1 = new PokerHand("2H 2D 4C 4D 4S");
PokerHand h2 = new PokerHand("3C 3D 3S 9S 9D");
PokerCompare p = new PokerCompare();
if(p.compare(h1,h2)<0) {
System.out.println("Test 5 correct.");
} else {
System.out.println("Test 5 failed.");
}
}
//////////////////////////////////////
// Main driver/main problem
public static void doit() throws FileNotFoundException {
Scanner s = new Scanner( new BufferedReader( new FileReader("poker.txt")));
LinkedList<PokerHand> player1 = new LinkedList<PokerHand>();
@ -20,15 +98,32 @@ public class Poker { @@ -20,15 +98,32 @@ public class Poker {
player2.add(new PokerHand(hand2));
}
// Now count the number of wins for player 1
int p1w = 0;
PokerCompare p = new PokerCompare();
System.out.println(p.compare(player1.get(0),player2.get(0)));
for(int i=0; i<player1.size(); i++) {
System.out.println(player1.get(i) + "\t\t\t" + player2.get(i));
if( p.compare(player1.get(i), player2.get(i)) < 0 ) {
System.out.println("player 1 wins.");
}
System.out.println();
if( p.compare(player1.get(i), player2.get(i)) < 0 ) {
// player 1 wins, has higher ranked hand
p1w++;
}
}
System.out.println("Number of wins for player 1: " + p1w);
}
}
class PokerHand {
class PokerHand implements Comparable<PokerHand> {
public static final String[] OUTCOMES = {"high","one","two","three","straight","flush","full house","four","straight flush","royal flush"};
public static final char[] CARDS = {'2','3','4','5','6','7','8','9','D','J','Q','K','A'};
public static final char[] VALUES = {'2','3','4','5','6','7','8','9','T','J','Q','K','A'};
public static final char[] SUITS = {'S','C','D','H'};
private class Cards {
@ -37,13 +132,26 @@ class PokerHand { @@ -37,13 +132,26 @@ class PokerHand {
public Cards(char suit,char value) { this.suit=suit; this.value=value; }
public char getSuit() { return suit; }
public char getValue() { return value; }
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append(value);
sb.append(suit);
return sb.toString();
}
}
///////////////////////////////
// Implement a poker hand
List<Cards> hand;
// The list of five Cards that are dealt to a given player
LinkedList<Cards> hand;
// Final cards that matter to the outcome of the game
LinkedList<Cards> finallyhand;
// Keep track of various quantities in the hand
int nSuits;
int nValues;
int nPairs;
@ -52,6 +160,7 @@ class PokerHand { @@ -52,6 +160,7 @@ class PokerHand {
public PokerHand(String handStr) {
hand = new LinkedList<Cards>();
finallyhand = new LinkedList<Cards>();
String[] tokens = handStr.split(" ");
// assume exactly 5 tokens, otherwise you're a masochist
for(int i=0; i<tokens.length; i++) {
@ -61,24 +170,115 @@ class PokerHand { @@ -61,24 +170,115 @@ class PokerHand {
}
countSuits();
countValues();
countPairs();
countTriplets();
}
public String toString() {
StringBuffer sb = new StringBuffer();
for(Cards c : hand) {
sb.append(c.getValue());
sb.append(c.getSuit());
sb.append(" ");
}
sb.append( OUTCOMES[this.getOutcome()] );
return sb.toString();
}
/** Card comparator: compare cards by face value. */
private class ValueComparator implements Comparator<Cards> {
public int compare(Cards c1, Cards c2) {
int c1outcome = indexOf(VALUES,c1.value);
int c2outcome = indexOf(VALUES,c2.value);
// swapping the normal order so bigger cards come first
return (c2outcome-c1outcome);
}
}
/** Card comparator: compare cards by suit. */
private class SuitComparator implements Comparator<Cards> {
public int compare(Cards c1, Cards c2) {
int c1outcome = indexOf(SUITS,c1.suit);
int c2outcome = indexOf(SUITS,c1.suit);
return (c1outcome-c2outcome);
// swapping the normal order so bigger cards come first
return (c2outcome-c1outcome);
}
}
private class ValueComparator implements Comparator<Cards> {
public int compare(Cards c1, Cards c2) {
c1outcome = indexOf(VALUES,c1.value);
c2outcome = indexOf(VALUES,c1.value);
return (c1outcome-c2outcome);
/////////////////////////////////////////
// This is the heart of the problem.
/** Compare two PokerHand objects based on outcome, or if tie, on face value. */
public int compareTo(PokerHand other) {
int hand1outcome = this.getOutcome();
int hand2outcome = other.getOutcome();
if(hand1outcome==hand2outcome) {
// Resolve by high card.
// First, resolve by high card in finallyhand,
// the cards that were actually important to the
// final outcome.
// If those are tied, resolve by high card in hand.
ValueComparator comp = new ValueComparator();
Collections.sort(this.finallyhand, comp);
Collections.sort(other.finallyhand, comp);
Iterator<Cards> carditer1 = this.finallyhand.iterator();
Iterator<Cards> carditer2 = other.finallyhand.iterator();
// Break ties by highest finallyhand cards
while(carditer1.hasNext() && carditer2.hasNext()) {
Cards c1 = carditer1.next();
Cards c2 = carditer2.next();
if(c1.getValue()!=c2.getValue()) {
return comp.compare(c1,c2);
}
}
// If we get here, it's something like
// two pairs that are tied.
// Use the rest of the hand.
carditer1 = this.hand.iterator();
carditer2 = other.hand.iterator();
// Break ties by highest finallyhand cards
while(carditer1.hasNext() && carditer2.hasNext()) {
Cards c1 = carditer1.next();
Cards c2 = carditer2.next();
if(c1.getValue()!=c2.getValue()) {
return comp.compare(c1,c2);
}
}
// Well sheeeyut
return 0;
} else {
// swapping the normal order so bigger cards come first
return (hand2outcome-hand1outcome);
}
}
///////////////////////////////////////////////
// Utility counting methods
/** Count number of unique suits. */
protected void countSuits() {
this.nSuits = 0;
Set<Character> suits = new HashSet<Character>();
@ -87,6 +287,7 @@ class PokerHand { @@ -87,6 +287,7 @@ class PokerHand {
}
}
/** Count number of unique values. */
protected void countValues() {
this.nValues = 0;
Set<Character> values = new HashSet<Character>();
@ -95,6 +296,7 @@ class PokerHand { @@ -95,6 +296,7 @@ class PokerHand {
}
}
/** Count pairs. */
protected void countPairs() {
nPairs = 0;
@ -104,10 +306,13 @@ class PokerHand { @@ -104,10 +306,13 @@ class PokerHand {
// Count pairs, not triples
for(int i=0; i+1<hand.size(); i++) {
if( hand.get(i).getValue()==hand.get(i+1).getValue() ) {
Cards ci = hand.get(i);
Cards cip1 = hand.get(i+1);
if( ci.getValue() == cip1.getValue() ) {
nPairs++;
try {
if(hand.get(i).getValue()==hand.get(i+2).getValue()) {
try {
Cards cip2 = hand.get(i+2);
if( ci.getValue() == cip2.getValue() ) {
nPairs--;
}
} catch(IndexOutOfBoundsException e){
@ -119,7 +324,7 @@ class PokerHand { @@ -119,7 +324,7 @@ class PokerHand {
}
}
/** Count three of a kind occurrences. */
protected void countTriplets() {
nThrees = 0;
@ -146,6 +351,14 @@ class PokerHand { @@ -146,6 +351,14 @@ class PokerHand {
}
}
/////////////////////////////////////////////////
// Here is the meat of the class.
/** Check for royal flush. */
public boolean hasRoyalFlush() {
// Sort by face value
ValueComparator comp = new ValueComparator();
@ -163,25 +376,215 @@ class PokerHand { @@ -163,25 +376,215 @@ class PokerHand {
if(c.getValue()=='J') nj++;
if(c.getValue()=='D') nd++;
}
if( na!=1 || nk!=1 || nq!=1 || nj!=1 || nd!=1 ) {
if( na==1 && nk==1 && nq==1 && nj==1 && nd==1 ) {
finallyhand = (LinkedList<Cards>)( hand.clone() );
return true;
} else {
return false;
}
}
/** Check for straight flush - same suit cards in order. */
public boolean hasStraightFlush() {
// If we have a straight or a flush, these will take care of finallyhand for us.
if( hasStraight() && hasFlush() ) {
return true;
} else {
return false;
}
return true;
}
public boolean hasFour() { return (nValues==2 && nPairs==0); }
/** Four of a kind */
public boolean hasFour() {
if(nValues==2 && nPairs==0){
// Only four of a kind cards should go in finallyhand
for(int i=0; i<hand.size(); i++) {
int duper = 0;
for(int j=0; j<hand.size(); j++) {
if(i==j) {
continue;
}
if(hand.get(i).getValue()==hand.get(j).getValue()) {
duper++;
}
}
if(duper==4) {
finallyhand.add(hand.get(i));
}
}
return true;
} else {
return false;
}
}
/** Full house. */
public boolean hasFullHouse() {
return false;
if(nValues==2 && nPairs==1) {
// Only three of a kind cards should go in finallyhand
for(int i=0; i<hand.size(); i++) {
int duper = 0;
for(int j=0; j<hand.size(); j++) {
if(i==j) {
continue;
}
if(hand.get(i).getValue()==hand.get(j).getValue()) {
duper++;
}
}
if(duper==2) {
finallyhand.add(hand.get(i));
}
}
return true;
} else {
return false;
}
}
/** Check for flush - matching straights. */
public boolean hasFlush() {
// Add suits to a set, size should be 1
Set<Character> suits = new HashSet<Character>();
for(Cards c : hand) {
suits.add(c.getSuit());
}
if(suits.size()==1) {
finallyhand = (LinkedList<Cards>)( hand.clone() );
return true;
} else {
return false;
}
}
/** Check for straight - cards in order. */
public boolean hasStraight() {
return false;
// Sort by face value
ValueComparator comp = new ValueComparator();
Collections.sort(hand, comp);
// This is a bit messy, but basically it checks the index of each card
// and ensures that the next card has an index of previous - 1.
//
// Ace is a special case - it can either end a straight DJQKA,
// or it can start a straight A2345.
// We have ace hard coded in the values index at the end,
// so it always behaves as expected with DJQKA.
// However, if we see an ace at the beginning,
// we have to check if it's an ok start.
int priorCardIndex, thisCardIndex;
Iterator<Cards> iter = hand.iterator();
Cards mycard = iter.next();
if(mycard.getValue()=='A') {
priorCardIndex = -1;
} else {
priorCardIndex = indexOf(VALUES, mycard.getValue());
}
while(iter.hasNext()) {
mycard = iter.next();
thisCardIndex = indexOf(VALUES, mycard.getValue());
if( thisCardIndex != (priorCardIndex-1) ) {
return false;
}
}
finallyhand = (LinkedList<Cards>)( hand.clone() );
return true;
}
/** Check for three pairs */
public boolean hasThree() {
if(nThrees>0) {
// Only three of a kind cards should go in finallyhand
for(int i=0; i<hand.size(); i++) {
int duper = 0;
for(int j=0; j<hand.size(); j++) {
if(i==j) {
continue;
}
if(hand.get(i).getValue()==hand.get(j).getValue()) {
duper++;
}
}
if(duper==2) {
finallyhand.add(hand.get(i));
}
}
return true;
} else {
return false;
}
}
/** Check for two pairs */
public boolean hasTwo() {
if(nPairs==2) {
// Only pair cards should go in finallyhand
for(int i=0; i<hand.size(); i++) {
int duper = 0;
for(int j=0; j<hand.size(); j++) {
if(i==j) {
continue;
}
if(hand.get(i).getValue()==hand.get(j).getValue()) {
duper++;
}
}
if(duper==1) {
finallyhand.add(hand.get(i));
}
}
return true;
} else {
return false;
}
}
/** Check for one pair */
public boolean hasOne() {
if(nPairs==1) {
// Only pair cards should go in finallyhand
for(int i=0; i<hand.size(); i++) {
int duper = 0;
for(int j=0; j<hand.size(); j++) {
if(i==j) {
continue;
}
if(hand.get(i).getValue()==hand.get(j).getValue()) {
duper++;
}
}
if(duper==1) {
finallyhand.add(hand.get(i));
}
}
return true;
} else {
return false;
}
}
public boolean hasThree() { return nThrees>0; }
public boolean hasTwo() { return nPairs==2; }
public boolean hasOne() { return nPairs==1; }
// Finished the meat of the class.
////////////////////////////////////////
/** Get string indicating outcome. */
public int getOutcome() {
// Check in order of rank:
// royal flush
@ -202,10 +605,20 @@ class PokerHand { @@ -202,10 +605,20 @@ class PokerHand {
} else if(hasOne()) {
return indexOf(OUTCOMES,"one");
} else {
finallyhand = (LinkedList<Cards>)( hand.clone() );
return indexOf(OUTCOMES,"high");
}
}
public int indexOf(char[] arr, char target) {
for(int i=0; i<arr.length; i++) {
if(arr[i]==target) {
return i;
}
}
return -1;
}
public int indexOf(String[] arr, String target) {
for(int i=0; i<arr.length; i++) {
if(arr[i].equals(target)) {
@ -216,22 +629,12 @@ class PokerHand { @@ -216,22 +629,12 @@ class PokerHand {
}
}
class PokerCompare implements Comparator<PokerHand> {
public PokerCompare() {}
public int compare(PokerHand hand1, PokerHand hand2) {
int hand1outcome = hand1.getOutcome();
int hand2outcome = hand2.getOutcome();
if(hand1outcome==hand2outcome) {
// resolve by high card
System.out.println("meh");
} else {
return (hand1outcome-hand2outcome);
}
return hand1.compareTo(hand2);
}
}

Loading…
Cancel
Save