By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
458,107 Members | 1,245 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 458,107 IT Pros & Developers. It's quick & easy.

Trying to get more precise number (Poker Hands Generator)

P: 7
Hello Everyone,

I did a poker program in Java that essencially finds the strenght of a poker hand created Randomly. My program is doing OK...but I'm pretty sure it can be optimised.

This is my results with 1 million hands:



Number of hands generated : 1000000
Straight Flush : 0.0012 % In theory : 0.0012%
Four Of A Kind : 0.017 % In theory : 0.0240%
Full House : 0.1535 % In theory : 0.1441%
Flush : 0.2285 % In theory : 0.1967%
Straight : 0.3104 % In theory : 0.3532%
Three Of A Kind : 2.2372 % In theory : 2.1128%
Deux Pairs : 4.6104 % In theory : 4.759%
Pair : 41.777 % In theory : 42.2569%
Nothing : 50.6648 % In theory : 50.157%

There is big differences between my results and the theory. I thought at first that it was because I didn't used enough hands.

This is my results with 50 million hands:



Number of hands generated : 50000000
Straight Flush : 0.0012 % In theory : 0.0012%
Four Of A Kind : 0.0183 % In theory : 0.0240%
Full House : 0.1489 % In theory : 0.1441%
Flush : 0.2286 % In theory : 0.1967%
Straight : 0.3086 % In theory : 0.3532%
Three Of A Kind : 2.2266 % In theory : 2.1128%
Deux Pairs : 4.6107 % In theory : 4.759%
Pair : 41.7652 % In theory : 42.2569%
Nothing : 50.6918 % In theory : 50.1570%

And again, the numbers are pretty much the same so it means that thereare flaws in my logic. The problem is I can't find those flaws. My question will be about my isFourOfAKind() method because I get approximalety 20% less Four Of A Kind hands then the theory. A pretty good difference in my opinion.

In general, my program is built like this

Card --> suit, strenght.
Hand --> Card1, Card2, Card3, Card4, Card5.

This is a representation of my method (Card1 = the strenght of Card1. In reality Card1 would be replace by Card1.getCardStrenght())

if(Card1 == Card2 && Card1 == Card3 && Card1 == Card4 && Card1 != Card5)
return true
else if(Card1 == Card2 && Card1 == Card3 && Card1 != Card4 && Card1 == Card5)
return true
if(Card1 == Card2 && Card1 != Card3 && Card1 == Card4 && Card1 == Card5)
return true
if(Card1 != Card2 && Card1 == Card3 && Card1 == Card4 && Card1 == Card5)
return true
else
return false

I'm pretty sure this logic is good. The problem is my results tells me that my logic is NOT good. Where is the flaw in that method?

Thanks in advance and pardon me for English mistakes...it isn't my first language

kinghippo423

P.S. I saw lots of poker hands generator like mice that works WAY faster than mine. Is there any website that explain some technics to have a "faster" program? It sucks to wait 1 minute ot generate 1 million hands...I hope I explain that well.
Sep 4 '07 #1
Share this Question
Share on Google+
13 Replies


Ganon11
Expert 2.5K+
P: 3,652
If you have translated your results correctly, then I see a 0.6% difference between your results and theory. It looks like your program is doing an adequate job of randomly generating hands - remember, nothing matches theory in practice.
Sep 4 '07 #2

P: 7
Theory almost never matched in practice.

By doing a test with 50 millions hands, I should have a really accurate result...specialy with isFourOfAKind() because I have only 5 cases (XOOOO, OXOOO, OOXOO, OOOXO, OOOOX).
Sep 4 '07 #3

Expert 10K+
P: 11,448
Card --> suit, strenght.
Hand --> Card1, Card2, Card3, Card4, Card5.

This is a representation of my method (Card1 = the strenght of Card1. In reality Card1 would be replace by Card1.getCardStrenght())

Expand|Select|Wrap|Line Numbers
  1. if(Card1 == Card2 && Card1 == Card3 && Card1 == Card4 && Card1 != Card5)
  2. return true
  3. else if(Card1 == Card2 && Card1 == Card3 && Card1 != Card4 && Card1 == Card5)
  4. return true
  5. if(Card1 == Card2 && Card1 != Card3 && Card1 == Card4 && Card1 == Card5)
  6. return true
  7. if(Card1 != Card2 && Card1 == Card3 && Card1 == Card4 && Card1 == Card5)
  8. return true
  9. else
  10. return false
  11.  
What if a four of a kind are to be found in card#2, card#3, card#4 and card#5?
I'm about sure that the above logic is incomplete.

kind regards,

Jos
Sep 4 '07 #4

