【算法】用c#实现德州扑克卡牌游戏规则

这篇具有很好参考价值的文章主要介绍了【算法】用c#实现德州扑克卡牌游戏规则。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

德州扑克是一种牌类游戏,可多人参与,它的玩法是,玩家每人发两张底牌,桌面依次发5张公共牌,玩家用自己的两张底牌和5张公共牌自由组合,按大小决定胜负。

使用c#完成功能Hand()以返回手牌类型和按重要性递减顺序排列的等级列表,用于与同类型的其他手牌进行比较,即最佳手牌。

可能的手牌按价值降序排列:

同花顺(同一套衣服的连续五个等级)。级别越高越好。

四张(四张等级相同的牌)。平局决胜先是等级,然后是剩余牌的等级。

满座(三张等级相同的牌,两张等级相同)。决胜局首先是三张牌的等级,然后是一对牌的等级。

同花顺(五张同花色的牌)。从高到低,级别越高越好。

直(连续五个等级)。级别越高越好。

三张牌(三张等级相同的牌)。决胜局是三张牌中排名第一的,然后是其他排名最高的,然后才是其他排名第二的。

两对(两张相同等级的牌,两张不同等级的牌)。决胜局首先是高牌对的等级,然后是低牌对的级别,然后是剩余牌的等级。

配对(两张等级相同的牌)。平局决胜是先是两张牌的等级,然后是其他三张牌的级别。


算法实现:

  1 using System;
  2 using System.Collections.Generic;
  3 using System.Linq;
  4 using System.Text;
  5 
  6 public static class Edm
  7     {
  8         public static (string type, string[] ranks) Hand(string[] holeCards, string[] communityCards)
  9         {
 10             Card[] allCards = holeCards.Concat(communityCards).Select( x=> new Card(x)).OrderByDescending(card =>card.value).ToArray();
 11             
 12             var rulesChain = createChainOfCommand();
 13             var powerhands = rulesChain.Execute(allCards);
 14             return (powerhands.Item1, getReturnlist(allCards, powerhands.Item2));
 15 
 16         }
 17         public static string[] getReturnlist(Card[] cards, Card[] powerhand)
 18         {
 19             var remainderHand = cards.Where(x => !powerhand.Any(y => y.Equals(x))).Take(5-powerhand.Length);
 20             var result = powerhand.Select(x =>x.number).Distinct().Concat(remainderHand.Select(x=>x.number)).Take(5).Select(x => x.ToString()).ToArray();
 21             return result;
 22         }
 23 
 24         public static Rule createChainOfCommand()
 25         {
 26             Rule straightFlush = new StraightFlushRule();
 27             Rule fourOfAKind = new FourOfAKindRule();
 28             Rule fullHouse = new FullHouseRule();
 29             Rule flush = new FlushRule();
 30             Rule straight = new StraightRule();
 31             Rule threeOfAKind = new ThreeOfAKindRule();
 32             Rule pairTwoPair = new PairTwoPairRule();
 33             straightFlush.SetSuccessor(fourOfAKind);
 34             fourOfAKind.SetSuccessor(fullHouse);
 35             fullHouse.SetSuccessor(flush);
 36             flush.SetSuccessor(straight);
 37             straight.SetSuccessor(threeOfAKind);
 38             threeOfAKind.SetSuccessor(pairTwoPair);
 39             return straightFlush;
 40         }
 41     }
 42     public abstract class Rule
 43     {
 44         private Rule nextRule;
 45         public void SetSuccessor(Rule next)
 46         {
 47             nextRule = next;
 48         }
 49         public virtual (string, Card[]) Execute(Card[] cards)
 50         {
 51             if (nextRule != null)
 52             {
 53                 return nextRule.Execute(cards);
 54             }
 55             return ("nothing", cards.Take(5).ToArray());
 56         }
 57     }
 58 
 59     public class PairTwoPairRule : Rule
 60     {
 61         public override (string, Card[]) Execute(Card[] cards)
 62         {
 63             var pairs = cards.GroupBy(x => x.number).Where(g => g.Count() >= 2).SelectMany(card => card).ToList();
 64             if (pairs.Any())
 65             {
 66                 if(pairs.Count() >= 4)
 67                 {
 68                     return ("two pair", pairs.Take(4).ToArray());
 69                 }
 70                 return ("pair", pairs.Take(2).ToArray());
 71             }
 72             return base.Execute(cards);
 73         }
 74     }
 75     public class ThreeOfAKindRule : Rule
 76     {
 77         public override (string, Card[]) Execute(Card[] cards)
 78         {
 79             var triple = cards.GroupBy(x => x.number).Where(g => g.Count() >= 3).SelectMany(card => card).ToList();
 80             if (triple.Any())
 81             {
 82                 return ("three-of-a-kind", triple.Take(3).ToArray());
 83             }
 84             return base.Execute(cards);
 85         }
 86     }
 87     public class StraightRule : Rule
 88     {
 89         public override (string, Card[]) Execute(Card[] cards)
 90         {
 91             for (int i = 0; i < cards.Length - 4; i++)
 92             {
 93                 List<Card> rtnList = new List<Card>() { cards[i] }; //  "A♥","J♦","10♥" "9♠", "9♥", "8♠", "7♣"
 94                 int counter = 4; 
 95                 int j = i; 
 96                 while (counter >= 0 && j < cards.Length - 1)
 97                 {
 98                     if (cards[j].value - cards[j + 1].value == 1)
 99                     {
100                         rtnList.Add(cards[j + 1]);
101 
102                         if (rtnList.Count() == 5)
103                         {
104                             return ("straight", rtnList.ToArray());
105                         }
106                         counter--;
107                         j++;
108                     }
109                     else if (cards[j].value - cards[j + 1].value == 0)
110                     {
111                         j++;
112                     }
113                     else
114                     {
115                         break;
116                     }
117                 }
118             }
119             return base.Execute(cards);
120         }
121     }
122     public class FlushRule : Rule
123     {
124         public override (string, Card[]) Execute(Card[] cards)
125         {
126             var flush = cards.GroupBy(x => x.suit).Where(g => g.Count() >= 5).SelectMany(card => card).ToList(); 
127             if (flush.Any())
128             {
129                 return ("flush", flush.ToArray());
130             }
131             return base.Execute(cards);
132         }
133     }
134 
135     public class FullHouseRule : Rule
136     {
137         public override (string, Card[]) Execute(Card[] cards)
138         {
139             var triple = new ThreeOfAKindRule();
140             var pair = new PairTwoPairRule();
141 
142             var powerhands = triple.Execute(cards);
143             if (!powerhands.Item1.Equals("nothing"))
144             {
145                 if (powerhands.Item2.Count() == 6) // then 2 three of a kind found
146                 {
147                     return ("full house", powerhands.Item2.Take(5).ToArray());
148                 }
149                 var remainderHand = cards.Where(x => !powerhands.Item2.Any(y => y.Equals(x))).ToArray();
150                 var pairHand = pair.Execute(remainderHand);
151                 if (!pairHand.Item1.Equals("nothing"))
152                 {
153                     var fullhouseHand = powerhands.Item2.Concat(pairHand.Item2.Take(2)).ToArray();
154                     return ("full house", fullhouseHand.Take(5).ToArray());
155                 }
156             }
157             return base.Execute(cards);
158         }
159     }
160     public class FourOfAKindRule : Rule
161     {
162         public override (string, Card[]) Execute(Card[] cards)
163         {
164             var fourOfAKind = cards.GroupBy(x => x.number).Where(g => g.Count() >= 4).SelectMany(card => card).ToList();
165             if (fourOfAKind.Any())
166             {
167                 return ("four-of-a-kind", fourOfAKind.Take(4).ToArray());
168             }
169             return base.Execute(cards);
170         }
171     }
172     public class StraightFlushRule : Rule
173     {
174         public override (string, Card[]) Execute(Card[] cards)
175         {
176             var flushRule = new FlushRule();
177             var straightRule = new StraightRule();
178             var flushHand = flushRule.Execute(cards);
179             var straightHand = straightRule.Execute(flushHand.Item2);
180             if (!straightHand.Item1.Equals("nothing") && !flushHand.Item1.Equals("nothing"))
181             {
182                 return ("straight-flush", straightHand.Item2.Take(5).ToArray());
183             }
184             return base.Execute(cards);
185         }
186     }
187 
188     public class Card{
189         public String number { get; set; }
190         public int value { get; set; }
191         public char suit { get; set; }
192         public Dictionary<char, int> mapping = new Dictionary<char, int>()
193         {
194             { 'A',14 },
195             { 'K',13 },
196             { 'Q',12 },
197             { 'J',11 },
198             { '1', 10}
199         };
200         public Card(String s)
201         {
202             number = (s[0] == '1')? "10": Char.ToString(s[0]);
203             value = mapping.ContainsKey(s[0])? mapping[s[0]]: (int) Char.GetNumericValue(s[0]);
204             suit = s[s.Length-1];
205         }
206         public override string ToString()
207         {
208             return number.ToString();
209         }
210 
211         public bool equals(Card s)
212         {
213             return this.value == s.value && this.suit.Equals(s.suit);
214         }
215     }

