Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c# check for a poker straight

Tags:

c#

poker

I am trying to write a poker hand evaluation method in c#. I have managed to do this for every poker hand using linq except a straight. For those that don't play a straight is made up of 5 cards with increments of 1 for each card. Ace can be high or low.

I have created an object called card which has a suit, rank and value (J = 11, Q =12 etc..). My method will be passed a list of this object containing 7 cards (hole cards and the board.)

Another thing to bear in mind is that a straight can only be made if the player has a 5 or 10.

See below my methods for other poker hands and please let me know if you have an idea for the straight method. Pseudo code would be fine also.


public bool CheckPair(List<Card> cards)
{
    //see if exactly 2 cards card the same rank.
    return cards.GroupBy(card => card.Rank).Count(group => group.Count() == 2) == 1;
}

public bool CheckTwoPair(List<Card> cards)
{
    //see if there are 2 lots of exactly 2 cards card the same rank.
    return cards.GroupBy(card => card.Rank).Count(group => group.Count() >= 2) == 2;
}

public bool CheckTrips(List<Card> cards)
{
    //see if exactly 3 cards card the same rank.
    return cards.GroupBy(card => card.Rank).Any(group => group.Count() == 3);
}
public bool CheckStraight(List<Card> cards)
{
    // order by decending to see order
    var cardsInOrder = cards.OrderByDescending(a => a.Value).ToList();
    // check for ace as can be high and low
    if (cardsInOrder.First().Rank == "A")
    {
        // check if straight with ace has has 2 values
        bool highStraight = cards.Where(a => a.Rank == "K" || a.Rank == "Q" || a.Rank == "J" || a.Rank == "10").Count() == 4;
        bool lowStraight = cards.Where(a => a.Rank == "2" || a.Rank == "3" || a.Rank == "4" || a.Rank == "5").Count() == 4;
        // return true if straight with ace
        if (lowStraight == true || highStraight == true)
        {
            return true;
        }
    }
    else
    {
        // check for straight here
        return true;
    }
    // no straight if reached here.
    return false;

}

public bool CheckFlush(List<Card> cards)
{
    //see if 5 or more cards card the same rank.
    return cards.GroupBy(card => card.Suit).Count(group => group.Count() >= 5) == 1;
}

public bool CheckFullHouse(List<Card> cards)
{
    // check if trips and pair is true
    return CheckPair(cards) && CheckTrips(cards);
}
public bool CheckQuads(List<Card> cards)
{
    //see if exactly 4 cards card the same rank.
    return cards.GroupBy(card => card.Rank).Any(group => group.Count() == 4);
}

// need to check same 5 cards
public bool CheckStraightFlush(List<Card> cards)
{
    // check if flush and straight are true.
    return CheckFlush(cards) && CheckStraight(cards);
}
like image 420
Charlie Beesley Avatar asked Sep 22 '16 11:09

Charlie Beesley


1 Answers

This might not be the best performing check, but I'd say it's very readable which is usually a good property.

Just grab 5 cards, skipping cards you've already seen every iteration and check for a straight for each sequence. An ordered sequence is a straight if it does not contain doubles and if the first and last cards difference is 5.

public bool CheckStraight(List<Card> cards)
{
     //maybe check 5 and 10 here first for performance

     var ordered = cards.OrderByDescending(a => a.Value).ToList();
     for(i = 0; i < ordered.Count - 5; i++) {
          var skipped = ordered.Skip(i);
          var possibleStraight = skipped.Take(5);
          if(IsStraight(possibleStraight)) {
               return true;
          }
     }
     return false;
}

public bool IsStraight(List<Card> fiveOrderedCards) {
     var doubles = cards.GroupBy(card => card.Rank).Count(group => group.Count() > 1);
     var inARow = cards[4] - cards[0] = 5; //Ace is 0

     return !doubles && inARow;
}
like image 79
Glubus Avatar answered Oct 23 '22 08:10

Glubus