Nepomuk
Expert 2.5K+
P: 3,112
What if a four of a kind are to be found in card#2, card#3, card#4 and card#5?
I'm about sure that the above logic is incomplete.
True, you said yourself that there are 5 possibilities, but you only check 4! Try to figure out, which one is missing. ^^

Greetings,
Nepomuk
Sep 4 '07 #5

Expert 10K+
P: 11,448
True, you said yourself that there are 5 possibilities, but you only check 4! Try to figure out, which one is missing. ^^

Greetings,
Nepomuk
Yep, and it statistically answers the question that the four of a kind score is
about 20% too low. Problem solved ;-)

kind regards,

Jos
Sep 4 '07 #6

P: 7
I was probably smooking that day. I correct that really dumb answer and this is my results after 50 millions hands. The results are as bad but reversely:

Nombre de mains généré : 50000000
Straight Flush : 0.0011 % In theory : 0.0012%
Four Of A Kind : 0.0354 % In theory : 0.0240%
Full House : 0.1419 % In theory : 0.1441%
Flush : 0.2264 % In theory : 0.1967%
Straight : 0.3069 % In theory : 0.3532%
Three Of A Kind : 2.1676 % In theory : 2.1128%
Deux Pairs : 4.5608 % In theory : 4.759%
Pair : 41.5571 % In theory : 42.2569%
C'est rien : 51.003 % In theory : 50.1570%

As you can see, now after 50 millions hands the difference between results and theory are at 0.0114%. That's almost 50% more F-O-A-K than theory. Now I know that my logic is correct thanks to all of you. But still, I'm still with that problem.

This is my new question. Throughtout my program, I check the strenght of the hand by checking all the possibilities. For example, for a pair there is 10 possibilities : XXOOO, XOXOO, XOOXO, XOOOX, OXXOO, OXOXO, OXOOX, OOXXO, OOXOX, OOOXX. I double checked my isPair() method and the logic is perfect. But still, I'm almost a 1% off the theory and I'm using 50 millions hands and that'a a lot.

Is it the optimal way to check the strenght of a poker hand. Is there anyone here that used a different approch? I'm not trying to get a easy answer from all of you (because I will probably re-do my progran with piles and other concepts and I learned in the last year) but you open my mind because in my mind, that's the only way to check the strenght of a poker hand...is by checking every possibilities. My method for my isTwoPairs() method is huge because there is 30 way to manipulate XXOOJ (J in that case is a non-full-house card) without duplication.

My method is excellent? Great? Good 'nouf? Please come again?

BTW, the random Java Class is trustable? I'm starting to suspect that something isn't right with that class.

Oh and By the Way again, what is exactly the seed in the Random Class? I randomize the seed for better result but is it a good way to do it? Should I keep the seed fixed?

Thanks you all agai for the advises.
Sep 5 '07 #7

Ganon11
Expert 2.5K+
P: 3,652
Random number generators are, in fact, rarely Random. What they do is reference a very long list of integers that are 'random' - a portion of this list may be:

Expand|Select|Wrap|Line Numbers
  1. ...324845, 348723, 876334, 3984, 4358,...
The seed tells the generator where along the list to begin. If you keep the seed constant, you will be getting the same 'random' number every time, so randomizing the seed is essential.
Sep 5 '07 #8

P: 7
The seed tells the generator where along the list to begin. If you keep the seed constant, you will be getting the same 'random' number every time, so randomizing the seed is essential.
But Randomizing the seed doesn't makes the Random numbers really Random though because Math.Random() will never be "Pure" Random. Am I correct?

P.S. Maybe too much Random in that sentence :)
Sep 5 '07 #9

Expert 10K+
P: 11,448
My method is excellent? Great? Good 'nouf? Please come again?

Thanks you all agai for the advises.
Mwah, I'd call it so-so. I once did it like this: create two char arrays, one for the
ranks (strengths) and one for the suits:

Expand|Select|Wrap|Line Numbers
  1. char[4] suits= new char[4];
  2. char[15] ranks= new char[15];
  3. Arrays.fill(suits, '0');
  4. Arrays.fill(ranks, '0');
  5.  
Note the fifteen elements in the ranks array; the first two elements are unused
because there are no 0 and 1 cards; aces are high (14) and all cards have a
rank equal to their, ahem, rank.

For five cards in a hand update the two arrays:

Expand|Select|Wrap|Line Numbers
  1. for (Card card: hand) {
  2.    suits[card.getSuit()]++;
  3.    ranks[card.getRank()]++;
  4. }
  5.  
... and convert the arrays to Strings:

Expand|Select|Wrap|Line Numbers
  1. String s= new String(suits);
  2. String r= new String(rank);
  3.  
And here comes the fun: use regular expressions for finding the score:
Four of a kind is found as follows:

Expand|Select|Wrap|Line Numbers
  1. boolean fook= r.matches("0*40*");
  2.  
