【问题标题】:C# card shuffle in card deck 52 cards卡片组中的 C# 洗牌 52 张卡片
【发布时间】:2017-04-27 00:08:07
【问题描述】:

我仍在开发一个 Windows 应用程序项目,它是关于一套卡片组的。该应用程序使用 52 张牌,其中包括 4 个花色和 13 个面值,例如 2 个梅花、红心杰克等。我正在工作的部分是我还必须使用五个图片框来显示每张随机卡片,因此我单击“交易”按钮。我知道我必须使用“随机”关键字以及使用 for 循环来进行洗牌。

因此,我不太确定如何使用不同的随机卡片显示每个图片框并相应地显示每张卡片的名称。

下面包含 Windows 应用程序外观的屏幕截图和我的项目代码。

    List<PlayingCard> cardDeckList = new List<PlayingCard>();

    private void buttonDeal_Click(object sender, EventArgs e)
    {

        int integer = 0;
        Random picRandom = new Random();
        int n = 0;

        integer = picRandom.Next(0, imageListCards.Images.Count);

        for( n = 0; n < cardDeckList.Count; n++)
        {
            pictureBox_Card1.Image = cardDeckList[integer].CardImage;
            pictureBox_Card2.Image = cardDeckList[integer].CardImage;
            pictureBox_Card3.Image = cardDeckList[integer].CardImage;
            pictureBox_Card4.Image = cardDeckList[integer].CardImage;
            pictureBox_Card5.Image = cardDeckList[integer].CardImage;

        }

        listBoxOutput.Items.Add(cardDeckList[integer].ToString());

    }


    private void FormShuffleCardDeck_Load(object sender, EventArgs e)
    {
        try
        {

            string[] suitList = { "Clubs", "Diamonds", "Hearts", "Spades" };

            string[] faceList = new string[13];


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

            pointValues.Add(2);
            pointValues.Add(3);
            pointValues.Add(4);
            pointValues.Add(5);
            pointValues.Add(6);
            pointValues.Add(7);
            pointValues.Add(8);
            pointValues.Add(9);
            pointValues.Add(10);
            pointValues.Add(10);
            pointValues.Add(11);

            string suit = "";
            string face = "";
            int counter = 0;
            int i = 0;
            int k = 0;

            for (i = 0; i < 4; i++)
            {
                suit = i.ToString();

                switch (suit)
                {
                    case "0":
                        suit = "Clubs";
                        break;

                    case "1":
                        suit = "Diamonds";
                        break;

                    case "2":
                        suit = "Hearts";
                        break;

                    case "3":
                        suit = "Spades";
                        break;
                }

                for (k = 0; k < 13; k++)
                {
                    face = k.ToString();

                    switch (k)
                    {
                        case 0:
                            face = "2";
                            break;

                        case 1:
                            face = "3";
                            break;

                        case 2:
                            face = "4";
                            break;

                        case 3:
                            face = "5";
                            break;

                        case 4:
                            face = "6";
                            break;

                        case 5:
                            face = "7";
                            break;

                        case 6:
                            face = "8";
                            break;

                        case 7:
                            face = "9";
                            break;

                        case 8:
                            face = "10";
                            break;

                        case 9:
                            face = "Ace";
                            break;

                        case 10:
                            face = "King";
                            break;

                        case 11:
                            face = "Jack";
                            break;

                        case 12:
                            face = "Queen";
                            break;
                    }


                    cardDeckList.Add(new PlayingCard(suit, face, imageListCards.Images[counter],2));
                    counter++;
                }


            }

            //for (int l = 0; l < cardDeckList.Count; l++)
            //{
            //    listBoxOutput.Items.Add(cardDeckList[l].ToString());
            //    //MessageBox.Show(cardDeckList.Count.ToString());              

            //}

        }



        catch(Exception ex)
        {
            MessageBox.Show(ex.Message);
        }

    }

Windows App Program

【问题讨论】:

  • shuffle 应该是 shuffle 方法中唯一的东西。同样,create deck 方法中应该只存在创建卡片。一旦保持这种分离,就很容易在 SO 上搜索“洗牌”并调整代码。这两种方法都应该比显示的代码小很多。此外,通过为套件中的每张牌赋予 1(ace)..13(king) 的值,可以大大简化创建代码。卡本身知道它是“面值字符串”。然后可以使用简单的循环和模数来创建卡片。
  • 洗牌本身比尝试从未洗牌的牌组中随机挑选要容易得多。

标签: c# image class for-loop picturebox


【解决方案1】:

我不确定您的 PlayingCard 类是如何编码的,但您的问题似乎很大一部分源于它的设计。以这个实现为例:

PlayingCard

public class PlayingCard : IComparable<PlayingCard>
{
    private int value;
    private int suit;
    private Bitmap cardImage;

