2014-10-26 89 views
2

我想产生一个牌手的所有不同的组合,如下所述:生成扑克牌牌的所有不同的7张牌组合吗?

Generating all 5 card poker hands

,但我一直卡住。当在上面的URL上尝试NickLarsen的C#答案时,我在第49行得到了未处理的异常错误。(https://stackoverflow.com/a/3832781/689881

我想要的非常简单:生成所有卡组合并一次打印一行简单的.txt文件

此外,我实际上想要所有7卡组合(而不是5)。 例如,前两行可能是这样的:

2c2d2h2s3c3d3h
2c2d2h2s3c3d3s

如何实现这一目标?速度并不那么重要。

下面是从NickLarsen失败的代码(我的修改):

using System; 
using System.Collections.Generic; 
using System.Linq; 

namespace ConsoleApplication20 
{ 
struct Card 
{ 
    public int Suit { get; set; } 
    public int Rank { get; set; } 
} 

class Program 
{ 
    static int ranks = 13; 
    static int suits = 4; 
    static int cardsInHand = 7; 

    static void Main(string[] args) 
    { 
     List<Card> cards = new List<Card>(); 
     //cards.Add(new Card() { Rank = 0, Suit = 0 }); 
     int numHands = GenerateAllHands(cards); 

     Console.WriteLine(numHands); 
     Console.ReadLine(); 
    } 

    static int GenerateAllHands(List<Card> cards) 
    { 
     if (cards.Count == cardsInHand) return 1; 

     List<Card> possibleNextCards = GetPossibleNextCards(cards); 

     int numSubHands = 0; 

     foreach (Card card in possibleNextCards) 
     { 
      List<Card> possibleNextHand = cards.ToList(); // copy list 
      possibleNextHand.Add(card); 
      numSubHands += GenerateAllHands(possibleNextHand); 
     } 

     return numSubHands; 
    } 

    static List<Card> GetPossibleNextCards(List<Card> hand) 
    { 
     int maxRank = hand.Max(x => x.Rank); 

     List<Card> result = new List<Card>(); 

     // only use ranks >= max 
     for (int rank = maxRank; rank < ranks; rank++) 
     { 
      List<int> suits = GetPossibleSuitsForRank(hand, rank); 
      var possibleNextCards = suits.Select(x => new Card { Rank = rank, Suit = x }); 
      result.AddRange(possibleNextCards); 
     } 

     return result; 
    } 

    static List<int> GetPossibleSuitsForRank(List<Card> hand, int rank) 
    { 
     int maxSuit = hand.Max(x => x.Suit); 

     // select number of ranks of different suits 
     int[][] card = GetArray(hand, rank); 

     for (int i = 0; i < suits; i++) 
     { 
      card[i][rank] = 0; 
     } 

     int[][] handRep = GetArray(hand, rank); 

     // get distinct rank sets, then find which ranks they correspond to 
     IEnumerable<int[]> distincts = card.Distinct(new IntArrayComparer()); 

     List<int> possibleSuits = new List<int>(); 

     foreach (int[] row in distincts) 
     { 
      for (int i = 0; i < suits; i++) 
      { 
       if (IntArrayComparer.Compare(row, handRep[i])) 
       { 
        possibleSuits.Add(i); 
        break; 
       } 
      } 
     } 

     return possibleSuits; 
    } 

    class IntArrayComparer : IEqualityComparer<int[]> 
    { 
     #region IEqualityComparer<int[]> Members 

     public static bool Compare(int[] x, int[] y) 
     { 
      for (int i = 0; i < x.Length; i++) 
      { 
       if (x[i] != y[i]) return false; 
      } 

      return true; 
     } 

     public bool Equals(int[] x, int[] y) 
     { 
      return Compare(x, y); 
     } 

     public int GetHashCode(int[] obj) 
     { 
      return 0; 
     } 

     #endregion 
    } 

    static int[][] GetArray(List<Card> hand, int rank) 
    { 
     int[][] cards = new int[suits][]; 
     for (int i = 0; i < suits; i++) 
     { 
      cards[i] = new int[ranks]; 
     } 

     foreach (Card card in hand) 
     { 
      cards[card.Suit][card.Rank] = 1; 
     } 

     return cards; 
    } 
} 
} 
+0

哪一行是第49行?你有没有试过调试它? – 2014-10-26 16:43:27

+0

是的,下面的行是49: int maxRank = hand.Max(x => x.Rank); “InvalidOperationException未处理:序列不包含任何元素”@YuliaV – 2014-10-26 16:45:52

+0

您意识到这将是一个2GB文件? – 2014-10-27 20:42:40

