【问题标题】:Generate all distinct 7 card combinations of a poker hand?生成一手牌的所有不同的 7 张牌组合?
【发布时间】:2014-12-21 21:48:19
【问题描述】:

我正在尝试生成扑克牌的所有不同组合,如下所述:

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

【问题讨论】:

  • 第 49 行是哪一行?你试过调试吗?
  • 是的,下面一行是49: int maxRank = hand.Max(x => x.Rank); “InvalidOperationException 未处理:序列不包含任何元素”@YuliaV
  • 你知道这将是一个 2GB 的文件吗?

标签: c# combinations permutation poker


【解决方案1】:

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

【讨论】:

  • 好的,所以我删除了 cmets。当我运行它时,我只会在提示中得到结果“57027”。如果我换成 7 张卡,我会得到 4973182。仅此而已。如何简单地将每个组合写入 ​​.txt 文件,或者至少将它们打印出来,每行一次一个?谢谢
  • @Chris,如果你 google “c# print file”,你会得到很多问题的答案!
  • 是的,但如何读/写文件不是问题。我不知道如何获取 List 中组合(手)的实际字符串表示。
  • 您需要添加一个 Card 类的方法来输出您喜欢的字符串表示形式,例如Suit.ToString() + " - " + Rank.ToString()。然后在hand 上调用它以获取卡片的字符串表示列表。然后使用String.Join 得到一个长字符串。祝你好运!
  • 另外,如果您觉得我的回答和以下讨论有帮助,请您“打勾”。
【解决方案2】:

我参加聚会有点晚了,但也有同样的需要(5 张牌扑克手)。也从尼克拉森的(似乎不完美,因为我也得到了错误的数字)的答案在另一个线程上工作,只需添加一个方法来获取卡的名称(我相信有人可以更优雅地做到这一点,但它有效):

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

【讨论】:

    【解决方案3】:

    这将在大约 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"));
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2011-04-19
      • 2016-02-24
      • 2021-05-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多