使用概率遍历项目数组
Loop through array of items using probability
我是 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!");
我已经自己尝试了一段时间,但似乎无法得到它,所以任何帮助将不胜感激。谢谢!
您可以使用与在 dice while 循环中使用的相同方法来解决钻石问题。只需生成一个 1-20 之间的随机数,如果生成的数字是 1,则告诉用户他们找到了钻石,因为生成 1 的几率是 5%。
下面是一个允许任意加权概率的一般答案...我在我编写的一些游戏中成功地使用了它。
- 对于每个项目,给它一个正概率。它不需要是一个
整数,它们的总和不需要为 1。
- 求和所有概率。称其为总计。
- 生成一个介于 0 和 Total 之间的数字,又名 Math.random() * total
- 对于每个项目,查看数字是否小于该项目的概率。如果是,return 那个项目。如果,不减去概率,进行下一项。
这是一个 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');
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();
我是 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!");
我已经自己尝试了一段时间,但似乎无法得到它,所以任何帮助将不胜感激。谢谢!
您可以使用与在 dice while 循环中使用的相同方法来解决钻石问题。只需生成一个 1-20 之间的随机数,如果生成的数字是 1,则告诉用户他们找到了钻石,因为生成 1 的几率是 5%。
下面是一个允许任意加权概率的一般答案...我在我编写的一些游戏中成功地使用了它。
- 对于每个项目,给它一个正概率。它不需要是一个 整数,它们的总和不需要为 1。
- 求和所有概率。称其为总计。
- 生成一个介于 0 和 Total 之间的数字,又名 Math.random() * total
- 对于每个项目,查看数字是否小于该项目的概率。如果是,return 那个项目。如果,不减去概率,进行下一项。
这是一个 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');
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();