回答

2

这是因为你已经注释掉//cards.Add(new Card() { Rank = 0, Suit = 0 });。您的cards列表为空,您的代码无法找到空数组的max - 这是可预测的。

+0

好吧,我删除了评论。当我运行它时,我只在提示中得到结果“57027”。如果我换成7张牌,我得到4973182.没有更多。我如何简单地将每个组合写入一个.txt文件,或者至少只是将它们打印出来,每行一个一个地打印出来? Thx – 2014-10-26 16:55:56

+1

@Chris,如果你是谷歌“c#打印文件”,你会很多答案你的问题! – 2014-10-26 16:59:09

+0

是的,但如何读取/写入文件不是问题。我不知道如何获取列表中组合(手形)的实际字符串表示形式。 – 2014-10-26 18:17:11

1

我对派对有点迟到,但有同样的需要(5卡扑克牌手)。另外从Nick Larsen的工作(看起来不完美,因为我也得到错误的数字)在另一个线程上的答案,只需添加一个方法来获取卡的名称(我相信有人可以做得更优雅,但它的工作原理):

static string GetCardName(Card card) 
    { 
     string cardName; 
     string cardFace; 
     string cardSuit; 

     switch (card.Rank) 
     { 
      case 0: 
       cardFace = "2"; 
       break; 
      case 1: 
       cardFace = "3"; 
       break; 
      case 2: 
       cardFace = "4"; 
       break; 
      case 3: 
       cardFace = "5"; 
       break; 
      case 4: 
       cardFace = "6"; 
       break; 
      case 5: 
       cardFace = "7"; 
       break; 
      case 6: 
       cardFace = "8"; 
       break; 
      case 7: 
       cardFace = "9"; 
       break; 
      case 8: 
       cardFace = "10"; 
       break; 
      case 9: 
       cardFace = "J"; 
       break; 
      case 10: 
       cardFace = "Q"; 
       break; 
      case 11: 
       cardFace = "K"; 
       break; 
      default: 
       cardFace = "A"; 
       break; 
     } 

     switch (card.Suit) 
     { 
      case 0: 
       cardSuit = "H"; 
       break; 
      case 1: 
       cardSuit = "D"; 
       break; 
      case 2: 
       cardSuit = "S"; 
       break; 
      default: 
       cardSuit = "C"; 
       break; 
     } 

     cardName = cardFace + cardSuit; 

     return cardName; 
    } 

然后,使用一个for循环,所以你可以把它打印出来或者任何你需要:

static void Main(string[] args) 
    { 
     List<Card> cards = new List<Card>(); 
     cards.Add(new Card() { Rank = 0, Suit = 0 }); 
     int numHands = GenerateAllHands(cards); 
     int counter = 0; 

     Console.WriteLine(numHands); 
     Console.WriteLine(possibleHands.Count); 

     foreach (Hand hand in possibleHands) 
     { 
      counter += 1; 

      foreach (Card card in hand.Cards) 
      { 
       hand.HandString += GetCardName(card) + " "; 
      } 

      hand.HandString = hand.HandString.Trim(); 
     } 

     Console.ReadLine(); 
    } 
1

这将运行在大约3秒
为什么他们写出来的文本文件
你可以比文件读取更快地生成它们

public void PokerHands7from52() 
    { 
     for (byte i = 0; i < 52; i++) 
      Debug.WriteLine("rank " + i % 13 + " suite " + i/13); 

     Stopwatch sw = new Stopwatch(); 
     sw.Start(); 
     int counter = 0; 
     for (int i = 51; i >= 6; i--) 
     { 
      for (int j = i - 1; j >= 5; j--) 
      { 
       for (int k = j - 1; k >= 4; k--) 
       { 
        for (int m = k - 1; m >= 3; m--) 
        { 
         for (int n = m - 1; n >= 2; n--) 
         { 
          for (int p = n - 1; p >= 1; p--) 
          { 
           for (int q = p - 1; q >= 0; q--) 
           { 
            // the 7 card are i, j, k, m, n, p, q 
            counter++; 
            if (counter % 10000000 == 0) 
             Debug.WriteLine(counter.ToString("N0") + " " + sw.ElapsedMilliseconds.ToString("N0")); 
           } 
          } 
         } 

        } 
       } 
      } 
     } 
     sw.Stop(); 
     System.Diagnostics.Debug.WriteLine("counter " + counter.ToString("N0") + " should be 133,784,560"); 
     System.Diagnostics.Debug.WriteLine("sw " + sw.ElapsedMilliseconds.ToString("N0")); 
    } 
}