Android Open Source - pokerdrome Hand Rank






From Project

Back to project page pokerdrome.

License

The source code is released under:

Pokerdrome was released under the GPLv3+ (https://www.gnu.org/licenses/gpl.html) by darlose pokerengine (https://code.google.com/p/pokerengine/) was released under the Apache License 2.0 (https://www...

If you think the Android project pokerdrome listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package com.darlose.pokerdrome;
/*w  w w  .j av  a  2  s .co  m*/
/*
* Copyright (c) 2005 Your Corporation. All Rights Reserved.
*/

import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;

/**
 * User: sam
 * Date: Apr 2, 2005
 * Time: 4:26:31 PM
 */
public final class HandRank implements Comparable<HandRank> {
    private static final int NUM_SUITS = Card.Suit.values().length;
    private static final int NUM_RANKS = Card.Rank.values().length;

    private final Cards hand;
    private final Cards fiveCardHand;
    private Rank rank = Rank.HIGH;
    private static final int HAND_SIZE = 5;
    private static final int TOTAL_POSSIBLE = 7;

    public String toString() {
        return fiveCardHand + ": " + rank.name();
    }

    /**
     * Used to sort handranks.  First check to see which has a higher absolute handrank, then if equal, determine which
     * hand is better.
     */
    public int compareTo(HandRank handRank) {
        int compare = getRank().compareTo(handRank.getRank());
        if (compare != 0) {
            return compare;
        }
        Cards myHand = getHand();
        Cards theirHand = handRank.getHand();
        for (int i = 0; i < HAND_SIZE; i++) {
            if (myHand.size() > i) {
                Card card1 = myHand.get(i);
                Card card2 = theirHand.get(i);
                compare = card1.compareTo(card2);
                if (compare != 0) return compare;
            }
        }
        return 0;
    }

    public enum Rank {
        HIGH, PAIR, TWOPAIR, THREEOFAKIND, STRAIGHT, FLUSH, FULLHOUSE, FOUROFAKIND, STRAIGHTFLUSH
    }


    /**
     * Before calling this method sort the hand from highest to lowest rank.  If you do not do this you will not get interesting results.
     *
     * @param hand The hand must be sorted from highest to lowest rank.
     */
    public HandRank(Cards hand) {
        this.hand = hand;
        fiveCardHand = new Cards(HAND_SIZE);
        evaluate();
    }

    public Rank getRank() {
        return rank;
    }

    private Cards getHand() {
        return fiveCardHand;
    }


    /*
     * Evaluate the hand using the rules of poker.
     *
     */
    private void evaluate() {
        // Bin cards by rank and suit
        for (Card card : hand) {
            assertCard(card);
        }

        // Check for flushes and straight flushes
        if (isStraightFlushOrFlush()) {
            if (rank == Rank.STRAIGHTFLUSH) return;
            // If you have a FLUSH and there are 7 or fewer cards, nothing else can beat it
            if (hand.size() <= 7) return;
        }

        // We'll need this to determine the rest of the hands
        int trips = 0;
        int pairs = 0;

        // Check for 4 of a kind, count trips/pairs
        for (int i = ranks.length - 1; i >= 0; i--) {
            Card[] value = ranks[i];
            if (value == null) continue;
            Card.Rank key = RANKS[i];
            int size = numRanks[i];
            if (size >= 4) {
                rank = Rank.FOUROFAKIND;
                // Get the five card hand
                for (int j = 0; j < value.length; j++) {
                    Card card = value[j];
                    if (card != null) fiveCardHand.add(card);
                }
                for (Card card : hand) {
                    if (card.getRank() != key) {
                        fiveCardHand.add(card);
                        return;
                    }
                }
            }
            if (size == 3) trips++;
            if (size == 2) pairs++;
        }

        // Find full houses
        if ((trips == 1 && pairs >= 1) || (trips > 1)) {
            foundFullHouse();
            return;
        }

        // Now we use the flush from above
        if (rank == Rank.FLUSH) {
            return;
        }

        // Find the straights
        int[] inarow = {1};
        Card firstCard = checkStraight(hand, inarow);
        if (inarow[0] == HAND_SIZE) {
            foundStraight(firstCard);
            return;
        }

        // Trips
        if (trips == 1) {
            foundTrips();
            return;
        }

        // Two of a kind
        if (pairs >= 2) {
            foundTwoPair();
            return;
        }

        // One Pair
        if (pairs == 1) {
            foundPair();
            return;
        }

        // High Card
        for (int i = 0; i < HAND_SIZE; i++) {
            if (hand.size() > i) fiveCardHand.add(hand.get(i));
        }
    }

    private void foundFullHouse() {
        rank = Rank.FULLHOUSE;
        Card.Rank tripRank = null;
        // Find the biggest trips
        for (int i = ranks.length - 1; i >= 0; i--) {
            Card[] value = ranks[i];
            if (value == null) continue;
            if (numRanks[i] == 3) {
                tripRank = RANKS[i];
                break;
            }
        }
        // Remove this trip and find the biggest match for the house
        final int tripOrd = tripRank.ordinal();
        for (int j = 0; j < numRanks[tripOrd]; j++)
            fiveCardHand.add(ranks[tripOrd][j]);
        ranks[tripOrd] = null;
        Card.Rank pairRank = null;
        // Find the next biggest pair
        for (int i = ranks.length - 1; i >= 0; i--) {
            Card[] value = ranks[i];
            if (value == null) continue;
            if (numRanks[i] >= 2) {
                pairRank = RANKS[i];
                break;
            }
        }
        Card[] pairCards = ranks[pairRank.ordinal()];
        // Just add the first two cards from the match
        for (int i = 0; i < 2; i++) {
            fiveCardHand.add(pairCards[i]);
        }
    }

    private void foundPair() {
        rank = Rank.PAIR;
        Card.Rank firstPair = null;
        for (int i = 0; i < ranks.length; i++) {
            Card[] value = ranks[i];
            if (value == null) continue;
            if (numRanks[i] == 2) {
                firstPair = RANKS[i];
                break;
            }
        }
        final int firstOrd = firstPair.ordinal();
        for (int i = 0; i < numRanks[firstOrd]; i++)
            fiveCardHand.add(ranks[firstOrd][i]);
        int i = 0;
        for (Card card : hand) {
            if (card.getRank() != firstPair) {
                fiveCardHand.add(card);
                if (++i == 3) break;
            }
        }
    }

    private void foundStraight(Card firstCard) {
        boolean add = false;
        Card last = null;
        for (Card card : hand) {
            // Purposeful optimization
            if (card == firstCard) {
                add = true;
            }
            if (add) {
                if (last == null || last.getRank() != card.getRank()) {
                    fiveCardHand.add(card);
                    if (fiveCardHand.size() == HAND_SIZE) break;
                    last = card;
                }
            }
        }
        // Make sure you add the Ace in for the wheel
        if (fiveCardHand.size() == 4) {
            fiveCardHand.add(hand.get(0));
        }
        rank = Rank.STRAIGHT;
    }

    private void foundTrips() {
        rank = Rank.THREEOFAKIND;
        Card.Rank tripRank = null;
        // Find the biggest trips
        for (int i = 0; i < ranks.length; i++) {
            Card[] value = ranks[i];
            if (value == null) continue;
            if (numRanks[i] == 3) {
                tripRank = RANKS[i];
                for (int j = 0; j < numRanks[i]; j++)
                    fiveCardHand.add(ranks[i][j]);
                break;
            }
        }
        int i = 0;
        for (Card card : hand) {
            if (card.getRank() != tripRank) {
                fiveCardHand.add(card);
                i++;
            }
            if (i == 2) break;
        }
    }

    private void foundTwoPair() {
        rank = Rank.TWOPAIR;
        Card.Rank firstPair = null;
        Card.Rank secondPair = null;
        int firstOrd = -1;
        int secondOrd = -1;
        for (int i = ranks.length - 1; i >= 0; i--) {
            Card[] value = ranks[i];
            if (value == null) continue;
            if (numRanks[i] == 2) {
                Card.Rank rank = RANKS[i];
                if (firstPair == null) {
                    firstPair = rank;
                    firstOrd = firstPair.ordinal();
                } else {
                    secondPair = rank;
                    secondOrd = secondPair.ordinal();
                    break;
                }
            }
        }
        for (int i = 0; i < numRanks[firstOrd]; i++)
            fiveCardHand.add(ranks[firstOrd][i]);
        for (int i = 0; i < numRanks[secondOrd]; i++)
            fiveCardHand.add(ranks[secondOrd][i]);
        for (Card card : hand) {
            if (card.getRank() != firstPair && card.getRank() != secondPair) {
                fiveCardHand.add(card);
                break;
            }
        }
    }

    private boolean isStraightFlushOrFlush() {
        for (int i = 0; i < suits.length; i++) {
            Card[] cards = suits[i];
            if (cards == null) continue;
            if (numSuits[i] >= HAND_SIZE) {
                int[] inarow = {1};
                Card firstCard = checkStraight(cards, numSuits[i], inarow);
                if (inarow[0] == HAND_SIZE) {
                    boolean add = false;
                    for (int j = 0; j < numSuits[i]; j++) {
                        Card card = suits[i][j];
                        // Purposeful optimization
                        if (card == firstCard) {
                            add = true;
                        }
                        if (add) {
                            fiveCardHand.add(card);
                        }
                        if (fiveCardHand.size() == HAND_SIZE) break;
                    }
                    if (fiveCardHand.size() == 4) {
                        fiveCardHand.add(suits[i][0]);
                    }
                    rank = Rank.STRAIGHTFLUSH;
                } else {
                    // At least a flush
                    for (int j = 0; j < HAND_SIZE; j++) {
                        fiveCardHand.add(cards[j]);
                        rank = Rank.FLUSH;
                    }
                }
                return true;
            }
        }
        return false;
    }

    // This would have been a good place to use a closure.  Make sure that this
    // method changes in sync with the other version
    private static Card checkStraight(Cards hand, int[] inarow) {
        // This is the value of the straight
        Card firstCard = null;
        // Keep track of the last card so we can skip over pairs and determine continuity
        Card lastCard = null;
        // Check to see if there is a straight as well
        int num = hand.size();
        for (int i = 0; i < num; i++) {
            Card card = hand.get(i);
            if (lastCard != null) {
                int lastOrd = lastCard.getRank().ordinal();
                int cardOrd = card.getRank().ordinal();
                if (lastOrd - cardOrd == 1) {
                    inarow[0]++;
                    if (inarow[0] == 4 && card.getRank() == Card.Rank.TWO && hand.get(0).getRank() == Card.Rank.ACE) {
                        // Wheel
                        inarow[0]++;
                    }
                } else if (lastOrd - cardOrd != 0) {
                    inarow[0] = 1;
                    firstCard = card;
                }
            } else {
                firstCard = card;
            }
            lastCard = card;

            // Highest straight found
            if (inarow[0] == HAND_SIZE) return firstCard;

            // OPT: If we have a straight or have too few cards remaining, return.
            if (num - i + inarow[0] < HAND_SIZE) return null;
        }
        return null;
    }

    private static Card checkStraight(Card[] cards, int num, int[] inarow) {
        // This is the value of the straight
        Card firstCard = null;
        // Keep track of the last card so we can skip over pairs and determine continuity
        Card lastCard = null;
        // Check to see if there is a straight as well
        for (int i = 0; i < num; i++) {
            Card card = cards[i];
            if (lastCard != null) {
                int lastOrd = lastCard.getRank().ordinal();
                int cardOrd = card.getRank().ordinal();
                if (lastOrd - cardOrd == 1) {
                    inarow[0]++;
                    if (inarow[0] == 4 && card.getRank() == Card.Rank.TWO && cards[0].getRank() == Card.Rank.ACE) {
                        // Wheel
                        inarow[0]++;
                    }
                } else if (lastOrd - cardOrd != 0) {
                    inarow[0] = 1;
                    firstCard = card;
                }
            } else {
                firstCard = card;
            }
            lastCard = card;

            // Highest straight found
            if (inarow[0] == HAND_SIZE) return firstCard;

            // OPT: If we have a straight or have too few cards remaining, return.
            if (num - i + inarow[0] < HAND_SIZE) return null;
        }
        return null;
    }

    private final Card[][] ranks = new Card[NUM_RANKS][];
    private final int[] numRanks = new int[NUM_RANKS];
    private final Card[][] suits = new Card[NUM_SUITS][];
    private final int[] numSuits = new int[NUM_SUITS];

    private static final Card.Rank[] RANKS = new Card.Rank[NUM_RANKS];
    private static final Card.Suit[] SUITS = new Card.Suit[NUM_SUITS];

    static {
        int i = 0;
        for (Card.Rank rank : Card.Rank.values()) {
            RANKS[i++] = rank;
        }
        i = 0;
        for (Card.Suit suit : Card.Suit.values()) {
            SUITS[i++] = suit;
        }
    }

    private void assertCard(Card card) {
        int cardRank = card.getRank().ordinal();
        Card[] rankList = ranks[cardRank];
        if (rankList == null) {
            rankList = new Card[NUM_SUITS];
            ranks[cardRank] = rankList;
        }
        int numRank = numRanks[cardRank]++;
        rankList[numRank] = card;
        int cardSuit = card.getSuit().ordinal();
        Card[] suitList = suits[cardSuit];
        if (suitList == null) {
            suitList =  new Card[NUM_RANKS];
            suits[cardSuit] = suitList;
        }
        int numSuit = numSuits[cardSuit]++;
        suitList[numSuit] = card;
    }

}




Java Source Code List

com.darlose.pokerdrome.CardDeck.java
com.darlose.pokerdrome.Card.java
com.darlose.pokerdrome.Cards.java
com.darlose.pokerdrome.Deck.java
com.darlose.pokerdrome.Evaluate.java
com.darlose.pokerdrome.Game.java
com.darlose.pokerdrome.HandRank.java
com.darlose.pokerdrome.MainActivity.java
com.darlose.pokerdrome.Player.java
com.darlose.pokerdrome.Tables.java
com.darlose.pokerdrome.VideoPokerActivity.java