    public int Value => value;
    public string ValueName => ValueToName(value);

    public int Suit => suit;
    public string SuitName => SuitToName(suit);

    public Bitmap CardImage => cardImage;

    public PlayingCard(int value, int suit, Bitmap cardImage)
    {
        this.value = value;
        this.suit = suit;
        this.cardImage = cardImage;
    }

    private string ValueToName(int n)
    {
        switch (n)
        {
            case 0:
                return "Ace";
            case 1:
            case 2:
            case 3:
            case 4:
            case 5:
            case 6:
            case 7:
            case 8:
            case 9:
                return (n+1).ToString();
            case 10:
                return "Jack";
            case 11:
                return "Queen";
            case 12:
                return "King";
            default:
                throw new ArgumentException("Unrecognized card value.");

        }
    }

    private string SuitToName(int s)
    {
        switch (s)
        {
            case 0:
                return "Clubs";
            case 1:
                return "Diamonds";
            case 2:
                return "Spades";
            case 3:
                return "Hearts";
            default:
                throw new ArgumentException("Unrecognized card suit");
        }
    }

    public int CompareTo(PlayingCard other)
    {
        int result = this.Suit.CompareTo(other.Suit);

        if (result != 0)
            return result;

        return this.Value.CompareTo(other.Value);
    }

    public override string ToString()
    {
        return String.Format("{0} of {1}", ValueName, SuitName);
    }
}

其中包含所有比较和值转换的编码,因此您不必担心创建高度专业化的方法来进行无关的转换。你可以像这样在牌组中使用它:

数组实现

// How to initialize deck
PlayingCard[] deck = Enumerable.Range(0, 52)
                        .Select(x => new PlayingCard(x % 13, x / 13, imageListCards[x]))
                        .ToArray();


// How to shuffle deck
Random r = new Random();
Array.Sort(deck, (a, b) => r.Next(0, 2) == 0 ? -1 : 1);

// How to reset deck
Array.Sort(deck);

// How to display top five cards
pictureBox_Card1.Image = deck[0].CardImage;
pictureBox_Card2.Image = deck[1].CardImage;
pictureBox_Card3.Image = deck[2].CardImage;
pictureBox_Card4.Image = deck[3].CardImage;
pictureBox_Card5.Image = deck[4].CardImage;

列表实现

// How to initialize deck
List<PlayingCard> deck = Enumerable.Range(0, 52)
                        .Select(x => new PlayingCard(x % 13, x / 13, imageListCards[x]))
                        .ToList();


// How to shuffle deck
Random r = new Random();
deck.Sort((a, b) => r.Next(0, 2) == 0 ? -1 : 1);

// How to reset deck
deck.Sort();

// How to display top five cards
pictureBox_Card1.Image = deck[0].CardImage;
pictureBox_Card2.Image = deck[1].CardImage;
pictureBox_Card3.Image = deck[2].CardImage;
pictureBox_Card4.Image = deck[3].CardImage;
pictureBox_Card5.Image = deck[4].CardImage;

编辑:

手动改组

如果您想手动进行随机播放,有一种称为Fisher-Yates Shuffle 的简单算法可以解决问题:

private static Random r = new Random();
static void Shuffle<T>(T[] array)
{
    for (int i = 0; i < array.Length; i++)
    {
        int idx = r.Next(i, array.Length);
        T temp = array[idx];
        array[idx] = array[i];
        array[i] = temp;
    }
}

(列表实现)

private static Random r = new Random();
static void Shuffle<T>(List<T> list)
{
    for (int i = 0; i < list.Count; i++)
    {
        int idx = r.Next(i, list.Count);
        T temp = list[idx];
        list[idx] = list[i];
        list[i] = temp;
    }
}

【讨论】:

  • 啊...我明白了。这在某种程度上是有道理的。是的,我确实使用了一个名为“PlayingCard”的类,并且大部分代码都涉及使用它。我很抱歉,因为我不太熟悉洗牌和通过五个不同的图片框显示每张随机牌。此外,我在洗牌时有一个问题。有没有可能我可以通过 for 循环来洗牌?
  • @LasknaK 这当然是可能的。请参阅我对如何操作的编辑。
  • 哦...我明白了...我试图搜索并了解洗牌过程如何运作,尤其是在卡片中。谢谢你。嗯.. 但是,这将如何实现列表类?
  • @LasknaK 通过将数组引用替换为 List 等效项。
  • 我明白了。我实际上尝试过这样做...但是...似乎 temp 有一个错误(下面有一个红色的摆动标记)...不知何故,错误消息表明它无法将 int 转换为 PlayingCard ... for (int i = 0; i
猜你喜欢
  • 2020-11-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-21
  • 2021-05-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多