【问题标题】:Deal Distinct Poker Hands处理不同的扑克手
【发布时间】:2015-12-05 16:00:06
【问题描述】:

我正在尝试生成不同的 5 张扑克手的文本文件,与 this question 非常相似(我实际上发布了一个答案)。我从this answer to that question 拼凑的程序大部分都有效。但是,有两个主要问题:手数不正确,每手都有红心2。如果手数是正确的,那么手数也是正确的。

发布我正在工作的答案的人说,他没有为初始卡播种而得到了正确的号码。但是,如果您删除种子,则在尝试进行排名时会收到 Invalid Exception 错误。播种它会使程序工作,但只返回一半的手。

我需要对此代码执行什么操作才能获得所有不同的 5 张牌?

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

namespace PokerHands

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

class Hand
{
    public List<Card> Cards { get; set; }
    public string HandString { get; set; }
}

class Program
{
    static int ranks = 13;
    static int suits = 4;
    static int cardsInHand = 5;
    static List<Hand> possibleHands = new List<Hand>();

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

        possibleHands.Shuffle();
        using (System.IO.StreamWriter file = new System.IO.StreamWriter(AppDomain.CurrentDomain.BaseDirectory + "Hands.txt"))
        {
            foreach (Hand hand in possibleHands)
            {
                counter += 1;
                hand.Cards.Shuffle();

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

                file.WriteLine(hand.HandString.Trim());
            }
        }

        Console.ReadLine();
    }

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

    static int GenerateAllHands(List<Card> cards)
    {
        if (cards.Count == cardsInHand)
        {
            Hand hand = new Hand();
            hand.Cards = cards;

            possibleHands.Add(hand);

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

public static class ThreadSafeRandom
{
    [ThreadStatic]
    private static Random Local;

    public static Random ThisThreadsRandom
    {
        get { return Local ?? (Local = new Random(unchecked(Environment.TickCount * 31 + Thread.CurrentThread.ManagedThreadId))); }
    }
}

static class MyExtensions
{
    public static void Shuffle<T>(this IList<T> list)
    {
        int n = list.Count;
        while (n > 1)
        {
            n--;
            int k = ThreadSafeRandom.ThisThreadsRandom.Next(n + 1);
            T value = list[k];
            list[k] = list[n];
            list[n] = value;
        }
    }
}
}

【问题讨论】:

  • 你试过调试你的代码吗?这是问题中的相当多的代码,我认为没有人愿意通过所有这些来找到一些调试会出现的东西。

标签: c# poker


【解决方案1】:

将GetPossibleNextCards()的开头改为:

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

并删除GetPossibleSuitsForRank() 的第一行,因为您没有使用结果。即删除这一行:

int maxSuit = hand.Max(x => x.Suit); // remove this

同时删除 Main() 中添加 2H 的行:

cards.Add(new Card() { Rank = 0, Suit = 0 }); // remove this

【讨论】:

    【解决方案2】:

    可以在 0.2 秒内生成所有不同的 5 卡。
    您无法以那么快的速度读取文件。
    手顺序无关紧要 - 没有 52!手。
    来自combinationscombin(52,5) 有 2,598,960 手牌。

    private byte[,] pokerHands;
    public byte[,] PokerHands
    {
        get
        {
            if (pokerHands == null)
            {
                // easy to get rank and suite from a byte  
                // just store byte 
                // type can make a card class that you pass a byte constuctor
                for (byte i = 0; i < 52; i++)
                    Debug.WriteLine("rank " + i % 13 + "  suite " + i / 13);
    
                Stopwatch sw = new Stopwatch();
                sw.Start();
                int counter = 0;
                pokerHands = new byte[2598960, 5];
                for (int i = 51; i >= 4; i--)
                {
                    for (int j = i-1; j >= 3; j--)
                    {
                        for (int k = j-1; k >= 2; k--)
                        {
                            for (int m = k-1; m >= 1; m--)
                            {
                                for (int n = m-1; n >= 0; n--)
                                {
                                    pokerHands[counter, 0] = (byte)i;
                                    pokerHands[counter, 1] = (byte)j;
                                    pokerHands[counter, 2] = (byte)k;
                                    pokerHands[counter, 3] = (byte)m;
                                    pokerHands[counter, 4] = (byte)n;
                                    counter++;
                                }
                            }
                        }
                    }
                }
                sw.Stop();
                System.Diagnostics.Debug.WriteLine("counter " + counter);
                System.Diagnostics.Debug.WriteLine("sw " + sw.ElapsedMilliseconds.ToString("N0"));
            }                
            return pokerHands;
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-11-04
      • 1970-01-01
      • 1970-01-01
      • 2014-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-09
      • 2023-03-11
      相关资源
      最近更新 更多