简体   繁体   中英

Java 7 card poker hand evaluator

I'm trying to create a hand evaluator that it will allow me to compare if one hand is better than another. I know there many other post on SO about this topic however many of them are old now and the links no longer link to anything useful. The only way I can think of doing this at the moment is to manually check for every different combination. Eg check for ace of any suit, if this doesn't exist then move to the next combination eg straight flush then 4 of a kind and so on. However, then how would you compare a pair of 2s to a pair of 3s unless you gave an integer to every combination of cards that made something interesting. However, that would very hard to do manually. Is there a better way?

Why hard?

class Card{

String suite;
int value;
....
}
// ...if two combinations are equal, Do for both combinations
int power = 0;

for (Card card: combination){
power += card.getValue()
}
// and compare!

I would separate the problem for each type of combinations, and assign an integer for a specific occurence of a combination called ie. strength (so a Straight Flush of 5-4-3-2-A is the weakest and KQJ-10-9 is the strongest).

Individual combinations can be handled pretty well i think. For a royal flush, you sort your 7 cards by their number descending, and check if the first 5 cards are (AKQJ-10) and if they are of the same suit. A royal flush's strength is indefinite.

For flush you can sort your cards by suit, and check if you can move 4 times in your list of card without witnessing a suit change. A Flush's strength is determined by the highest valued card of it.

A very brief template for the idea:

   // main logic of who wins, note it doesn't handle when two players have the same
// combo with same strength
class HandComparator {
    public Player compare(Player player1, Player player2) {
        HandEvaluator handEvaluator = new HandEvaluator();
        Combination player1Combo = handEvaluator.evaluate(player1.hand);
        Combination player2Combo = handEvaluator.evaluate(player2.hand);

        if (player1Combo.type.equals(player2Combo.type)) {
            // note, strength is only taken into account if the two players have
            // the same combo (ie both has full house)
            if (player1Combo.strength < player2Combo.strength) {
                return player2;
            } else {
                return player1;
            }
        } else if (player1Combo.type.compareTo(player2Combo.type) < 0) {
            return player2;
        } else {
            return player1;
        }
    }
}

class Card {
    int suit;
    int number;
}

class Player {
    List<Card> hand;
}

// this is built by CombinationRecognisers. Note, that the member 'strength' is
// related to a specific combination, not all possible hands
class Combination {

    enum Type {
        ROYAL_FLUSH,
        STRAIGHT_FLUSH;
        // etc.
    }

    Type type;
    int strength;
}

// implement this for all combinations (ROYAL_FLUSH,STRAIGHT_FLUSH, etc)
interface CombinationRecogniser {
    public Combination evaluate(List<Card> hand);
}

/*
 * this class holds all CombinationRecognisers and iterates throught them. It
 * will stop the moment a combo has been found.
 */
class HandEvaluator {
    static List<CombinationRecogniser> recognizers = new ArrayList<CombinationRecogniser>();

    static {
        recognizers.add(new RoyalFlushRecogniser());
        recognizers.add(new StraightFlushRecogniser());
    }

    public Combination evaluate(List<Card> hand) {

        for (CombinationRecogniser recogniser : recognizers) {
            Combination combination = recogniser.evaluate(hand);
            if (combination != null) {
                return combination;
            }
        }
        return null;
    }
}

class RoyalFlushRecogniser implements CombinationRecogniser {

    @Override
    public Combination evaluate(List<Card> hand) {
        // code goes here that decides if the given hand is a valid royal flush
        return null; // of new Combination() if the given hand is a valid royal flush
    }

}

class StraightFlushRecogniser implements CombinationRecogniser {

    @Override
    public Combination evaluate(List<Card> hand) {
        // code goes here that decides if the given hand is a valid straight flush
        return null; // of new Combination() if the given hand is a valid royal flush
    }

}

This code actually works if you implement the CombinationRecogniser interface for all special combinations. An example:

I don't know if this is the best approach, but this could be possible and this is all manually.

Let's say you already have the code to determine which hand the player has in this format:

22s, KKs, 98o, 11o

Now you have an array with three values eg:

["K", "K", "s"]

...and another array:

[9, 8, "o"]

You first have to class those hands (like flush, straight etc.) to make sure which one will win (royal flush always win). And after those checks, you have to do some checks in the array. Check if it's suited or offsuit, if "K" is higher than 9 etc.

You can give them values like this:

...
8=8
9=9
10=10
J=11
Q=12
K=13
A=14 (or 1)

And then compare with that. This is a hard algorithm to do it properly without doing so many things manually. I hope someone who has experience with this takes my answer over and recover my mistakes or wrong steps/thoughts.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM