为什么洗牌两个不同的套牌产生相同的结果?

时间:2014-07-22 08:07:34

标签: c# random shuffle

首先我在这里有“Deck”课程。我刚刚介绍了一些基本方法,用于测试目的。这是我第一次创建“卡片”计划。

    public class Deck
{
    private int deckCounter = 0;
    private List<Card> deckSize = new List<Card>();
    private List<Card> shuffledDeck = new List<Card>();
    private Random random = new Random();

    public Deck()
    {
    }

    public void Build()
    {
        for (int i = 1; i < 5; i++)
        {
            for (int k = 1; k < 14; k++)
            {
                deckSize.Add(new Card(k.ToString(), i));
            }
        }
    }

    public void Add(Card card)
    {
        deckSize.Add(card);
        deckCounter++;
    }

    public Card RemoveCard()
    {
            Card cardToRemove = deckSize.First();
            deckSize.RemoveAt(0);
            return cardToRemove;
    }

    public void ShowContainedCards()
    {
        int cardCount = 0;
        foreach (Card c in deckSize)
        {
            Console.WriteLine(c.ReturnCardInfo());
            cardCount++;
        }
        Console.WriteLine(cardCount);
    }

    public void Shuffle()
    {
        while (deckSize.Count != 0)
        {
            int i = random.Next(deckSize.Count);
            shuffledDeck.Add(deckSize[i]);

            deckSize.RemoveAt(i);
        }
        deckSize = shuffledDeck;
    }

    public bool IsEmpty()
    {
        if (deckSize.Any())
        {
            return false;
        }
        else return true;
    }

    public List<Card> GetCardList()
    {
        return deckSize;
    }
}

基本上,我所做的就是:

    Deck deck1 = new Deck();
    Deck deck2 = new Deck();

    deck1.Build();
    deck1.Shuffle();
    deck2.Build();
    deck2.Shuffle();

在那之后,我得到完全相同的洗牌,对于deck1和deck2。这是为什么?另外,如果你不知道的话,我就是新手了。)

3 个答案:

答案 0 :(得分:1)

在两个套牌实例中使用相同的Random类实例:

Random random = new Random();
Deck deck1 = new Deck(random);
Deck deck2 = new Deck(random);

所以,在构造函数中:

public class Deck
{
    private int deckCounter = 0;
    private List<Card> deckSize = new List<Card>();
    private List<Card> shuffledDeck = new List<Card>();
    private Random random;

    public Deck(Random random)
    {
        this.random = random;
    }

您的代码当前存在的问题是,创建的Random的两个实例的种子是相同的。这导致它们产生相同的结果。使用Random的相同实例意味着第二个shuffle将在第一个shuffle的种子结果之上构建

答案 1 :(得分:1)

来自docs

  

默认种子值源自系统时钟并具有有限的分辨率。因此,通过调用默认构造函数紧密连续创建的不同Random对象将具有相同的默认种子值,因此将生成相同的随机数集。

相同的文档也提出了一个解决方案:

  

使用单个Random对象生成所有随机数可以避免此问题。

因此,一种可能的解决方案是使您的随机生成器静态,因此所有Deck实例共享相同的Random实例:

private static Random random = new Random();

这样,您甚至可以避免更改Deck类的公共界面的任何部分。

答案 2 :(得分:0)

计算机本身随机,因此任何随机数生成器实际上都会使用算法生成看起来随机的输出。与此相关的是始终有一个起点,如果你知道它从哪里开始,你可以预测结果。因此,随机数生成器具有“种子”,告诉它从哪里开始。相同的种子将始终给出相同的“随机”数字序列。

两次,您都在使用new Random(),它使用默认种子。在某些语言中,建议您将当前时间作为种子传递,但C#会为您执行此操作。但是,如果你创建了两个靠近的Random个对象,它们很可能会得到相同的时间,这就是这里发生的事情。

如果你的Random是静态的,那么你所有的随机数都来自同一个来源,所以这两个套牌会得到连续的随机数,而不是相同的随机数。