繁体   English   中英

从数组中选择随机元素时如何获得平衡输出?

[英]How to get a balanced output when picking a random element from an array?

作为一个有趣的项目,我正在开发一个板球模拟器游戏,其中一个主要方面是每次交付的随机结果。

一般来说,在Test Cricket中,可能性如下:

“0”,“1”经常发生(60%的时间)

“2”,“3”适度发生(25%的时间)

“四”,“六”,“出”很少发生(10%的时间)

“WALL BALL”,“NO BALL”很少发生(2%的时间)

如果我有一个数组,如:

var possible_outcomes = ["0","1","2","3","FOUR","SIX","OUT","WIDE BALL","NO BALL"];

有什么能拉从一个随机的项目时,得到上述概率的最好方法possible_outcomes在固定的迭代次数,说60。

PS:如果你们中的一些人不知道这项运动,我很抱歉。 我使用了几个与板球相关的术语,因为我不知道如何更好地解释。

您可以生成0到100之间的随机数。 如果0 <number <10则运行0,如果20-25则运行2。 同样,如果我们获得100然后检票口。

IMO最简单但不那么花哨的解决方案是创建一个包含重复项目的数百个元素的数组:

var possible_outcomes = ["0","0","0","0","0","0","0","0","0","0",
"0","0","0","0","0","0","0","0","0","0",
"0","0","0","0","0","0","0","0","0","0",
"1","1","1","1","1","1","1","1","1","1",
"1","1","1","1","1","1","1","1","1","1",
"1","1","1","1","1","1","1","1","1","1",
,and so on...,
,"WIDE BALL","WIDE BALL","NO BALL","NO BALL"];

然后你只需从该数组中获取随机项。 不需要,如果需要或者需要转换箱子。

PS。 我不知道板球,但是如果不允许重复100次“0”,你总是可以从阵列中删除所选的选项,所以它不会再发生。

我建议使用连续检查概率和随机数的其余部分。

此函数首先将返回值设置为最后一个可能的索引并迭代,直到随机值的其余部分小于实际概率。

概率必须总和为1。

 function getRandomIndexByProbability(probabilities) { var r = Math.random(), index = probabilities.length - 1; probabilities.some(function (probability, i) { if (r < probability) { index = i; return true; } r -= probability; }); return index; } var i, action = ["0", "1", "2", "3", "FOUR", "SIX", "OUT", "WIDE BALL", "NO BALL", "other"], probabilities = [0.3, 0.3, 1 / 8, 1 / 8, 1 / 30, 1 / 30, 1 / 30, 0.01, 0.01, 0.03], count = {}, index; action.forEach(function (a) { count[a] = 0; }); for (i = 0; i < 1e6; i++) { index = getRandomIndexByProbability(probabilities); count[action[index]]++; } console.log(count); 
 .as-console-wrapper { max-height: 100% !important; top: 0; } 

您想要使用的技术称为“加权随机性”。 要在Javascript中实现此目的,您可以构建一个数组,该数组中填充的数量可能与给定的发生概率相匹配。 有关如何执行此操作及其工作原理的详细信息,请参阅此问题

在你的板球比赛的逻辑中,你可以使用循环来取出随机结果,直到击球手出局,如下所示:

 function weightedRand(spec) { var i, j, table = []; for (i in spec) { for (j = 0; j < spec[i] * 10; j++) { table.push(i); } } return function() { return table[Math.floor(Math.random() * table.length)]; } } var outcomes = weightedRand({ '0': 0.3, '1': 0.3, '2': 0.125, '3': 0.125, 'FOUR': 0.033, 'SIX': 0.033, 'OUT': 0.033, 'WIDE BALL': 0.01, 'NO BALL': 0.01 }); $('button').click(function() { clearInterval(interval); $('.innings').empty(); $(this).prop('disabled', true); var interval = setInterval(function() { var item = outcomes(); $('.innings').append('<div>' + item + '<div>'); if (item == 'OUT') { clearInterval(interval); $('button').prop('disabled', false); } }, 1000); }) 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <button>Start innings</button> <div class="innings"></div> 

请注意,概率与上面代码中指定的概率不完全匹配,因为它们不累加到1.00,但可以很容易地修改这些值。

一个容易改变的解决方案如下:

var cricket = [
    {
        name: 0,
        weight: 30
    },
    {
        name: 1,
        weight: 30
    },
    {
        name: 2,
        weight: 13
    }
    // ...
];

// Create the chances array by putting as many instances of a value in it, as it's weight

var chances = [];
for (var i = 0; i < cricket.length; i++) {
    for (var j = 0; j < cricket[i].weight; j++) {
        chances.push(cricket[i].name);
    }
}

// getting a value

var value = chances[Math.floor(Math.random() * chances.length)];

请原谅我的尴尬代码,但我希望你能将此视为解决方案吗? :d

 function repeatArray(value, len) { if (len == 0) return []; var a = [value]; while (a.length * 2 <= len) a = a.concat(a); if (a.length < len) a = a.concat(a.slice(0, len - a.length)); return a; } var zeroes = repeatArray("0", 30); var ones = repeatArray("1", 25); var twos = repeatArray("2", 15); var threes = repeatArray("3", 10); var fours = repeatArray("FOUR", 5); var sixes = repeatArray("SIX", 5); var wickets = repeatArray("OUT", 5); var extras = repeatArray("Extra", 5); var finalArr = []; finalArr = finalArr.concat(zeroes, ones, twos, threes, fours, sixes, wickets, extras); for (var i = 0; i < 20; i++) { var idx = Math.floor(Math.random() * finalArr.length); $("#out").append(finalArr[idx]+", "); } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div id="out"></div> 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM