【问题标题】:Loop through array of items using probability [duplicate]使用概率循环遍历项目数组[重复]
【发布时间】:2016-10-12 23:55:08
【问题描述】:

我对 JavaScript 还是很陌生,我一直在制作 while 循环,它会掷骰子并在你掷出 6 时跳出循环。

var rollDice = function() {
  var dice = Math.floor(Math.random() * 6 + 1);

  while (dice !== 6) {
    console.log("A " + dice + " was rolled!");
    var dice = Math.floor(Math.random() * 6 + 1)
  }
  console.log("Lucky! You rolled a 6!");
}

现在我想遍历一个项目数组,并在找到所需项目时打破它。我希望能够像这样声明所需的项目:

var desiredItem = "Diamond";

但是,每个项目都有自己的概率值,我想将其包含在这个 while 循环中。这意味着您有 25% 的机会获得生锈的指甲,而只有 5% 的机会获得钻石。所以从统计上看,你会得到比钻石更多的生锈指甲。我还想在循环内向用户输出所有内容,如下所示:

console.log("Dang! A " + lootedItem + " was found...");

当你最终收到想要的物品并打破循环时:

console.log("Lucky! A" + desiredItem + "was found!");

我自己已经尝试了一段时间,但似乎无法得到它,所以任何帮助将不胜感激。谢谢!

【问题讨论】:

    标签: javascript arrays while-loop probability


    【解决方案1】:

    这是一个 ES6 实现:

    var findItem = function(desiredItem) {
        var items = [
            { item: "rusty nail", probability: 0.25 },
            { item: "stone", probability: 0.23 },
            { item: "banana", probability: 0.20 },
            { item: "leaf", probability: 0.17 },
            { item: "mushroom", probability: 0.10 },
            { item: "diamond", probability: 0.05 }
        ];
        var possible = items.some( ({item, probability}) => 
              item === desiredItem && probability > 0 );
        if (!possible) {
            console.log('There is no chance you\'ll ever find a ' + desiredItem);
            return;
        }
        var sum = items.reduce( (sum, {item, probability}) => sum+probability, 0 );
        while (true) {
            var value = Math.random() * sum;
            var lootedItem = items.find( 
                    ({item, probability}) => (value -= probability) <= 0 ).item;
            if (lootedItem === desiredItem) break;
            console.log("Dang! A " + lootedItem + " was found...");
        }
        console.log("Lucky! A " + desiredItem + " was found!");
    }
    
    findItem('diamond');

    【讨论】:

    • 这是一个非常酷的答案!
    • 感谢您的回答,非常有帮助!现在我想向items 数组添加另一个值,称为category? . The categories can be either 2, 5` 或10。所以假设diamond 项目将属于category: 10,当我运行findItem 时,只有属于同一类别的项目才会包含在所有可能性中。我已经尝试了几天,但似乎无法得到它。谁能把我推向正确的方向?谢谢!
    • 如果您有一个新问题,您应该将其作为新创建的问题提出。如果您想让我看一下,您可以在创建它后在此处发布对它的引用。无论如何,我将在接下来的 12 小时内离线,因此这是将其作为新问题发布的第二个原因:它会吸引其他能够帮助您的人。在新问题中,您当然可以参考这个问题,因为回答的人想使用此处发布的代码。
    • 感谢您的提示,我现在在stackoverflow.com/questions/40002440/…提出了另一个问题
    【解决方案2】:

    您可以对在 dice while 循环中使用的菱形问题使用相同的方法。只需生成一个介于 1-20 之间的随机数,如果生成的数字是 1,则告诉用户他们找到了钻石,因为生成 1 的几率为 5%。

    【讨论】:

      【解决方案3】:

      以下是允许任意加权概率的一般答案...我已经在我编写的几款游戏中成功使用了它。

      1. 对于每个项目,给它一个正概率。它不需要是一个 整数,它们的总和不需要为 1。
      2. 总结所有概率。总而言之。
      3. 生成一个介于 0 和 Total 之间的数字,即 Math.random() * total
      4. 对于每个项目,查看数量是否小于该项目的概率。如果是,则返回该项目。如果,不减去概率,继续下一项。

      【讨论】:

        【解决方案4】:
        const DIAMOND = 1,
              TRASH = 0;
        
        var treasures = [DIAMOND, TRASH, TRASH, TRASH, DIAMOND],
            len = treasures.length;
        
        function searchForDiamond() {
            while (true) {
                var j = Math.floor(getRandomArbitrary(0, len)),
                    discovery = treasures[j];
        
                if (discovery === DIAMOND) {
                    console.log("I am a lucky pirate!");
                    break;
                } else {
                    console.log("I am a crappy pirate!");
                }
            }
        }
        
        // FROM MDN
        // Returns a random number between min (inclusive) and max (exclusive)
        function getRandomArbitrary(min, max) {
            return Math.random() * (max - min) + min;
        }
        
        
        searchForDiamond();
        

        【讨论】:

          猜你喜欢
          • 2011-11-30
          • 2016-08-24
          • 1970-01-01
          • 2011-08-23
          • 1970-01-01
          • 1970-01-01
          • 2020-01-13
          • 1970-01-01
          • 2017-09-12
          相关资源
          最近更新 更多