I want to evaluate Poker Hands an wrote the following Code:
https://dotnetfiddle.net/mxMvq9
Anything wrong / to imporve?
public class Deck
{
private Random rnd;
private List<Card> DeckCards { get; set; }
private int PlayerCount { get; set; }
public Deck(int playerCount)
{
rnd = new Random();
List<Card> result = new List<Card>();
for (int i = 2; i <= 14; i++)
{
result.Add(new Card(i, Suit.Club));
result.Add(new Card(i, Suit.Diamond));
result.Add(new Card(i, Suit.Heart));
result.Add(new Card(i, Suit.Spade));
}
DeckCards = result;
SetCards();
CreatePlayerHands(playerCount);
PlayerCount = playerCount;
}
public void CreatePlayerHands(int count)
{
if (count < 1 || count > 10)
throw new IndexOutOfRangeException();
for (int i = 1; i <= count; i++)
{
SetCards(i);
}
}
public void ShowCards()
{
Console.WriteLine("Flop:");
foreach (Card c in DeckCards.Where(x => x.UsedByPlayerID == 0))
{
c.ConsoleOutput();
}
Console.WriteLine();
for (int i = 1; i <= PlayerCount; i++)
{
HandResult result = GetHandResult(i);
Console.Write("Player #" + i + "\t(" + result.result + " ");
foreach (Card cResult in result.resultCards)
{
cResult.ConsoleOutput();
}
Console.Write(")");
Console.WriteLine();
foreach (Card c in DeckCards.Where(x => x.UsedByPlayerID == i))
{
c.ConsoleOutput();
}
Console.WriteLine();
}
}
private IOrderedEnumerable<Card> GetPlayerSet(int playerID)
{
return DeckCards.Where(x => x.UsedByPlayerID == 0 || x.UsedByPlayerID == playerID).OrderByDescending(x => x.Face);
}
private void SetCards(int? playerID = null)
{
IEnumerable<Card> playerCards = DeckCards.Where(x => !x.UsedByPlayerID.HasValue).OrderBy(x => rnd.Next()).Take(playerID.HasValue ? 2 : 5);
foreach (Card c in playerCards)
{
c.UsedByPlayerID = playerID.HasValue ? playerID : 0;
}
}
public class HandResult
{
public HandResult(IEnumerable<Card> rc, Hand h)
{
result = h;
resultCards = rc;
}
public Hand result { get; set; }
public IEnumerable<Card> resultCards { get; set; }
}
public HandResult GetHandResult(int playerID)
{
IEnumerable<Card> set = GetPlayerSet(playerID).OrderBy(x => x.Face);
return new[] { GetRoyalFlush(set), GetStraightFlush(set), GetFourOfAKind(set), GetFullHouse(set), GetFlush(set), GetStraight(set), GetThreeOfAKind(set), GetTwoPair(set), GetOnePair(set), GetHighCard(set) }.First(x => x != null);
}
private HandResult GetRoyalFlush(IEnumerable<Card> set)
{
HandResult straightflush = GetStraightFlush(set);
if (straightflush != null)
{
return straightflush.resultCards.Any(x => x.Face == 14 && x.Face == 13) ? new HandResult(straightflush.resultCards, Hand.RoyalFlush) : null;
}
return null;
}
private HandResult GetStraightFlush(IEnumerable<Card> set)
{
IEnumerable<Card> flush = set.GroupBy(x => x.Suit).Where(x => x.Count() >= 5).SingleOrDefault() ?? Enumerable.Empty<Card>();
HandResult strightflush = GetStraight(flush);
return strightflush != null ? new HandResult(strightflush.resultCards, Hand.StraightFlush) : null;
}
private HandResult GetFourOfAKind(IEnumerable<Card> set)
{
IEnumerable<Card> fourOfAKind = set.GroupBy(x => x.Face).SingleOrDefault(x => x.Count() >= 4) ?? Enumerable.Empty<Card>();
return fourOfAKind.Any() ? new HandResult(fourOfAKind, Hand.FourOfAKind) : null;
}
private HandResult GetFullHouse(IEnumerable<Card> set)
{
HandResult threeOfAKind = GetThreeOfAKind(set);
if (threeOfAKind != null)
{
IEnumerable<Card> remainingCards = set.Where(x => !threeOfAKind.resultCards.Any(y => y.Face == x.Face && y.Suit == x.Suit));
IEnumerable<Card> highestTwoPair = remainingCards.GroupBy(x => x.Face).Where(x => x.Count() >= 2).OrderByDescending(x => x.Key).FirstOrDefault() ?? Enumerable.Empty<Card>(); ;
if (highestTwoPair.Any())
{
return new HandResult(threeOfAKind.resultCards.Concat(highestTwoPair.Take(2)), Hand.ThreeOfAKind);
}
}
return null;
}
private HandResult GetFlush(IEnumerable<Card> set)
{
IEnumerable<Card> flush = set.GroupBy(x => x.Suit).Where(x => x.Count() >= 5).SelectMany(x => x.OrderByDescending(y => y.Face).Take(5));
return flush.Any() ? new HandResult(flush, Hand.Flush) : null;
}
private HandResult GetThreeOfAKind(IEnumerable<Card> set)
{
IEnumerable<Card> threeOfAKind = set.GroupBy(x => x.Face).OrderByDescending(x => x.Key).FirstOrDefault(x => x.Count() == 3);
return threeOfAKind != null ? new HandResult(threeOfAKind, Hand.ThreeOfAKind) : null;
}
private HandResult GetTwoPair(IEnumerable<Card> set)
{
var pairs = set.GroupBy(x => x.Face).Where(x => x.Count() == 2);
return pairs.Count() >= 2 ? new HandResult(pairs.OrderByDescending(x => x.Key).Take(2).SelectMany(x => x), Hand.TwoPair):null;
}
private HandResult GetOnePair(IEnumerable<Card> set)
{
IEnumerable<Card> onePair = set.GroupBy(x => x.Face).FirstOrDefault(x => x.Count() >= 2) ;
return onePair != null ? new HandResult(onePair, Hand.OnePair) : null;
}
private HandResult GetStraight(IEnumerable<Card> set)
{
if (set.Any())
{
bool isAceStraight = !new List<int>() { 14, 2, 3, 4, 5 }.Except(set.Select(x => x.Face)).Any();
if (isAceStraight)
{
return new HandResult( set.Where(x => new List<int>() { 14, 2, 3, 4, 5 }.Contains(x.Face)).GroupBy(x => x.Face).Select(x => x.First()), Hand.Straight);
}
int? temp = null;
int conseductiveIndex = 0;
for (int i = 0; i < set.Count(); i++)
{
if (temp.HasValue)
{
if (temp != set.ElementAt(i).Face - 1)
{
conseductiveIndex = i;
}
if (i - conseductiveIndex == 4)
{
return new HandResult( set.Skip(conseductiveIndex).Take(5), Hand.Straight);
}
}
temp = set.ElementAt(i).Face;
}
}
return null;
}
private HandResult GetHighCard(IEnumerable<Card> set)
{
return new HandResult(set.OrderByDescending(x => x.Face).Take(5), Hand.HighCard);
}
public enum Hand { RoyalFlush, StraightFlush, FourOfAKind, FullHouse, Flush, Straight, ThreeOfAKind, TwoPair, OnePair, HighCard }
public enum Suit { Heart = '\u2665', Diamond = '\u2666', Spade = '\u2660', Club = '\u2663' }
public class Card
{
public Card(int face, Suit suit)
{
Suit = suit;
Face = face;
}
public Suit Suit { get; set; }
public int Face { get; set; }
public int? UsedByPlayerID { get; set; }
public void ConsoleOutput()
{
Console.OutputEncoding = System.Text.Encoding.UTF8;
Console.BackgroundColor = ConsoleColor.White;
string face = GetFace(Face).PadLeft(2);
Console.ForegroundColor = Suit == Deck.Suit.Diamond || Suit == Deck.Suit.Heart ? ConsoleColor.Red : ConsoleColor.Black;
Console.Write(face + (char)Suit);
Console.ResetColor();
Console.Write(" ");
}
private string GetFace(int face)
{
return face.ToString().Replace("11", "J").Replace("12", "Q").Replace("13", "K").Replace("14", "A");
}
}
}
Replace
s and "LINQ"s) method and the each item of the array declaration inGetHandResult
on a new line to improve readability. You can still edit this before an answer is posted. \$\endgroup\$Random
correctly. I would suggest reading through all 4 parts , ericlippert.com/2019/01/31/fixing-random-part-1 \$\endgroup\$random
part into a answer? \$\endgroup\$