簡體   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