测试用例:

  1 namespace Solution
  2 {
  3     using NUnit.Framework;
  4     using System;
  5     using System.Collections.Generic;
  6     using System.Diagnostics;
  7     using System.Linq;
  8     using System.Text;
  9   
 10     [TestFixture]
 11     public class SolutionTest
 12     {
 13         #region Sample Tests
 14     
 15         [Test(Description = "Fixed Tests")]
 16         public void FixedTests()
 17         {
 18             SampleTest(("nothing",         new[] { "A", "K", "Q", "J", "9" }),  new[] { "K♠", "A♦" },  new[] { "J♣", "Q♥", "9♥", "2♥", "3♦" });
 19             SampleTest(("pair",            new[] { "Q", "K", "J", "9" }),       new[] { "K♠", "Q♦" },  new[] { "J♣", "Q♥", "9♥", "2♥", "3♦" });
 20             SampleTest(("two pair",        new[] { "K", "J", "9" }),            new[] { "K♠", "J♦" },  new[] { "J♣", "K♥", "9♥", "2♥", "3♦" });
 21             SampleTest(("three-of-a-kind", new[] { "Q", "J", "9" }),            new[] { "4♠", "9♦" },  new[] { "J♣", "Q♥", "Q♠", "2♥", "Q♦" });
 22             SampleTest(("straight",        new[] { "K", "Q", "J", "10", "9" }), new[] { "Q♠", "2♦" },  new[] { "J♣", "10♥", "9♥", "K♥", "3♦" });
 23             SampleTest(("flush",           new[] { "Q", "J", "10", "5", "3" }), new[] { "A♠", "K♦" },  new[] { "J♥", "5♥", "10♥", "Q♥", "3♥" });
 24             SampleTest(("full house",      new[] { "A", "K" }),                 new[] { "A♠", "A♦" },  new[] { "K♣", "K♥", "A♥", "Q♥", "3♦" });
 25             SampleTest(("four-of-a-kind",  new[] { "2", "3" }),                 new[] { "2♠", "3♦" },  new[] { "2♣", "2♥", "3♠", "3♥", "2♦" });
 26             SampleTest(("straight-flush",  new[] { "J", "10", "9", "8", "7" }), new[] { "8♠", "6♠" },  new[] { "7♠", "5♠", "9♠", "J♠", "10♠" });
 27         }
 28     
 29         private static void SampleTest((string type, string[] ranks) expected, string[] holeCards, string[] communityCards)
 30         {
 31             var actual = Act(holeCards, communityCards);
 32             Verify(expected, actual, holeCards, communityCards);
 33         }
 34     
 35         #endregion
 36     
 37         private static readonly StringBuilder template = new StringBuilder();
 38         private static readonly StringBuilder buffer = new StringBuilder();
 39         private static readonly string[] ranks = new string[] { "A", "K", "Q", "J", "10", "9", "8", "7", "6", "5", "4", "3", "2" };
 40         private static readonly string[] types = new string[] { "straight-flush", "four-of-a-kind", "full house", "flush", "straight", "three-of-a-kind", "two pair", "pair", "nothing" };
 41         private static readonly Dictionary<string, int> ranksLookup = ranks.ToDictionary(x => x, x => Array.FindIndex(ranks, y => y == x));
 42         private static string Show(string str) => $@"""{str}""";
 43         private static string ShowSeq(IEnumerable<string> seq) => $"[{string.Join(", ", seq.Select(Show))}]";
 44         private static (string type, string[] ranks) Act(string[] holeCards, string[] communityCards) => Edm.Hand(holeCards.Select(m=>m).ToArray(), communityCards.Select(m=>m).ToArray());
 45     
 46         private static string Error(string message)
 47         {
 48             buffer.Clear();
 49             buffer.Append(template.ToString());
 50             buffer.AppendLine($"Error: {message}");
 51             return buffer.ToString();
 52         }
 53     
 54         private static void Verify(
 55             (string type, string[] ranks) expected, (string type, string[] ranks) actual, string[] holeCards, string[] communityCards)
 56         {
 57             Debug.Assert(holeCards.Concat(communityCards).Distinct().Count() == 7, "Invalid input");
 58             template.Clear();
 59             template.AppendLine($"\tHole cards: {ShowSeq(holeCards)}");
 60             template.AppendLine($"\tCommunity cards: {ShowSeq(communityCards)}");
 61             template.AppendLine($"Expected: (type: {Show(expected.type)}, ranks: {ShowSeq(expected.ranks)})");
 62             Assert.IsNotNull(actual.type, Error("Type must not be null"));
 63             Assert.IsNotNull(actual.ranks, Error("Ranks must not be null"));
 64             template.AppendLine($"Actual: (type: {Show(actual.type)}, ranks: {ShowSeq(actual.ranks)})");
 65             Assert.IsTrue(types.Any(x => string.Equals(x, actual.type)), 
 66                 Error($"{Show(actual.type)} is not valid, valid options are: {ShowSeq(types)}"));
 67             Assert.AreEqual(expected.type, actual.type, Error("Type is incorrect"));
 68             Assert.AreEqual(expected.ranks.Length, actual.ranks.Length, Error("Number of ranks is incorrect"));
 69             for (var i = 0; i < expected.ranks.Length; i++)
 70                 Assert.IsTrue(ranks.Any(x => string.Equals(x, actual.ranks[i])),
 71                     Error($"{Show(actual.ranks[i])} is not valid, valid options are: {ShowSeq(ranks)}"));
 72             for (var i = 0; i < expected.ranks.Length; i++) 
 73                 Assert.AreEqual(expected.ranks[i], actual.ranks[i], Error($"Rank at position {i} is incorrect"));
 74         }
 75     
 76         #region Test Cases
 77     
 78         private static readonly string[] suits = new string[] { "", "", "", "" };
 79         private static Dictionary<string, int> stats = new Dictionary<string, int>();
 80     
 81         [Test(Description = "Fixed Edge Case Tests")]
 82         public void FixedEdgeCaseTests()
 83         {
 84             // ace low straight invalidated 
 85             SampleTest(("nothing", new[] { "A", "8", "7", "5", "4" }), new[] { "A♠", "2♦" }, new[] { "3♣", "4♥", "5♥", "7♥", "8♦" });
 86             // non straight around
 87             SampleTest(("nothing", new[] { "A", "K", "8", "7", "4" }), new[] { "A♠", "K♦" }, new[] { "3♣", "4♥", "2♥", "7♥", "8♦" });
 88           
 89             // pair on board
 90             SampleTest(("pair", new[] { "4", "A", "9", "7" }), new[] { "A♠", "2♦" }, new[] { "3♣", "4♥", "9♥", "7♥", "4♦" });
 91             // pair made with 1 hole card
 92             SampleTest(("pair", new[] { "4", "A", "10", "9" }), new[] { "A♠", "4♦" }, new[] { "3♣", "4♥", "9♥", "7♥", "10♦" });
 93             // pair made with 2 hole cards
 94             SampleTest(("pair", new[] { "4", "A", "10", "9" }), new[] { "4♠", "4♦" }, new[] { "3♣", "A♥", "9♥", "7♥", "10♦" });
 95 
 96             // two pair on board
 97             SampleTest(("two pair", new[] { "Q", "2", "K" }), new[] { "K♠", "J♦" }, new[] { "Q♣", "Q♥", "9♥", "2♥", "2♦" });
 98             // two pair made with 1 hole card and 1 pair on board
 99             SampleTest(("two pair", new[] { "Q", "2", "K" }), new[] { "K♠", "Q♦" }, new[] { "J♣", "Q♥", "9♥", "2♥", "2♦" });
100             // two pair made with 2 hole cards
101             SampleTest(("two pair", new[] { "Q", "2", "K" }), new[] { "2♠", "Q♦" }, new[] { "J♣", "Q♥", "9♥", "2♥", "K♦" });
102             // two pair made with pair in hole cards and 1 pair on board
103             SampleTest(("two pair", new[] { "Q", "2", "K" }), new[] { "Q♠", "Q♦" }, new[] { "K♣", "J♥", "9♥", "2♥", "2♦" });
104             // two pair made with 2 hole cards, invalidating a 3th pair on board
105             SampleTest(("two pair", new[] { "K", "J", "9" }), new[] { "K♠", "J♦" }, new[] { "J♣", "K♥", "9♥", "2♥", "2♦" });
106 
107             // three-of-a-kind on board
108             SampleTest(("three-of-a-kind", new[] { "Q", "K", "J" }), new[] { "K♠", "J♦" }, new[] { "Q♣", "Q♥", "9♥", "2♥", "Q♦" });
109             // three-of-a-kind made with 1 hole card and 1 pair on board
110             SampleTest(("three-of-a-kind", new[] { "Q", "K", "J" }), new[] { "K♠", "Q♦" }, new[] { "Q♣", "Q♥", "9♥", "2♥", "J♦" });
111             // three-of-a-kind made with 2 hole cards
112             SampleTest(("three-of-a-kind", new[] { "Q", "K", "J" }), new[] { "Q♣", "Q♦" }, new[] { "K♠", "Q♥", "9♥", "2♥", "J♦" });
113 
114             // board straight cancels out pocket aces
115             SampleTest(("straight", new[] { "A", "K", "Q", "J", "10" }), new[] { "A♥", "A♠" }, new[] { "A♣", "K♥", "Q♥", "J♥", "10♦" });
116             // super straight
117             SampleTest(("straight", new[] { "A", "K", "Q", "J", "10" }), new[] { "A♠", "Q♥" }, new[] { "K♥", "10♠", "J♠", "9♠", "8♦" });
118             // high straight
119             SampleTest(("straight", new[] { "7", "6", "5", "4", "3" }), new[] { "6♠", "7♥" }, new[] { "3♥", "4♠", "5♠", "10♠", "10♦" });
120             // low straight
121             SampleTest(("straight", new[] { "6", "5", "4", "3", "2" }), new[] { "2♠", "3♥" }, new[] { "4♥", "5♠", "6♠", "10♠", "10♦" });
122             // outside straight
123             SampleTest(("straight", new[] { "6", "5", "4", "3", "2" }), new[] { "2♠", "6♥" }, new[] { "4♥", "5♠", "3♠", "10♠", "10♦" });
124             // inside straight
125             SampleTest(("straight", new[] { "6", "5", "4", "3", "2" }), new[] { "4♠", "3♥" }, new[] { "2♥", "5♠", "6♠", "10♠", "10♦" });
126             // interspersed straight
127             SampleTest(("straight", new[] { "6", "5", "4", "3", "2" }), new[] { "4♠", "2♥" }, new[] { "3♥", "5♠", "6♠", "10♠", "10♦" });
128 
129             // seven deuce runner runner
130             SampleTest(("full house", new[] { "2", "7" }), new[] { "7♥", "2♠" }, new[] { "A♣", "K♥", "2♦", "7♣", "2♥" });
131             // full house with 2 pairs on board where pockets make the triple
132             SampleTest(("full house", new[] { "A", "K" }), new[] { "A♠", "A♦" }, new[] { "K♣", "K♥", "A♥", "Q♥", "Q♦" });
133             // full house with 1 pair on board where pockets make the triple
134             SampleTest(("full house", new[] { "A", "K" }), new[] { "A♠", "A♦" }, new[] { "K♣", "K♥", "A♥", "J♥", "Q♦" });
135             // full house with 1 hole card making triple and other making pair
136             SampleTest(("full house", new[] { "K", "A" }), new[] { "A♠", "K♦" }, new[] { "K♣", "K♥", "A♥", "J♥", "Q♦" });
137             // full house with better triple than board
138             SampleTest(("full house", new[] { "A", "K" }), new[] { "A♠", "A♦" }, new[] { "K♣", "K♥", "A♥", "Q♥", "K♦" });
139 
140             // flush and straight combo
141             SampleTest(("flush", new[] { "J", "10", "9", "8", "6" }), new[] { "8♠", "6♠" }, new[] { "7♦", "5♠", "9♠", "J♠", "10♠" });
142             // power flush
143             SampleTest(("flush", new[] { "A", "K", "Q", "J", "9" }), new[] { "A♠", "Q♠" }, new[] { "K♠", "4♠", "J♠", "9♠", "3♠" });
144 
145             // four-of-a-kind on board
146             SampleTest(("four-of-a-kind", new[] { "A", "K" }), new[] { "K♠", "9♥" }, new[] { "A♥", "A♣", "A♠", "A♦", "3♥" });
147             // four-of-a-kind with 1 hole card and triple on board
148             SampleTest(("four-of-a-kind", new[] { "A", "K" }), new[] { "K♠", "A♥" }, new[] { "9♥", "A♣", "A♠", "A♦", "3♥" });
149             // carré
150             SampleTest(("four-of-a-kind", new[] { "A", "K" }), new[] { "A♠", "A♦" }, new[] { "A♥", "A♣", "K♠", "9♥", "3♥" });
151 
152             // royal flush
153             SampleTest(("straight-flush", new[] { "A", "K", "Q", "J", "10" }), new[] { "A♠", "Q♠" }, new[] { "K♠", "10♠", "J♠", "9♠", "3♦" });
154           
155             // regression tests
156             SampleTest(("straight", new[] { "6", "5", "4", "3", "2" }), new[] { "3♠", "4♥" }, new[] { "6♣", "5♠", "2♣", "2♦", "3♦" });
157             SampleTest(("straight", new[] { "10", "9", "8", "7", "6" }), new[] { "6♣", "10♠" }, new[] { "9♠", "8♦", "5♦", "7♥", "9♦" });
158             SampleTest(("straight", new[] { "K", "Q", "J", "10", "9" }), new[] { "2♦", "J♦" }, new[] { "Q♥", "9♠", "K♥", "10♥", "J♥" });
159         }
160     
161         [Test(Description = "Random Tests (Batch #1)")]
162         public void RandomBatch1Tests()
163         {
164             var rand = new Random((int)(DateTime.Now.Ticks % int.MaxValue));
165             var bulkSize = 500;
166             for (var i = 0; i < bulkSize; i++)
167             {
168                 var hand = GenerateRandomHand(rand);
169                 var holeCards = hand.Take(2).ToArray();
170                 var communityCards = hand.Skip(2).ToArray();
171                 Test(holeCards, communityCards);
172             }
173         }
174 
175         [Test(Description = "Random Tests (Batch #2)")]
176         public void RandomBatch2Tests()
177         {
178             var rand = new Random((int)(DateTime.Now.Ticks % int.MaxValue));
179             var bulkSize = 500;
180             for (var i = 0; i < bulkSize; i++)
181             {
182                 do
183                 {
184                     var hand = GenerateRandomHand(rand);
185                     var holeCards = hand.Take(2).ToArray();
186                     var communityCards = hand.Skip(2).ToArray();
187                     var expected = Expect(holeCards, communityCards);
188 
189                     if (new[] { "nothing", "pair", "two pair", "three-of-a-kind" }.Contains(expected.type))
190                     {
191                         continue;
192                     }
193                     else
194                     {
195                         Test(holeCards, communityCards);
196                         break;
197                     }
198                 } while (true);
199             }
200         }
201 
202         [Test(Description = "Random Tests (Batch #3)")]
203         public void RandomBatch3Tests()
204         {
205             var rand = new Random((int)(DateTime.Now.Ticks % int.MaxValue));
206             var hands = new List<string[]>();
207             var batchSize = 100;
208             for (var i = 0; i < batchSize; i++) hands.Add(GenerateStraightFlush(rand));
209             for (var i = 0; i < batchSize; i++) hands.Add(GenerateFourOfAKind(rand));
210             for (var i = 0; i < batchSize; i++) hands.Add(GenerateFullHouse(rand));
211             for (var i = 0; i < batchSize; i++) hands.Add(GenerateFlush(rand));
212             for (var i = 0; i < batchSize; i++) hands.Add(GenerateStraight(rand));
213             hands = hands.Select(x => x.OrderBy(y => rand.Next()).ToArray()).OrderBy(x => rand.Next()).ToList();
214             foreach (var hand in hands)
215             {
216                 var holeCards = hand.Take(2).ToArray();
217                 var communityCards = hand.Skip(2).ToArray();
218                 Test(holeCards, communityCards);
219             }
220         }
221 
222         private static Dictionary<int, (string rank, string suit, int id)> Deck()
223         {
224             var id = 0;
225             var hand = new List<string>();
226             return (from suit in suits
227                     from rank in ranks
228                     select (rank, suit, id: id++)).ToDictionary(x => x.id);
229         }
230 
231         private static void RemoveSuit(Dictionary<int, (string rank, string suit, int id)> deck, int suit)
232         {
233             var list = deck.Values.Where(card => card.id / ranks.Length == suit).ToList();
234             foreach (var card in list)
235             {
236                 deck.Remove(card.id);
237             }
238         }
239 
240         private static void RemoveRank(Dictionary<int, (string rank, string suit, int id)> deck, int rank)
241         {
242             var list = deck.Values.Where(card => card.id % ranks.Length == rank).ToList();
243             foreach (var card in list)
244             {
245                 deck.Remove(card.id);
246             }
247         }
248 
249         private static (string rank, string suit, int id) RandomCard(Dictionary<int, (string rank, string suit, int id)> deck, Random rand)
250         {
251             return deck.Skip(rand.Next(0, deck.Count)).First().Value;
252         }
253 
254         private static string[] GenerateRandomHand(Random rand)
255         {
256             var hand = new List<string>();
257             var deck = Deck();
258 
259             while (hand.Count < 7)
260             {
261                 var next = RandomCard(deck, rand);
262                 deck.Remove(next.id);
263                 hand.Add($"{next.rank}{next.suit}");
264             }
265 
266             return hand.ToArray();
267         }
268 
269         private static string[] GenerateStraightFlush(Random rand)
270         {
271             var hand = new List<string>();
272             var deck = Deck();
273             var suit = rand.Next(0, suits.Length);
274             var rank = rand.Next(0, ranks.Length - 5);
275             var head = suit * ranks.Length + rank;
276             // 5 cards make the straight flush
277             for (var i = 0; i < 5; i++)
278             {
279                 var current = head + i;
280                 var card = deck[current];
281                 deck.Remove(current);
282                 hand.Add($"{card.rank}{card.suit}");
283             }
284             // any 2 other cards may be added
285             for (var i = 0; i < 2; i++)
286             {
287                 var card = RandomCard(deck, rand);
288                 deck.Remove(card.id);
289                 hand.Add($"{card.rank}{card.suit}");
290             }
291             return hand.ToArray();
292         }
293 
294         private static string[] GenerateFourOfAKind(Random rand)
295         {
296             var hand = new List<string>();
297             var deck = Deck();
298             var rank = rand.Next(0, ranks.Length);
299             var head = rank;
300             // 4 cards make the four-of-a-kind
301             for (var i = 0; i < 4; i++)
302             {
303                 var current = head + i * ranks.Length;
304                 var card = deck[current];
305                 deck.Remove(current);
306                 hand.Add($"{card.rank}{card.suit}");
307             }
308             // any 3 other cards may be added
309             for (var i = 0; i < 3; i++)
310             {
311                 var card = RandomCard(deck, rand);
312                 deck.Remove(card.id);
313                 hand.Add($"{card.rank}{card.suit}");
314             }
315             return hand.ToArray();
316         }
317 
318         private static string[] GenerateFullHouse(Random rand)
319         {
320             var hand = new List<string>();
321             var deck = Deck();
322             var rank = rand.Next(0, ranks.Length);
323             var head = rank;
324             // 3 cards make the triple
325             for (var i = 0; i < 3; i++)
326             {
327                 var current = head + i * ranks.Length;
328                 var card = deck[current];
329                 deck.Remove(current);
330                 hand.Add($"{card.rank}{card.suit}");
331             }
332             // remaining rank would result in a four-of-a-kind
333             RemoveRank(deck, rank);
334             // 2 cards make a pair
335             var rank2 = Array.IndexOf(ranks, RandomCard(deck, rand).rank);
336             var head2 = rank2;
337             for (var i = 0; i < 2; i++)
338             {
339                 var current = head2 + i * ranks.Length;
340                 var card = deck[current];
341                 deck.Remove(current);
342                 hand.Add($"{card.rank}{card.suit}");
343             }
344             // remaining rank would result in a three-of-a-kind
345             RemoveRank(deck, rank2);
346             // any 2 other cards may be added
347             for (var i = 0; i < 2; i++)
348             {
349                 var card = RandomCard(deck, rand);
350                 deck.Remove(card.id);
351                 hand.Add($"{card.rank}{card.suit}");
352             }
353             return hand.ToArray();
354         }
355 
356         private static string[] GenerateFlush(Random rand)
357         {
358             var hand = new List<string>();
359             var deck = Deck();
360             var primaryDeck = Deck();
361             var suit = rand.Next(0, suits.Length);
362             for (var i = 0; i < 4; i++)
363             {
364                 if (i != suit) RemoveSuit(primaryDeck, i);
365             }
366             // 5 cards make a flush
367             for (var i = 0; i < 5; i++)
368             {
369                 var card = RandomCard(primaryDeck, rand);
370                 primaryDeck.Remove(card.id);
371                 deck.Remove(card.id);
372                 hand.Add($"{card.rank}{card.suit}");
373             }
374             // any 2 other cards may be added
375             // small chance on straight flush, but that's ok
376             for (var i = 0; i < 2; i++)
377             {
378                 var card = RandomCard(deck, rand);
379                 deck.Remove(card.id);
380                 hand.Add($"{card.rank}{card.suit}");
381             }
382             return hand.ToArray();
383         }
384 
385         private static string[] GenerateStraight(Random rand)
386         {
387             var hand = new List<string>();
388             var deck = Deck();
389             var rank = rand.Next(0, ranks.Length - 5);
390             var head = rank;
391             // 5 cards make the straight
392             for (var i = 0; i < 5; i++)
393             {
394                 var suit = rand.Next(0, suits.Length);
395                 var current = head + i + suit * ranks.Length;
396                 var card = deck[current];
397                 deck.Remove(current);
398                 hand.Add($"{card.rank}{card.suit}");
399             }
400             // any 2 other cards may be added
401             // small chance on straight flush, but that's ok
402             for (var i = 0; i < 2; i++)
403             {
404                 var card = RandomCard(deck, rand);
405                 deck.Remove(card.id);
406                 hand.Add($"{card.rank}{card.suit}");
407             }
408             return hand.ToArray();
409         }
410 
411         private static void Test(string[] holeCards, string[] communityCards)
412         {
413             var expected = Expect(holeCards, communityCards);
414             var actual = Act(holeCards, communityCards);
415             Verify(expected, actual, holeCards, communityCards);
416             if (!stats.TryGetValue(expected.type, out var cnt)) cnt = 0;
417             stats[expected.type] = cnt + 1;
418         }
419     
420         private static (string type, string[] ranks) Expect(string[] holeCards, string[] communityCards)
421         {
422             var cards = holeCards.Concat(communityCards).Select(Parse).OrderBy(x => ranksLookup[x.rank]).ToArray();
423             var cardsByRank = cards.ToLookup(x => x.rank);
424             var cardsBySuit = cards.ToLookup(x => x.suit);
425             var ans = findStraightFlush();
426             if (ans == null) ans = findFourOfAKind();
427             if (ans == null) ans = findFullHouse();
428             if (ans == null) ans = findFlush();
429             if (ans == null) ans = findStraight();
430             if (ans == null) ans = findThreeOfAKind();
431             if (ans == null) ans = findTwoPair();
432             if (ans == null) ans = findPair();
433             if (ans == null) ans = findNothing();
434             return ans.GetValueOrDefault(default);
435     
436             (string rank, string suit) Parse(string card) => (card.Substring(0, card.Length - 1), card.Substring(card.Length - 1, 1));
437     
438             (string type, string[] ranks)? findStraightFlush()
439             {
440                 var flush = cardsBySuit.SingleOrDefault(x => x.Count() >= 5)?.ToArray();
441                 if (flush == null) return null;
442                 for (var i = 0; i + 4 < flush.Length; i++)
443                 {
444                     var match = true;
445                     for (var j = 1; j <= 4; j++)
446                     {
447                         if (!flush.Any(card => ranksLookup[card.rank] == ranksLookup[flush[i].rank] + j))
448                         {
449                             match = false;
450                             break;
451                         }
452                     }
453                     if (match) return ("straight-flush", Enumerable.Range(0, 5).Select(k => ranks[k + ranksLookup[flush[i].rank]]).ToArray());
454                 }
455                 return null;
456             }
457     
458             (string type, string[] ranks)? findFourOfAKind()
459             {
460                 var t4_cards = cardsByRank.SingleOrDefault(x => x.Count() == 4);
461                 if (t4_cards == null) return null;
462                 var t4 = t4_cards.First().rank;
463                 var h1 = cardsByRank.First(x => x.Key != t4).Key;
464                 return ("four-of-a-kind", new[] { t4, h1 });
465             }
466     
467             (string type, string[] ranks)? findFullHouse()
468             {
469                 var t3_set = cardsByRank.Where(x => x.Count() == 3);
470                 if (!t3_set.Any()) return null;
471                 var t3 = t3_set.First().First().rank;
472                 var t2_ranks = cardsByRank.Where(x => x.Count() == 2).Select(x => x.Key).ToList();
473                 if (t3_set.Count() > 1) t2_ranks.Add(t3_set.Skip(1).First().Key);
474                 if (!t2_ranks.Any()) return null;
475                 var t2 = t2_ranks.OrderBy(x => ranksLookup[x]).First();
476                 return ("full house", new[] { t3, t2 });
477             }
478     
479             (string type, string[] ranks)? findFlush()
480             {
481                 var flush = cardsBySuit.SingleOrDefault(x => x.Count() >= 5)?.ToArray();
482                 if (flush == null) return null;
483                 return ("flush", flush.Take(5).Select(x => x.rank).ToArray());
484             }
485     
486             (string type, string[] ranks)? findStraight()
487             {
488                 for (var i = 0; i + 4 < cards.Length; i++)
489                 {
490                     var match = true;
491                     for (var j = 1; j <= 4; j++)
492                     {
493                         if (!cards.Any(card => ranksLookup[card.rank] == ranksLookup[cards[i].rank] + j))
494                         {
495                             match = false;
496                             break;
497                         }
498                     }
499                     if (match) return ("straight", Enumerable.Range(0, 5).Select(k => ranks[k + ranksLookup[cards[i].rank]]).ToArray());
500                 }
501                 return null;
502             }
503     
504             (string type, string[] ranks)? findThreeOfAKind()
505             {
506                 var t3_cards = cardsByRank.SingleOrDefault(x => x.Count() == 3);
507                 if (t3_cards == null) return null;
508                 var t3 = t3_cards.First().rank;
509                 var h1 = cardsByRank.First(x => x.Key != t3).Key;
510                 var h2 = cardsByRank.First(x => x.Key != t3 && x.Key != h1).Key;
511                 return ("three-of-a-kind", new[] { t3, h1, h2 });
512             }
513     
514             (string type, string[] ranks)? findTwoPair()
515             {
516                 var t2_set = cardsByRank.Where(x => x.Count() == 2);
517                 if (t2_set.Count() < 2) return null;
518                 var t2_high = t2_set.First().First().rank;
519                 var t2_low = t2_set.Skip(1).First().First().rank;
520                 var h1 = cardsByRank.First(x => x.Key != t2_high && x.Key != t2_low).Key;
521                 return ("two pair", new[] { t2_high, t2_low, h1 });
522             }
523     
524             (string type, string[] ranks)? findPair()
525             {
526                 var t2_cards = cardsByRank.SingleOrDefault(x => x.Count() == 2);
527                 if (t2_cards == null) return null;
528                 var t2 = t2_cards.First().rank;
529                 var h1 = cardsByRank.First(x => x.Key != t2).Key;
530                 var h2 = cardsByRank.First(x => x.Key != t2 && x.Key != h1).Key;
531                 var h3 = cardsByRank.First(x => x.Key != t2 && x.Key != h1 && x.Key != h2).Key;
532                 return ("pair", new[] { t2, h1, h2, h3 });
533             }
534     
535             (string type, string[] ranks) findNothing()
536             {
537                 return ("nothing", cards.Take(5).Select(x => x.rank).ToArray());
538             }
539         }
540     
541         #endregion
542     }
543 }

 文章来源地址https://www.toymoban.com/news/detail-630201.html

