c# check for a poker straight

南笙酒味 提交于 2019-12-19 06:35:05

问题


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);
}

回答1:


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;
}



回答2:


I have made some small changes to Glubus answer. The code below does the job however you will have to check manually for a wheel (A,1,2,3,4,5) straight.

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

        var ordered = cards.OrderByDescending(a => a.Value).ToList();
        for (var i = 0; i < ordered.Count - 4; i++)
        {
            var skipped = ordered.Skip(i);
            var possibleStraight = skipped.Take(5).ToList();
            if (IsStraight(possibleStraight))
            {
                return true;
            }
        }
        return false;
    }
public bool IsStraight(List<Card> cards)
{
    return cards.GroupBy(card => card.Value).Count() == cards.Count() && cards.Max(card => (int)card.Value) - cards.Min(card => (int)card.Value) == 4;
    }



回答3:


erm,

function bool IsStraight(IEnumerable<int> cards)
{
    var orderedCards = cards.OrderBy(n => n).ToList();
    var test = orderdCards.Zip(orderdCards.Skip(1), (a, b) => b - a);

    var count = 0;
    foreach(var n in test)
    {
        if (n == 1)
        {
            count++;
            if (count == 4)
            {
                return true;
            }
        }
        else
        {
            count = 0;
        }
    }

    return false;
}



回答4:


I cannot think about real one liner, since A can be 1 or 14, but this should be good:

int c = 5; // How many cards straight
bool Ais1 = cards.OrderBy(a => a.Value).Select((i,j) => i.Value-j).Distinct().Skip(1).Count() <= (cards.Count - c);
bool Ais14 = cards.OrderBy(a => (a.Value == 1 ? 14 : a.Value)).Select((i,j) => (i.Value == 1 ? 14 : i.Value)-j).Distinct().Skip(1).Count() <= (cards.Count - c);
return Ais1 || Ais14;

(Updated - thank you Janne, I've fixed the code)



来源:https://stackoverflow.com/questions/39637965/c-sharp-check-for-a-poker-straight

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!