The simplest algorithm for poker hand evaluation

后端 未结 12 1043
独厮守ぢ
独厮守ぢ 2020-12-04 12:39

I am thinking about poker hand (5 cards) evaluation in Java. Now I am looking for simplicity and clarity rather than performance and efficiency. I probably can

12条回答
  •  刺人心
    刺人心 (楼主)
    2020-12-04 13:22

    You actually don't need any advanced functions, it can be all done bitwise: (source: http://www.codeproject.com/Articles/569271/A-Poker-hand-analyzer-in-JavaScript-using-bit-math)

    (This one is actually written in JavaScript, but you can evaluate JavaScript from Java if needed, so it shouldn't be a problem. Also, this is as short as it gets, so if even for illustration of the approach...):

    First you split your cards into two arrays: ranks (cs) and suits (ss) and to represent suits, you will use either 1,2,4 or 8 (that is 0b0001, 0b0010,...):

    var J=11, Q=12, K=13, A=14, C=1, D=2, H=4, S=8;
    

    Now here's the magic:

    function evaluateHand(cs, ss) {
        var pokerHands = ["4 of a Kind", "Straight Flush","Straight","Flush","High Card","1 Pair","2 Pair","Royal Flush", "3 of a Kind","Full House"];
    
        var v,i,o,s = 1 << cs[0] | 1 << cs[1] | 1 << cs[2] | 1 << cs[3] | 1 << cs[4];
        for (i = -1, v = o = 0; i < 5; i++, o = Math.pow(2, cs[i] * 4)) {v += o * ((v / o & 15) + 1);}
        v = v % 15 - ((s / (s & -s) == 31) || (s == 0x403c) ? 3 : 1);
        v -= (ss[0] == (ss[1] | ss[2] | ss[3] | ss[4])) * ((s == 0x7c00) ? -5 : 1);
        return pokerHands[v];
    }
    

    Usage:

    evaluateHand([A,10,J,K,Q],[C,C,C,C,C]); // Royal Flush
    

    Now what it does (very briefly) is that it puts 1 into 3rd bit of s when there's a 2, into 4th when there's 3, etc., so for the above example s looks like this:

    0b111110000000000

    for [A,2,3,4,5] it would look like this

    0b100 0000 0011 1100

    etc.

    v uses four bits to record multiple occurencies of same card, so it's 52bits long and if you have three Aces and two kings, its 8 MSB bits look like:

    0111 0011 ...

    The last line then checks for a flush or straight flush or royal flush (0x7c00).

提交回复
热议问题