使用随机数选择一个列表中的项目并将其移动到另一个列表

时间:2013-02-08 04:45:13

标签: c#

我正在设计一款名为Snap的纸牌游戏(Heres是一个显示规则http://boardgames.about.com/od/cardgames/a/snap.htm的链接),在我的版本中,如果一对出现,玩家将不得不点击中间的堆。我目前有4个班级,一个用于卡片(一个名为cardValue_的int),一个用于玩家手牌,一个用于原始牌组,一个用于中间牌。所以Deck,Pile和Hand课程中都有一张卡片列表。我现在正在尝试为Deck类编写一个shuffle方法,其中包含一个Cards列表。哪个会选择随机卡并将其移动到新列表,直到所有卡被挑选,然后将它们移回原始列表,从而进行简单的随机播放。到目前为止我的方法看起来像这样......

public List<Deck> Shuffle(List<Card> cardDeck)
    {
        int index = 0;
        Random randomCard = new Random();
        List<Card> newDeck = new List<Card>();

        while (index < cardDeck.Count)
        {
            int ran = randomCard.Next(0, cardDeck.Count);
            foreach (Card card in cardDeck)
            {

            }
        }
    }

我正在尝试解决foreach循环应该进行的操作(除非整个方法都错了),但现在我想我已经将所有卡片都放在了错误的位置,所有52张卡片当前都在表单中声明,还是我应该在甲板课上宣布它们?

2 个答案:

答案 0 :(得分:2)

你在哪里接近我将如何解决它,我会做的是随机复制出源列表,直到它为空,然后再填充它。你不需要返回一个列表,因为这只会改变你传递的列表。

//Move this out of the function, if you are wondering why search SO for "Not random" and choose any of the 100's of people asking "why is random not random?" :)
private static Random randomCard = new Random(); //Not thread safe, if multi-threading use locks!!!

public static void Shuffle(List<Card> cardDeck)
{
    int index = 0;
    List<Card> tempDeck = new List<Card>();

    while (cardDeck.Count > 0)
    {
        int removal = randomCard.Next(0, cardDeck.Count);
        Card tempCard = cardDeck[removal];
        cardDeck.RemoveAt(removal);
        tempDeck.Add(tempCard);
    }

    //cardDeck is empty at this point, now we refill it with our randomized deck.
    cardDeck.AddRange(tempDeck);
}

如果您不想修改原始列表,并且确实需要新的随机列表,请先复制源列表。

public static List<Card> Shuffle(List<Card> cardDeck)
{
    int index = 0;
    List<Card> tempDeck = new List<Card>();
    List<Card> localCopy = new List<Card>(cardDeck);   //Creates a shallow copy of the list.      

    while (localCopy.Count > 0)
    {
        int removal = randomCard.Next(0, cardDeck.Count);
        Card tempCard = localCopy[removal];
        localCopy.RemoveAt(removal);
        tempDeck.Add(tempCard);
    }

    return tempDeck;
}

我建议使用Richard's method。它简单得多。

答案 1 :(得分:2)

阅读杰夫的blog on shuffling了解所有细节。

public List<Card> Shuffle(List<Card> cards)
{
  return new List<Card>(cards)
   .OrderBy(a => Guid.NewGuid());
}

<强>更新

斯科特建议Guid可能不够随机,Crypto RNG会更好。因此,使用BigInteger因为它实现了IComparable,我们得到:

RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();

public List<Card> Shuffle(List<Card> cards)
{
  var r = new byte[32];
  return new List<Card>(cards)
   .OrderBy(a => new BigInteger(rng.GetBytes(r));
}