|
-
Jan 26th, 2010, 10:18 AM
#1
Poker Hand Evaluator
After reading about how poker hands are evaluated, I decided to have a go at it. Before I proceeded further I wanted to solicit opinions for what I have done so far.
edit - For now I am not worried about the return, but thoughts on how the Hand Ranking is returned is appreciated.
edit - Removed code
Last edited by dbasnett; Jan 28th, 2010 at 09:46 AM.
Reason: Remove code
-
Jan 28th, 2010, 09:59 AM
#2
Re: Poker Hand Evaluator
So the code has changed a lot. In pseudo code it now looks like this:
Check for Straight and Straight Flush
If Not Straight Flush Check for Flush
If Not Flush and Not Straight Check 4 of a Kind
If Not 4 of a Kind Mark Pairs and Trips Checking for Full House
end pseudo code
I have changed the order of checking numerous times, and I think this is best. The only thing I can think of, that might perform better is to check for full house first. But after days of thinking about it, I am not sure that I am thinking... Maybe over-thinking?
Two hands follow
Hand - 1
2 clubs
2 hearts
3 clubs
3 hearts
4 clubs
5 clubs
6 clubs
Hand - 2
2 clubs
2 hearts
3 clubs
3 hearts
3 diamonds
5 clubs
6 clubs
-
Jan 28th, 2010, 10:38 AM
#3
Frenzied Member
Re: Poker Hand Evaluator
Are you just trying to compare two or more hands to see which one is the highest? Why does it matter which order you check for each type of hand?
-
Jan 28th, 2010, 11:00 AM
#4
Re: Poker Hand Evaluator
You need to check hands in order to determine the highest hand condition is recognized. For example, if you have a 4 of a kind, the check for a 3 of a kind and a pair are also true.
You can split some conditions up, like the test for Flush, because if Flush = True, then you proceed to check for Straight. Throw in a high-card check and you can then determine between a Flush, Straight, Straight-Flush and Royal Flush. I'll dig up my evaluator function and post it for comparison.
-
Jan 28th, 2010, 11:17 AM
#5
Re: Poker Hand Evaluator
 Originally Posted by nbrege
Are you just trying to compare two or more hands to see which one is the highest? Why does it matter which order you check for each type of hand?
The order can eliminate certain possibilities. For example, if you have a full house, you can't have straight or flush.
The performance of the hand evaluator is dependent on the order. Right now I am around 0.00003 seconds per hand on my 1.8GHz laptop.
-
Jan 28th, 2010, 11:39 AM
#6
Frenzied Member
Re: Poker Hand Evaluator
I disagree that the order is important, but it all depends on how you code it. A flush beats a straight regardless of which one you check for first. If you're concerned about order then why not just check each hand in the same order as the rankings? ie. check for 1 pair, then 2 pair, then 3 of a kind, etc. Also, how are you ranking hands of the same type? ie. two flushes.
Last edited by nbrege; Jan 28th, 2010 at 12:22 PM.
-
Jan 28th, 2010, 12:53 PM
#7
Re: Poker Hand Evaluator
 Originally Posted by nbrege
I disagree that the order is important, but it all depends on how you code it. A flush beats a straight regardless of which one you check for first. If you're concerned about order then why not just check each hand in the same order as the rankings? ie. check for 1 pair, then 2 pair, then 3 of a kind, etc. Also, how are you ranking hands of the same type? ie. two flushes.
Maybe my whole approach is wrong, but the order does make a big difference in what I have done so far. A pair, two pair, and three of a kind, don't eliminate other checks.
-
Jan 28th, 2010, 12:58 PM
#8
Frenzied Member
Re: Poker Hand Evaluator
Well, then check in reverse order ... straight flush, four of a kind, full house, etc. Whenever you find a match, you eliminate all the lesser ranked hands. What exactly is your end goal?
-
Jan 28th, 2010, 01:06 PM
#9
-
Jan 28th, 2010, 03:43 PM
#10
Re: Poker Hand Evaluator
I saw that. It didn't tell me much. I was only asking if the approach I posted made sense and seemed efficient.
-
Jan 28th, 2010, 03:51 PM
#11
Re: Poker Hand Evaluator
Funny, I implemented something extremely similar to that algorithm when I made mine. I never fully tested it but it seemed to work well enough.
Here's my "Hand" object. Notice the very slick GetHandRank function. 
Code:
Public Class Hand
Inherits List(Of Card)
Implements ICloneable
Public Function GetBestHand() As HandRank
Dim listHands As List(Of HandRank) = Me.CheckHand
Dim bestHands = From hr In listHands Where hr.Rank = listHands.Max(Function(hr2 As HandRank) hr2.Rank)
Return (From hr In bestHands Where hr.Highcard.Rank = bestHands.Max(Function(hr2 As HandRank) hr2.Highcard.Rank)).FirstOrDefault
End Function
Private Function CheckHand() As List(Of HandRank)
Dim hl As New List(Of HandRank)
If Me.Count > 5 Then
For Each c In Me
Dim h2 As Hand = DirectCast(Me.Clone, Hand)
h2.Remove(c)
hl.AddRange(h2.CheckHand.ToArray)
Next
Else
hl.Add(New HandRank With {.Rank = Me.GetHandRank, .Highcard = Me.GetHighCard})
Return hl
End If
Return hl
End Function
Private Function GetHandRank() As HandRankType
Dim hist = Me.GroupBy(Function(c) New With {Key c.Rank}).Select(Function(CardCount) CardCount.Count)
If hist.Contains(4) Then Return HandRankType.FourOfAKind
If hist.Contains(3) AndAlso hist.Contains(2) Then Return HandRankType.FullHouse
If hist.Contains(3) AndAlso hist.Count = 3 Then Return HandRankType.ThreeOfAKind
If hist.Contains(2) AndAlso hist.Count = 3 Then Return HandRankType.TwoPair
If hist.Count = 4 Then Return HandRankType.OnePair
Dim booFlush As Boolean = Me.GroupBy(Function(c) New With {Key c.Suite}).Count = 1
Dim booStraight As Boolean = Me.Max(Function(c As Card) c.Rank) - Me.Min(Function(c As Card) c.Rank) = 4
Dim booAceHigh As Boolean = Me.Max(Function(c As Card) c.Rank) = CardRank.Ace
If booAceHigh AndAlso booStraight AndAlso booFlush Then Return HandRankType.RoyalFlush
If booFlush AndAlso booStraight Then Return HandRankType.StraightFlush
If booFlush Then Return HandRankType.Flush
If booStraight Then Return HandRankType.Straight
Return HandRankType.HighCard
End Function
Private Function GetHighCard() As Card
Return (From c In Me Where c.Rank = Me.Max(Function(c2 As Card) c2.Rank) Select c).FirstOrDefault
End Function
Public Function Clone() As Object Implements System.ICloneable.Clone
Dim newHand As New Hand
newHand.AddRange(Me.ToArray)
Return newHand
End Function
End Class
-
Jan 28th, 2010, 03:54 PM
#12
Re: Poker Hand Evaluator
This is pretty close to yours:
Check - Straight
Check - Flush
If Both True Done
Check - Four Of A Kind
If True Done
Check - Full House
If True Done
If Flush Was True Done
If Straight Was True Done
Check - Three Of A Kind
If True Done
Check - Two Pair
If True Done
Check - Pair
If True Done
If None True Then
Result Is High Card
-
Jan 28th, 2010, 04:07 PM
#13
Re: Poker Hand Evaluator
Here, these are the little support/data classes and enums for the above post just so you don't have to reverse engineer it from the above.
Code:
Public Module Enums
Public Enum CardSuite
Spade = 4
Heart = 3
Club = 2
Diamond = 1
End Enum
Public Enum HandRankType
RoyalFlush = 10
StraightFlush = 9
FourOfAKind = 8
FullHouse = 7
Flush = 6
Straight = 5
ThreeOfAKind = 4
TwoPair = 3
OnePair = 2
HighCard = 1
End Enum
Public Enum CardRank
Ace = 13
King = 12
Queen = 11
Jack = 10
Ten = 9
Nine = 8
Eight = 7
Seven = 6
Six = 5
Five = 4
Four = 3
Three = 2
Deuce = 1
End Enum
End Module
Public Class HandRank
Public Rank As HandRankType
Public Highcard As Card
End Class
Public Class Card
Public Suite As CardSuite
Public Rank As CardRank
End Class
-
Jan 28th, 2010, 04:52 PM
#14
Re: Poker Hand Evaluator
@Jenner - Thanks. It will take me some time to digest that. It is certainly prettier than my code.
Have you tested it for time? In my test rig I only time the code in the hand evaluation. As I posted earlier I am around 0.00003 seconds per hand on my 1.8GHz laptop. I still need to add tie breakers for straight flush, straight, flush, two pair, pair, and high card.
note - I am testing 7 card hands, with ace being high and low.
I also added a singleton count. When I did it with LINQ I took a performance hit, but when I iterated throught the array manually I saw a slight increase in performance.
Last edited by dbasnett; Jan 28th, 2010 at 04:55 PM.
-
Jan 28th, 2010, 05:00 PM
#15
Re: Poker Hand Evaluator
Let me convert it for ace high and low. I assume low ace is only used for evaluation of straights? Last I tested it, it was monster-fast. I don't have your code or your rig, so any number I get on my end wouldn't be a good comparison.
EDIT: Using the diagnostics.stopwatch I'm getting a fairly consistent 0.0000185 sec/hand on my rig which is a Core 2 Duo E8400 @ 3.00Ghz. I'm not checking for low-ace though.
EDIT #2: Altered the function to check for the wheel (ace low-straight). Time decreased to about 0.0000181 sec/hand from just sorting it once and using their indexes to figure straights. GetHandRank function now looks like this:
Code:
Private Function GetHandRank() As HandRankType
Dim hist = Me.GroupBy(Function(c) New With {Key c.Rank}).Select(Function(CardCount) CardCount.Count)
If hist.Contains(4) Then Return HandRankType.FourOfAKind
If hist.Contains(3) AndAlso hist.Contains(2) Then Return HandRankType.FullHouse
If hist.Contains(3) AndAlso hist.Count = 3 Then Return HandRankType.ThreeOfAKind
If hist.Contains(2) AndAlso hist.Count = 3 Then Return HandRankType.TwoPair
If hist.Count = 4 Then Return HandRankType.OnePair
Me.Sort(New Comparison(Of Card)(Function(c1 As Card, c2 As Card) If(c1.Rank > c2.Rank, 1, If(c1.Rank < c2.Rank, -1, 0))))
Dim booAceHigh As Boolean = Me(4).Rank = CardRank.Ace
Dim booCheckWheel As Boolean = Me(3).Rank = CardRank.Five
Dim booStraight As Boolean = (booAceHigh AndAlso booCheckWheel) OrElse Me(4).Rank - Me(0).Rank = 4
Dim booFlush As Boolean = Me.GroupBy(Function(c) New With {Key c.Suite}).Count = 1
If booAceHigh AndAlso booStraight AndAlso booFlush Then Return HandRankType.RoyalFlush
If booFlush AndAlso booStraight Then Return HandRankType.StraightFlush
If booFlush Then Return HandRankType.Flush
If booStraight Then Return HandRankType.Straight
Return HandRankType.HighCard
End Function
Last edited by Jenner; Jan 28th, 2010 at 05:57 PM.
-
Jan 28th, 2010, 06:33 PM
#16
Re: Poker Hand Evaluator
I am Pentium(R) M @ 1.8Ghz, with some tie checking in place.
0.0000230
0.0000181
I don't know how the processors compare, and my number is going to go up with all the other tie checking.
BTW - I pulled the singleton check out. If you have 7 singletons you still might have a straight.
-
Jan 29th, 2010, 10:00 AM
#17
Re: Poker Hand Evaluator
I think I have it, and the times only went up fractionally. After I run some more tests I'll post the whole project if anyone is interested.
-
Jan 29th, 2010, 01:51 PM
#18
Re: Poker Hand Evaluator
Yea, I'd be interested.
-
Jan 29th, 2010, 04:50 PM
#19
Re: Poker Hand Evaluator
CardBasics.zip
Not cleaned up at all, but here you go.
-
Jan 30th, 2010, 07:51 PM
#20
Re: Poker Hand Evaluator
added BlackJack hand evaluator
Code:
Public Function BlackJackHandEvaluate(ByVal theHand As Hand) As Integer
Dim ranks() As Integer = New Integer() {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
Dim retval As Integer = 0
For Each c As Card In theHand
ranks(c.Rank) += 1
If c.Rank = Rank.Ace Then
retval += 11
ElseIf c.Rank + 2 >= 10 Then
retval += 10
Else
retval += c.Rank + 2
End If
Next
If retval <= 21 OrElse ranks(ranks.Length - 1) = 0 Then Return retval
Dim z As Integer = ranks(ranks.Length - 1) 'get the count of aces
For x As Integer = 1 To z 'loop, turning one ace at a time into a 1
ranks(ranks.Length - 1) -= 1
retval = x + (ranks(ranks.Length - 1) * 11) 'add remaining aces as 11
For y As Integer = 0 To ranks.Length - 2 'get remaining card values
If ranks(y) > 0 Then
If y + 2 >= 10 Then
retval += 10 * ranks(y)
Else
retval += (y + 2) * ranks(y)
End If
End If
Next
If retval <= 21 Then Exit For
Next
Return retval
End Function
-
Feb 21st, 2010, 08:53 AM
#21
Fanatic Member
Re: Poker Hand Evaluator
i am just now trying to do this very same thing, i came on here to see if anyone had done it, but i dont want to just take the code, i want to make my very own one just to see if i can, i have a very interesting approach on it and if any one would be interested i can post my solution when i code it?
I will be using VB6 though because this is my best language, and i have a game engine i have coded years ago already set up.
I started coding this on a ti83 calculator recently and relized that it takes too long to check all the possibilities and shuffle.
Also my game dosent come up with any random numbers i coded an actual shuffler, so its as if you were really shuffling yourself
Software languages known:
Qbasic - TI-Basic - Liberty Basic - Visual Basic 6
Software API's known:
Directx 7 and 8
Internet languages, in the process of learning:
HTML - JAVASCRIPT - PHP - CSS - MYSQL - AJAX
-
Feb 21st, 2010, 12:10 PM
#22
Re: Poker Hand Evaluator
You're in the wrong forum you realize.
-
Feb 21st, 2010, 12:48 PM
#23
Re: Poker Hand Evaluator
 Originally Posted by formlesstree4
You're in the wrong forum you realize.
Agreed. Should be here http://www.vbforums.com/forumdisplay.php?f=1
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|