import java.util.*; import card.*; class Game { private List deck = new ArrayList<>(); private List> hands = new ArrayList<>(); private List ranks = new ArrayList<>(); public Game() { setDeck(); } public Game(int handsNum) { setDeck(); // preflop for (int i = 0; i < handsNum; i++) { hands.add(setHand(2)); } for (List hand : hands) { getHand(hand); System.out.println(); } // flop, turn, and river hands.add(setHand(5)); List street = hands.get(hands.size() - 1); getHand(hands.get(hands.size() - 1)); System.out.println(); for (int i = 0; i < handsNum; i++) { for (int j = 0; j < 5; j++) { hands.get(i).add(street.get(j)); } hands.set(i, sort(hands.get(i))); } // TODO: find a better way to calculate combinations for each hand for (int i = 0; i < handsNum; i++) { List> combinations; combinations = generate(hands.get(i)); List combinationRanks = new ArrayList<>(); for (List combination : combinations) { combinationRanks.add(getRank(combination)); } int winner = getWinner(combinations, combinationRanks); hands.set(i, combinations.get(winner)); } for (int i = 0; i < handsNum; i++) { ranks.add(getRank(hands.get(i))); } } public void setHands(List> hands) { this.hands = hands; } public void setRanks(List ranks) { this.ranks = ranks; } public void setDeck() { Suit s = Suit.CLUBS; for (int i = 0; i < 4; i++) { switch (i) { case 0: s = Suit.CLUBS; break; case 1: s = Suit.DIAMONDS; break; case 2: s = Suit.HEARTS; break; case 3: s = Suit.SPADES; break; } for (int j = 1; j <= 13; j++) { Card card = new Card(j, s); deck.add(card); } } } public List sort(List hand) { if (hand.size() <= 1) return hand; int mid = hand.size() / 2; List left = sort(hand.subList(0, mid)); List right = sort(hand.subList(mid, hand.size())); return merge(left, right); } public List merge(List left, List right) { List result = new ArrayList<>(); int l = 0, r = 0; while (l < left.size() || r < right.size()) { if (l < left.size() && (r == right.size() || left.get(l).getValue() < right.get(r).getValue() )) { result.add(left.get(l)); l++; } else { result.add(right.get(r)); r++; } } return result; } public List setHand(int size) { List hand = new ArrayList<>(); Random rand = new Random(); for (int i = 0; i < size; i++) { int randInt = rand.nextInt(deck.size()); hand.add(deck.get(randInt)); deck.remove(randInt); } return sort(hand); } public void getHand(List hand) { for (Card c : hand) { System.out.println(c.displayCard()); } } public List> generate(List hand) { List> combinations = new ArrayList<>(); helper(hand, new ArrayList(), combinations); return combinations; } public void helper(List hand, List combination, List> combinations) { if (combination.size() == 5) { combinations.add(new ArrayList<>(sort(combination))); } else { for (int i = 0; i < 5; i++) { if (combination.contains(hand.get(i))) continue; combination.add(hand.get(i)); helper(hand, combination, combinations); combination.remove(combination.size() - 1); } } } public int getRank(List hand) { if (isRoyalFlush(hand)) { return 9; } else if (isStraightFlush(hand)) { return 8; } else if (isFourOfKind(hand)) { return 7; } else if (isFullHouse(hand)) { return 6; } else if (isFlush(hand)) { return 5; } else if (isStraight(hand)) { return 4; } else if (isThreeOfKind(hand)) { return 3; } else if (isTwoPair(hand)) { return 2; } else if (isPair(hand)) { return 1; } else { return 0; } } public void displayRank(List hand, int rank) { switch (rank) { case 8: System.out.println("Straight flush"); break; case 7: System.out.println("Four of a kind"); break; case 6: System.out.println("Full house"); break; case 5: System.out.println("Flush"); break; case 4: System.out.println("Straight"); break; case 3: System.out.println("Three of a kind"); break; case 2: System.out.println("Two pair"); break; case 1: System.out.println("Pair"); break; default: System.out.println("High card " + highCard(hand)); } } public String highCard(List hand) { if (hand.get(0).getValue() == 1) return hand.get(0).displayCard(); return hand.get(hand.size() - 1).displayCard(); } public boolean isPair(List hand) { boolean pair = false; for (int i = 0; i < hand.size() - 1; i++) pair = pair || (hand.get(i).getValue() == hand.get(i + 1).getValue()); return pair; } public boolean isTwoPair(List hand) { int numberOfPairs = 0; int i = 0; while (i < hand.size() - 1) { if (isPair(hand.subList(i, i + 2))) { numberOfPairs++; i += 2; } else { i++; } } return numberOfPairs == 2; } public boolean isThreeOfKind(List hand) { boolean threeOfKind = false; for (int i = 0; i < hand.size() - 2; i++) threeOfKind = threeOfKind || (hand.get(i).getValue() == hand.get(i + 2).getValue()); return threeOfKind; } // TODO: ace high straight public boolean isStraight(List hand) { int prev = hand.get(0).getValue(); int count = 0; for (int i = 1; i < hand.size() && count < 4; i++) { if (hand.get(i).getValue() - prev == 1) { count++; } else { count = 0; } prev = hand.get(i).getValue(); } return count == 4; } public boolean isFlush(List hand) { boolean flush = true; Suit suit = hand.get(0).getSuit(); for (int i = 1; i < hand.size(); i++) flush = flush && (hand.get(i).getSuit() == suit); return flush; } public boolean isFullHouse(List hand) { boolean pairThreeOfKind = false; boolean threeOfKindPair = false; for (int i = 0; i < hand.size() - 4; i++) pairThreeOfKind = (hand.get(i).getValue() == hand.get(i + 1).getValue()) && (hand.get(i + 2).getValue() == hand.get(i + 4).getValue()); for (int i = 0; i < hand.size() - 4; i++) threeOfKindPair = (hand.get(i).getValue() == hand.get(i + 2).getValue()) && (hand.get(i + 3).getValue() == hand.get(i + 4).getValue()); return pairThreeOfKind || threeOfKindPair; } public boolean isFourOfKind(List hand) { boolean fourOfKind = false; for (int i = 0; i < hand.size() - 3; i++) fourOfKind = fourOfKind || (hand.get(i).getValue() == hand.get(i + 3).getValue()); return fourOfKind; } public boolean isStraightFlush(List hand) { return isStraight(hand) && isFlush(hand); } // TODO: check A-10 public boolean isRoyalFlush(List hand) { return isFlush(hand) && hand.get(0).getValue() == 1 && hand.get(1).getValue() == 10 && hand.get(4).getValue() == 13; } public boolean compareHighCard(List firstHand, List secondHand) { if (firstHand.get(0).getValue() == 1) { return true; } else if (secondHand.get(0).getValue() == 1) { return false; } for (int j = firstHand.size() - 1; j > 0; j--) { if (firstHand.get(j).getValue() > secondHand.get(j).getValue()) { return true; } else if (secondHand.get(j).getValue() > firstHand.get(j).getValue()) { return false; } } return false; } public boolean comparePair(List firstHand, List secondHand) { Set temp = new HashSet<>(); int high = firstHand.get(0).getValue(); for (int i = 1; i < firstHand.size(); i++) { Card c = firstHand.get(i); if (temp.contains(c.getValue())) { high = c.getValue(); } else { temp.add(c.getValue()); } } temp.clear(); for (Card c : secondHand) { if (temp.contains(c.getValue())) { if (high > c.getValue()) return true; } else { temp.add(c.getValue()); } } return false; } // TODO: combine with comparePair and compareThreeOfKind public boolean compareTwoPair(List firstHand, List secondHand) { Set temp = new HashSet<>(); int high = firstHand.get(0).getValue(); for (int i = 1; i < firstHand.size(); i++) { Card c = firstHand.get(i); if (temp.contains(c.getValue()) && c.getValue() > high) { high = c.getValue(); } else { temp.add(c.getValue()); } } temp.clear(); int greater = 0; for (Card c : secondHand) { if (temp.contains(c.getValue()) && high > c.getValue()) { greater++; } else { temp.add(c.getValue()); } } return greater >= 2; } public int getWinner(List> hands, List ranks) { int bestHand = 0, bestRank = 0; for (int i = 0; i < ranks.size(); i++) { if (ranks.get(i) > bestRank) { bestHand = i; bestRank = ranks.get(i); } else if (ranks.get(i) == bestRank) { switch (bestRank) { case 7: case 6: case 3: case 2: if (compareTwoPair(hands.get(i), hands.get(bestHand))) { bestHand = i; bestRank = ranks.get(i); } break; case 1: if (comparePair(hands.get(i), hands.get(bestHand))) { bestHand = i; bestRank = ranks.get(i); } break; case 5: case 4: case 0: if (compareHighCard(hands.get(i), hands.get(bestHand))) { bestHand = i; bestRank = ranks.get(i); } } } } return bestHand; } public static void main(String[] args) { Game g = new Game(8); for (int i = 0; i < 8; i++) { g.getHand(g.hands.get(i)); g.displayRank(g.hands.get(i), g.ranks.get(i)); System.out.println(); } System.out.println(g.getWinner(g.hands, g.ranks)); } }