A full house is found like this:
Expand|Select|Wrap|Line Numbers
  1. boolean fh= r.matches("0*20*30*") || r.matches("0*30*20*");
  2.  
Checking whether or not all cards have the same suit is easy too:

Expand|Select|Wrap|Line Numbers
  1. boolean ss= s.matches("0*40*");
  2.  
I hope you get the picture.

kind regards,

Jos
Sep 5 '07 #10

P: 7
And here comes the fun: use regular expressions for finding the score:
Four of a kind is found as follows:

Expand|Select|Wrap|Line Numbers
  1. boolean fook= r.matches("0*40*");
  2.  
A full house is found like this:
Expand|Select|Wrap|Line Numbers
  1. boolean fh= r.matches("0*20*30*") || r.matches("0*30*20*");
  2.  
Checking whether or not all cards have the same suit is easy too:

Expand|Select|Wrap|Line Numbers
  1. boolean ss= s.matches("0*40*");
  2.  
I hope you get the picture.

kind regards,

Jos
I was unterstanding up to this point perfectly. I just want to make use I get it before asking for more explanation.

Let's say my hand is:

Hand (suit - strenght):
Card1 : 2 - 4.
Card1 : 2 - 6.
Card1 : 2 - 8.
Card1 : 2 - 9.
Card1 :2 - 11.

For checking if my hand is a flush, my method should look ike this:

// ss = result of the checking.
// s = the concatenation of the hand information.
isFlush(Card card)
{
boolean result;
if(boolean ss= s.matches("0*0*0*0*0*");
result = true;
else if(boolean ss= s.matches("1*1*1*1*1*");
result = true;
else if(boolean ss= s.matches("2*2*2*2*2*");
result = true;
else if(boolean ss= s.matches("3*3*3*3*3*");
result = true;
else
result = false;

return result;
}

I'm getting it?

If yes, why it's a better way to built the program?
If not, I'll need more specification on the use here of the regular expressions. I'M almost there though it's just still a little fuzzy...
Sep 5 '07 #11

Expert 10K+
P: 11,448
I was unterstanding up to this point perfectly. I just want to make use I get it before asking for more explanation.

Let's say my hand is:

Hand (suit - strenght):
Card1 : 2 - 4.
Card1 : 2 - 6.
Card1 : 2 - 8.
Card1 : 2 - 9.
Card1 :2 - 11.

For checking if my hand is a flush, my method should look ike this:

// ss = result of the checking.
// s = the concatenation of the hand information.
isFlush(Card card)
{
boolean result;
if(boolean ss= s.matches("0*0*0*0*0*");
result = true;
else if(boolean ss= s.matches("1*1*1*1*1*");
result = true;
else if(boolean ss= s.matches("2*2*2*2*2*");
result = true;
else if(boolean ss= s.matches("3*3*3*3*3*");
result = true;
else
result = false;

return result;
}

I'm getting it?

If yes, why it's a better way to built the program?
If not, I'll need more specification on the use here of the regular expressions. I'M almost there though it's just still a little fuzzy...
You must read up on regular expressions. A flush means the cards all have the
same suit, so the suits string matches this: "0*50*" which translates to human
language as zero or more '0's followed by a '5' followed by zero or more '0's.

This regular expresssion matches "5000", "0500", "0050" or "0005". That's the
fun of those regular expressions: let them do the hard work so your code can
be extremely simple.

kind regards,

Jos
Sep 5 '07 #12

Nepomuk
Expert 2.5K+
P: 3,112
You must read up on regular expressions. A flush means the cards all have the
same suit, so the suits string matches this: "0*50*" which translates to human
language as zero or more '0's followed by a '5' followed by zero or more '0's.

This regular expresssion matches "5000", "0500", "0050" or "0005". That's the
fun of those regular expressions: let them do the hard work so your code can
be extremely simple.

kind regards,

Jos
Actually, "0*" could mean one zeros, multiple zeros or no zeros. Therefore the Expression "0*50*" would match "5000" or "0005". What you said was, that "0*" meant zero or more multiple zeros, leaving out the possibility of the empty word.

Greetings,
Nepomuk
Sep 5 '07 #13

Expert 10K+
P: 11,448
Actually, "0*" could mean one zeros, multiple zeros or no zeros. Therefore the Expression "0*50*" would match "5000" or "0005". What you said was, that "0*" meant zero or more multiple zeros, leaving out the possibility of the empty word.

Greetings,
Nepomuk
Nope, "0*" just means zero or more '0's. So the expression matches all the
combinations 5000, 0500, 0050, 0005; give it a try.

kind regards,

Jos
Sep 5 '07 #14

Post your reply

Sign in to post your reply or Sign up for a free account.