到了这里,关于【算法】用c#实现德州扑克卡牌游戏规则的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 低代码自动化平台| 游戏规则改变者

    自动化测试对于软件开发公司起着非常重要的作用。它在公司及其客户之间建立了对优质产品的信任。此外,它还使软件开发人员更加自信,因为他们可以在其他模块上工作,而不必担心应用程序的任何现有功能是否存在错误。在软件测试中融入自动化是必须的,但雇用自动

    2024年01月17日
    浏览(46)
  • 第四范式AIGC的野心,改变软件行业游戏规则

     图片AI算法提供:Midjourney 在国内众多发布大模型的科技企业中,第四范式入局的方式与众不同。 “我们并不需要完整地对标OpenAI,也并不需要OpenAI能做什么就一定要做什么……我们不去参与一场全面的竞争,而是专注于其中一场比赛。” 第四范式创始人兼CEO戴文渊所说的

    2024年02月04日
    浏览(40)
  • 开源软件:释放创新的力量,改变数字世界的游戏规则

    在充满活力的技术领域,创新是至高无上的,有一种方法已获得显著的吸引力——开源软件。开源软件凭借其透明、协作和无限可能性的精神,彻底改变了我们开发、共享和定制应用程序的方式。从操作系统到数据分析工具,其影响跨越了多个领域。本文将带您深入了解开源

    2024年02月05日
    浏览(67)
  • 利用 Dynamsoft Panorama 提高效率:多代码读取领域的游戏规则改变者

    在繁忙的库存管理领域,不同的场景需要不同的解决方案。但如果一种解决方案可以适应多种场景呢?这就是强大的多代码阅读器Dynamsoft Panorama 的闪光点。让我们深入研究一下它如何带来无与伦比的效率,无论您的相机是扫描静态场还是沿着路径移动。 点击下载Dynamsoft Bar

    2024年02月03日
    浏览(41)
  • iOS 17中的Safari配置文件改变了游戏规则,那么如何设置呢

    Safari在iOS 17中最大的升级是浏览配置文件——能够在一个应用程序中创建单独的选项卡和书签组。这些也可以跟随你的iPad和Mac,但在本指南中,我们将向你展示如何使用运行iOS 17的iPhone。 你可能有点困惑,为什么Safari中没有明显的位置可以添加个人资料,我们当然也是。诀

    2024年02月09日
    浏览(48)
  • 【算法原理和代码实战】德州扑克计算概率4-2法则原理(基于概率论和统计学的基本原理),详细计算步骤,具体算法代码实例。

    德州扑克计算概率的4-2法则是一种简便的计算方法,用于估算在德州扑克中获得某种牌型的概率。4-2法则的原理是基于概率论和统计学的基本原理,通过观察德州扑克中的牌型组合和可能性,得出一个简单的计算公式。 在德州扑克的前三张公共牌(翻牌圈)之后,如果你需要

    2024年02月14日
    浏览(53)
  • Unity UI适配规则和对热门游戏适配策略的拆解

    本文会介绍一些关于UI适配的基础概念,并且统计了市面上常见的设备的分辨率的情况。同时通过拆解目前市面上较为成功的两款休闲游戏Royal Match和Monopoly GO(两款均为近期游戏付费榜前几的游戏),大致推断出他们的适配策略,以供学习和参考。 设计分辨率: 设计分辨率是指

    2024年03月14日
    浏览(68)
  • 颠覆传统制造:PLC物联网如何彻底改变工厂设备数据采集的游戏规则?

    颠覆传统制造:PLC物联网如何彻底改变工厂设备数据采集的游戏规则?       随着科技的不断发展,物联网技术正逐渐渗透到各个领域,其中PLC物联网技术在工厂设备数据采集方面发挥着越来越重要的作用。PLC物联网技术通过将PLC(可编程逻辑控制器)与物联网技术相结合,

    2024年03月11日
    浏览(52)
  • Gemini 1.0:Google推出的全新AI模型,改变生成式人工智能领域的游戏规则!

    Gemini 1.0:Google推出的全新AI模型,将改变生成式人工智能领域的游戏规则! 🎥 屿小夏 : 个人主页 🔥个人专栏 : IT杂谈 🌄 莫道桑榆晚,为霞尚满天! 北京时间 12 月 6 日晚,Google 给近期稍显沉寂的 AI 模型战场扔下了一颗新的炸弹:号称多模态任务处理能力首次超越人类

    2024年02月04日
    浏览(64)
  • 【免费题库】华为OD机试 - 德州扑克(Java & JS & Python & C & C++)

    哈喽,本题库完全免费,收费是为了防止被爬,大家订阅专栏后可以私信联系退款。感谢支持 五张牌,每张牌由牌大小和花色组成,牌大小2~10、J、Q、K、A,牌花色为红桃、黑桃、梅花、方块四种花色之一。 判断牌型: 牌型1,同花顺:同一花色的顺子,如红桃2红桃3红桃4红桃

    2024年04月10日
    浏览(71)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包