0

I am creating a poker game - Texas Holdem (5 cards on the table and 2 cards for myself).

I've already created flush, straight and straight flush functions and I got stuck on evaluating if the hand has a:
1. Four of a kind
2. Three of a kind
3. Full house
4. Two pairs
5. One pair

I believe I can write one function for all of the above, that will return a corresponding string.

I have created a list that holds list of Cards (7 cards) Class Card has a property cardNumber of Integer type (Ace = 1, Two = 2, Three = 3 etc)

Here is my function:

Public Shared Function ofAKind(hand As List(Of Card)) As String
    Dim result As String = ""
    Dim counter As Integer
    Dim IntegerList As New List(Of Integer)
    'creating a list of integers that are representing faces of cards
    Do
        IntegerList.Add(hand.Item(counter).cardNumber)
        counter += 1
    Loop Until counter = hand.Count

    Dim groupedIntegers = From Int In IntegerList
                          Group By Int
                              Into grouping = Group, Count()

    'and here is my problem: how can I make such a grouping? below is just pseudocode.
    'When using a debugger, I see that it groups them well. It is just that I do not know
    'how to use LINQ to extract that grouping into the below if statement and get a corresponding string. 


    'if grouping = 4 Then
    'result = "Four of a kind"
    'if grouping = 3 andAlso grouping = 2 Then
    'result = "Full House"
    'if grouping = 2 andAlso grouping = 2 Then
    'result = "Two Pairs"
    'if grouping = 2 Then
    'result = "Pair"


    Return result
End Function
Herb
  • 636
  • 1
  • 15
  • 29
  • You can rank the entire hand in one method using 2-3 linq queries - you sort of have to since you want to test in poker hand order. Returning a string is not enough info if you are going to compare hands. If 2 hands have 1 pair, what the pairs are determines who beats whom. Especially with HoldEm you also have to be able to break ties with the high cards (Pair Qs, Ace hi vs Pair Queens 9 hi). – Ňɏssa Pøngjǣrdenlarp Feb 04 '17 at 16:11
  • Plutonix. Thanks for your comment. What you've said makes perfect sense and I totally agree. I should have mentioned from the beginning that I am just trying to build a simple version of the game. And for this particular purpose It would be good enough for me to know my hand, and not compare it to any other hands. – Nurgazy Budaichiev Feb 04 '17 at 17:12
  • how are the cards stored? how is card class and is it 1 to 13? – Ashkan Mobayen Khiabani Feb 04 '17 at 18:44
  • cards are stored in the list. Cards have property cardNumber. Ace = 0, Two = 1, Three = 2... Queen = 11, King = 12. With Do Loop I have created a list of Integers to hold those values. with LINQ I went through the list and grouped by the value. – Nurgazy Budaichiev Feb 04 '17 at 20:38
  • You need an actual card class ( `{Rank, Suit, Value}` ) the value is not enough otherwise you wont be able to determine flushes. You might also want to start with ranking 5 card hands first since a 7 card hand adds complexity to finding straights and determining a straight flush – Ňɏssa Pøngjǣrdenlarp Feb 04 '17 at 23:14
  • You should read [Ask] and take the [Tour]. Some people are not inclined to post an answer until/unless you know how SO works. – Ňɏssa Pøngjǣrdenlarp Feb 05 '17 at 16:44
  • Yes, I have class called Card, which has faces, suits and cardNumber properties. I already created Flush, Street and Street Flush methods. Now I just need to be able to write if condition, as mentioned in my question for the LINQ aggregation. – Nurgazy Budaichiev Feb 05 '17 at 23:45
  • thanks Plutonix, I will read How to Ask again and make sure my questions are clearer next time – Nurgazy Budaichiev Feb 06 '17 at 00:55

2 Answers2

0

I figured it out. I am sure it can be done in a cleaner way, but it worked for me. At this phase of my programming discovery - this is a next milestone achieved. Thanks to Plutonix. Appreciate it.

Public Function ofAKind(IntegerList As List(Of Integer)) As String Dim result As String = "YES" Dim groupedIntegerList As New List(Of Integer)

    Dim groupedIntegers = From Int In IntegerList
                          Group By Int
                          Into LOL = Group, Count()

    'creating another list (I am sure there is a cleaner way, but I don't know it yet)
    For Each e In groupedIntegers
        groupedIntegerList.Add(e.Count)
    Next

    If groupedIntegerList.Contains(3) And groupedIntegerList.Contains(2) Then
        result = "Fullhouse!"
    ElseIf groupedIntegerList.Contains(4) Then
        result = "Four of a kind!"
    ElseIf groupedIntegerList.Contains(3) Then
        result = "Three of a kind"
    ElseIf groupedIntegerList.Contains(2) Then
        result = "Pair!"
    End If

    'ugly way to search for two pairs (but it works)

    If result = "Pair!" Then
        Dim searchingForTwoPairs = From int In groupedIntegerList
                                   Where int > 1
                                   Group By int
                                       Into LOL2 = Group, Count()

        Dim twoPairsList As New List(Of Integer)
        For Each e In searchingForTwoPairs
            twoPairsList.Add(e.Count)
        Next

        If twoPairsList.Contains(2) Or twoPairsList.Contains(3) Then
            result = "Two pairs!"
        End If
    End If

    Return result
End Function
0

For the lack of being able to comment.

Possibly String.Concat all of the card Values together (with whitespace in-between each) and use a Regex.Matches(...) with match code "\d" to match the Numbers

Then Array.ForEach(...) for the Groups() with an in-line If[...] to count the occurrences in each group and test if it has particular combinations of matches.


It may be a little tedious, and a long in-line Linq, but just a thought :p

Sir Kamui
  • 62
  • 6