c# - 在 C# 中反向 Fisher-Yates Shuffle

标签 c# sorting playing-cards array-algorithms

我正在尝试创建一个控制台程序来模拟有一副纸牌,用户应该能够;

  • 随机抽取一些卡片
  • 洗牌
  • 将牌组恢复到原来的状态

我正在努力想办法让牌组回到起点

当我尝试再次使用初始化数组时; string[] Deck = { x,x,x } 它似乎也不喜欢那样

任何指点将不胜感激!下面的代码;

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

namespace CardArranger
{  
    class Program
    {

        static void Main(string[] args)
        {

            string[] Deck =
            {
                "D1", "D2", "D3", "D4", "D5", "D6", "D7", "D8", "D9", "D10", "DJ", "DQ", "DK",
                "H1", "H2", "H3", "H4", "H5", "H6", "H7", "H8", "H9", "H10", "HJ", "HQ", "HK",
                "C1", "C2", "C3", "C4", "C5", "C6", "C7", "C8", "C9", "C10", "CJ", "CQ", "CK",
                "S1", "S2", "S3", "S4", "S5", "S6", "S7", "S8", "S9", "S10", "SJ", "SQ", "SK",
            };

            Random r1 = new Random();       

            while (true)
            {
                //display number of random cards
                Console.WriteLine("write shuffle to shuffle or 'sort' to organise the deck again");
                string Uinput = Console.ReadLine();

                bool isCount = int.TryParse(Uinput, out int noCards);

                if (isCount)
                {
                    for (int i = 0; i < noCards; i++)
                    {
                        Console.WriteLine(Deck[r1.Next(0, 52)]);
                    }
                }
                else
                {
                    if (Uinput.Equals("shuffle"))
                    {
                        Shuffle(ref Deck, r1);
                        Console.WriteLine("Shuffled Deck");
                        for (int i = 0; i < Deck.Length; i++)
                        {
                            Console.WriteLine(Deck[i] + " , ");                        
                        }
                        Console.WriteLine();
                        Console.WriteLine("---");
                    }
                    else if (Uinput.Equals("sort"))
                    {
                        //Implement your sort method here
                        Console.WriteLine("Sorted Deck");
                        for (int i = 0; i < Deck.Length; i++)
                        {
                            Console.WriteLine(Deck[i] + " , ");
                        }
                        Console.WriteLine();
                        Console.WriteLine("---");
                    }
                    else
                    {                    
                        Console.WriteLine("Unrecognised Command");
                    }

                }
                Console.WriteLine("Press Any Key to Repeat");
                Console.ReadKey();
            }

        }

        //Fisher-Yates Shuffle
        static void Shuffle(ref string[] OriginalArray, Random Rnd)
        {            
            for (int i = 0; i < OriginalArray.Length; i++)
            {
                string tmp = OriginalArray[i];
                int r = Rnd.Next(0, OriginalArray.Length);
                OriginalArray[i] = OriginalArray[r];
                OriginalArray[r] = tmp;
            }
        }



        static void Sort(ref string[] ShuffledArray)
        {
           // sort the deck back in order
        }
    }
}

最佳答案

简单地将数组分配给原始数组的副本可能是处理此问题的最简单方法。话虽如此,使用 Array.sort() 和自定义比较器函数对其进行排序是有益的,因为您可能希望在将来维护卡片状态(见下文):

static void Sort(ref string[] ShuffledArray)
{
    Array.Sort(ShuffledArray, CardComparator);
}

public static int CardComparator(string a, string b)
{
    Dictionary<string, int> rank = new Dictionary<string, int>()
    {
        {"A", 0}, {"1", 1}, {"2", 2}, {"3", 3}, {"4", 4}, 
        {"5", 5}, {"6", 6}, {"7", 7}, {"8", 8}, {"9", 9}, 
        {"10", 10}, {"J", 11}, {"Q", 12}, {"K", 13}, 
    };
    int cmp = "HCS".IndexOf(a[0]) - "HCS".IndexOf(b[0]);

    if (cmp == 0) 
    {
        return rank[a.Substring(1)] - rank[b.Substring(1)];
    }

    return cmp;
}

Try it!

这应该说明您可能很快就会遇到的一些程序设计问题。问题是排序需要解析字符串以确定每张牌的点数和花色。这对于编写游戏逻辑会有问题;您将花费大量精力进行解析。

为了解决这个问题,我建议写一个结构体或类来封装一张卡片。成员属性可以是 RankSuit 以及相应的 getter 和 setter(如果适用)。从长远来看,这种重构将得到肯定的返回(!)。 Deck 类也是合适的,它包含一个Card 成员数组以及SortShuffle 函数。

此外,您的随机播放代码似乎有偏见;检查pseudocode on Wikipedia并尝试重新实现它,直到您可以在大型数据集上运行它的无偏排序。以下是在数据集上运行排序数十万次并记录元素结束位置的示例分布(无偏排序将提供均匀分布):

111258
104215
99394
96347
95288
95949
98992
104344
111426

关于c# - 在 C# 中反向 Fisher-Yates Shuffle,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52594920/

相关文章:

python - 如何用python制作一副带有多个变量的纸牌?

c# - 从喊播中获取比特率

c++ - 排序相关算法(用排序集合中的索引替换每个项目)

java - 一个值类可以有两个 compareTo 方法吗?

Mysql使用数字和字符排序

java - 如何使用迭代器从 1 个 ArrayList 对象创建 4 个 ArrayList 对象(对于每个对象)

java - 如何仅对一副纸牌中的某些部分(面牌)使用枚举

c# - 如何检查 pdb 文件是否对调试程序集有效

C# 在其他 API 中调用 post 方法获取 404

c# - 通过 HTML 敏捷包向 HTML 添加文档类型