【问题标题】:Can someone please explain to me why this is an infinite loop?有人可以向我解释为什么这是一个无限循环吗?
【发布时间】:2015-02-02 22:25:10
【问题描述】:

有人可以向我解释为什么这是一个无限循环吗?当我尝试这个时,团结就会挂起。我正在尝试构建一副 52 张牌

    public class Deck {
        private List<Card> deckList = new List<Card>();

        public Deck() {
            for (int i = 0; i<52; i++) {
                System.Random rnd = new System.Random();
                Card newCard = new Card(rnd.Next(1,13), rnd.Next(1,4));
                if (!deckList.Contains(newCard) || i == 0) {
                    deckList.Add(newCard);
                } else { i--; }
            }
        }
    }

【问题讨论】:

  • 如果您的问题不是这样,请不要写“我如何[做这件事]”之类的标题。
  • 另外,你的方法确实效率低下。不要随意加卡;您已经知道一副纸牌应该包含什么(每张纸牌)。只需创建一个正常的有序牌组,然后使用一种方法对其进行洗牌。 stackoverflow.com/questions/273313/randomize-a-listt-in-c-sharp
  • 当您考虑当列表快满时会发生什么时,您可以看到这种随机化方法是多么可怕。当一副牌中有 51 张牌时,您知道最后一张牌是什么,但您仍继续尝试随机生成它。这种方法非常非常糟糕,在任何情况下都不应该使用它。如果您想要随机播放,请使用随机播放算法。
  • 这里的另一个重要点是,即使您修复了错误,您也是在使用 32 位种子来洗牌 52 张牌。这意味着有 2^32 个可能的洗牌,但有 52 个!可能的真正纸牌。您永远无法生成数以万亿计的可能套牌。使用加密强度的随机性来源来洗牌。
  • @Sahuagin:正确; Random 名称错误。它是一个伪随机数生成器;如果您知道种子,那么序列是完全可预测的,根本不是“随机的”。由于只有 ~10^9 个种子,因此只有 ~10^9 个可能的数字序列,因此只有 ~10^9 个可能的不同牌组生成。但现实生活中有大约 10^67 种可能的套牌;这个算法只得到它们的一小部分。如果玩这个游戏是为了钱,这可能很重要。

标签: c# list unity3d


【解决方案1】:

您正在紧密循环中重新创建Random。这每次都使用相同的种子值,因此您每次都生成相同的 card。如果卡片已经存在于套牌中,则由于您减少循环变量,因此它会“永远”旋转。实际上,如果种子最终改变了,你会没事的。

你的代码应该是:

       System.Random rnd = new System.Random();
       for (int i = 0; i<52; i++) {
            Card newCard = new Card(rnd.Next(1,14), rnd.Next(1,5));
            if (!deckList.Contains(newCard) || i == 0) {
                deckList.Add(newCard);
            } else { i--; }
        }

请注意,这是一个非常奇怪的循环。我会使用while 循环来检查是否还有剩余的卡片或其他东西。无论如何,不​​要在这样的紧密循环中实例化 Random

更好的是,只需创建所有卡片并shuffle 它们。

我错过了 cmets 中提到的另一个更改,您需要使用 rnd.Next(1,14)rnd.Next(1,5) 以便实际生成每张卡片。否则没有出路。请记住,rnd.Next 的最大值是独占

【讨论】:

  • 我首先尝试了这种方式,然后从一个 while 循环开始。这让我的挫败感发生了很大变化,但你说得对,它绝对是随机数。我将尝试其他人所说的并制作一副牌并洗牌。
  • 这是最有帮助的,但这也不起作用。在我把它弄得更糟并发表我的帖子之前,我实际上是先这样的
  • @ken 尝试在固定范围内随机运行它
【解决方案2】:

因为您要更改循环内的循环变量。

} else { i--; }

所以终止条件

i<52

永远不会变成假的。

一般来说,您不应该以这种方式胡乱处理循环变量。这非常令人困惑,并且违反了最小惊喜原则。找到一种更好的方法来做到这一点,而不涉及弄乱循环变量。

【讨论】:

  • 我相信i 会在每次将唯一卡添加到套牌时保持递增。它应该终止,如果他真的生成了所有的牌(我不认为他是)。虽然是一个糟糕的循环/练习。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-01-18
  • 1970-01-01
  • 2022-01-22
  • 1970-01-01
  • 2015-10-16
  • 2019-09-14
  • 1970-01-01
相关资源
最近更新 更多