Function to determine if a poker hand is straight?

For my homework, I was assigned a map class that listed types for Rank and Costume. I need to compare two hands in poker (each hand is an ArrayList of 5 cards) and determine the winner.

The isStraight() function really bothers me because I have to start the countdown after Ace. For example,

QUEEN, KING, ACE, TWO, THREE

Still considered direct. What is the best way to code this function?

Here is the code for the numbered Rank / Suit code, if that helps.

 public enum Rank { TWO(2), THREE(3), FOUR(4), FIVE(5), SIX(6), SEVEN(7), EIGHT(8), NINE(9), TEN(10), JACK(11), QUEEN(12), KING(13), ACE(14); private final int points; private Rank(int points) { this.points = points; } public int points() { return this.points; } } public enum Suit { DIAMONDS, CLUBS, HEARTS, SPADES; } 
+6
java performance poker
source share
10 answers

Do you understand that by the rules of any poker game that I have ever played or heard about straight, you can’t wrap it right? Ace can be low [A, 2,3,4,5] or high [10, J, Q, K, A], but it cannot be completed. According to these rules (and not yours), I already implemented something similar. Basically you sort the array and go through it, making sure that the current map is higher than the previous one. In the first iteration, if it's an ace, you explicitly check [A, 2,3,4,5]. If this is you return, and if you do not continue the normal direct logic. That should set you in the right direction.

+9
source share

You can write a fantastic algorithm for returning true, despite the number of possible cards, but if you understand that there are only 10 valid combinations on the sorted hand, you can simply find them:

 2-6, 3-7, 4-8, 5-9, 6-T, 7-J, 8-Q, 9-K, TA, (2-5,A) 
+3
source share

A good approach to resolving hands in poker as a whole is to assign a bit-bit value ((rank-2) * 2) to each card, as well as a bit (suit + 28), (so 2 ​​= 1, 3 = 4, 4 = 16 etc. Up to A = 0x1000000). Then connect all the cards (call this result β€œSum.” Calculate V1 = (Sum and 0x2AAAAAA) β†’ 1, V0 = (Sum and 0x1555555) and V2 = V1 and V0. Also together are the values ​​for the five cards, and calculate V3 = OrValue and 0xF0000000;

  • For a pair, V1 will have one bit, V0 will have several bits, and V2 will be zero.
  • For two pairs, V1 will have two bits, and V2 will be zero.
  • For the three options, V1 will have one bit, and V2 will be equal to V1.
  • For a straight line, V0 will be either 0x1000055, or power-of-two, a multiple of 0x155.
  • For a flash, V2 will have exactly one bit.
  • For a full house, V1 will have two bits, and V2 will be non-zero.
  • For the four options, V1 will be v0 twice, both of which have one bit, or V0 will have exactly two bits, and V1 will be zero.
  • For a straight flush, the conditions for direct and flush will be met.

These tests, necessary for this approach, should be quickly implemented with minimal branching.

+3
source share

Since there are only 5 cards in the list, you can sort them and determine the difference between two consecutive cards. If there is an ace in it, you should also consider it a low card. if all the differences are 1 (or -1, depending on the sort order), you have a straight line.

+2
source share

I would say that given this definition of RANK, these lines can only start with max ACE.points () - 4.

So, if you sort your hand, and the lowest RANK is> ACE.points () - 4, then you cannot have a straight line, otherwise you simply iterate over your hand to see that each card has a previous RANK + 1.

If the ACE can be high or low, then go to what the SHS replied.

0
source share

With an inner loop, this is pretty trivial, the task would be to do this without an inner loop ...

It also depends on whether you understood that your teacher or your teacher misunderstood (or distorted) the rules of the game.

I think that I will be tempted to simply create an array [2..14] and place the cards in a place corresponding to their rank. If you hit a duplicate, that is not the case, and when you are done, you should have 8 spaces in a row. If you have less than 8 spaces in a row, this is not direct.

All other solutions that may arise require an inner loop, and inner loops are one of those messy programming tasks that you need to avoid whenever possible, if you ever become a respectable programmer.

edit: In addition, if you misunderstood the teacher and the only condition for wrapping is "10, j, q, k, a" (as in the real rules), then you will need an additional test, which, if all 2, 13 and 14, is also failure (2-ak wraparound).

(Edited again to replace 1 for Ace with 14 after re-reading the question)

0
source share

I don’t use the enumeration much, I prefer named constants, but I assume that the transition from "ACE" to "14" is trivial

I'm too lazy to write real Java code (next to you you really need to do your homework ^^)

 check if the list has 5 cards convert card names to a card number list named array sort the list array for i=1 to 4 if not (array[i] + 1) % 13 == (array[i+1]) % 13 then it is not a straight 

The% operator is called modulo so (15% 13) == 2 I use this operator whenever I encounter a "wrap" problem

Edit: after reading your question again, my solution cannot work out of the box. You must change the order of listing so that TWO == 0

0
source share

I recommend using a bit vector to represent maps. This avoids sorting. You can add an ace twice (once every 1 time as king), or you can start a situation in a special case by checking if the ace bit is set before checking if 2 is set). If speed matters, you can build a large lookup table. This approach also allows you to clean the scales to find the rest of the hands (flushes, 2 pairs, full houses, trips, etc.). It also makes it easy to see if a given line is higher than another. And it automatically expands to 7 card appraisers

In pseudo-code, it looks something like this for a very general case (you can have any number of cards. It returns the first one in a row)

  long cardBitMask for each card in hand setBit in cardBitMask hearts = mask(cardBitMask) diamonds = mask(cardBitMask) clubs = mask(cardBitMask) spades = mask(cardBitMask) // find straight uniqueCards = hearts|diamonds|clubs|spades int cardsInaRow = 0 if uniqueCards&AceCardMask: cardsInaRow = 1 for card = 2...King if uniqueCards&(1<<card) cardsInARow++ else if cardsInARow == 5 break cardsInARow = 0 if cardsInARow==5: return true return false 
0
source share

Add all ranks to the list twice. Then, to check if the hand is straight, sort the hand by rank, and then check if the hand is a sublist of this list.

0
source share

you can write a class that converts each map to a specific map value

Joker = 11 Queen = 12 King = 13 Ace = 0 or 14

he will greatly simplify the work with cards and is looking for possible hands.

-2
source share

All Articles