分配 Javascript 中洗牌的概率

Assign probabilities to shuffle in Javascript

我有以下数组:

var myArray =  [BF1,BA1,BF2, BA2, BF3,BA3, BA4, BF4 , BA5, BF5, BF6, BA6, BF7, BA7, BA8, BF8, BA9, BF9, 
                BF10, BA10, BA11, BF11, BA12, BF12, BA13, BF13, BA14, BF14, BA15, BF15, BA16, BF16, BF17, BA18, 
                BF18, BA19, BF19, BA20, BF20, BA21, BF21, BF22, BA22, BA23, BF23, BA24, BF24, BA25, BF25, BA26, 
                BA27, BF27, BA28, BF28, WA29, WA30, WF30, WA31, WA31, WF32, WA32, WF33, WA33, WF34, WA34, 
                WF35, WA35, WA36, WA37, WA38, WF38, WA39, WF40, WA40, WA41, WF41, WA42, WF42, WF43, WA43, 
                WF44, WA44, WF45, WA45, WF46, WF46, WA47, WF47, WA48, WF48, WF49, WA49, WA50, WF50, WF51, 
                WA51];

我使用以下函数进行随机播放,这样 shuffle(myArray);

function shuffle(array){
    var counter = array.length,
        temp, index;
    while (counter > 0){
        index = Math.floor(Math.random() * counter);
        counter = counter-1;
        temp = array[counter];
        array[counter] = array[index];
        array[index] = temp;
    }
    return array;

不过,我想用概率来洗牌。这样 myArray 中以 B (BF1,BA1,BF2...BF28) 开头的项目有 0.8 的概率成为数组中的第一个项目,而以 W 开头的项目 (WA29,WA30,WF30...WA51)有 0.2 的概率成为数组中的第一项。

我可以使用 math.random 执行此操作吗?或者我应该使用其他东西?

提前致谢!

我假设你的意思是,当你选择第一个项目时,'B' 被加权,因此它们被第一个选择的可能性是原来的 4 倍。例如,如果我们有两个项目 B1 和 W1,那么您最终得到 ['B1', 'W1'] 的可能性为 80%,而最终得到 ['W1', 'B1'] 的可能性为 20%。如果您有四个项目 B1、W1、W2、W3,则 B1 优先(加权)的可能性为 80/140,W1、W2 或 W3 中的每一个优先的可能性为 20/140。如果 B1 是第一个,则每个剩余​​的 W 项都有相等的机会成为下一个。如果 W 是第一位,那么 B1 有 80/120 的机会成为第二位。等等...

一种方法是对剩余列表中的每个项目进行称重,并根据总概率计算一个随机数,然后遍历列表直到达到该数字。例如,B1 = 0.8、B2 = 0.8、W1 = 0.2、W2 = 0.2。所以你计算一个随机数 >0 = 且 < 2.0。说它是1.7。 运行 总数为 B1 = 0.8,B2 = 1.6,W1 = 1.8,W2 = 2.0。由于它大于 B2 且小于 W1,因此您选择 W1。

对于一个包含两个字符的简单列表,将数组拆分为 W 和 B,然后为每个组成一个数组,然后计算一个随机数(加权)用于从中选择的数组,然后另一个从该数组中选择哪个项目的随机数。

var myArray =  ['BF1','BA1','BF2','BA2','BF3','BA3','BA4',
'BF4','BA5','BF5','BF6','BA6','BF7','BA7',
'BA8','BF8','BA9','BF9','BF10','BA10',
'BA11','BF11','BA12','BF12','BA13','BF13',
'BA14','BF14','BA15','BF15','BA16','BF16',
'BF17','BA18','BF18','BA19','BF19','BA20',
'BF20','BA21','BF21','BF22','BA22','BA23',
'BF23','BA24','BF24','BA25','BF25','BA26',
'BA27','BF27','BA28','BF28','WA29','WA30',
'WF30','WA31','WA31','WF32','WA32','WF33',
'WA33','WF34','WA34','WF35','WA35','WA36',
'WA37','WA38','WF38','WA39','WF40','WA40',
'WA41','WF41','WA42','WF42','WF43','WA43',
'WF44','WA44','WF45','WA45','WF46','WF46',
'WA47','WF47','WA48','WF48','WF49','WA49',
'WA50','WF50','WF51','WA51'];
                
const shuffle = arr => {
  let bs = [], ws = [];
  arr.forEach(ele => {
    if (ele[0] === 'B') {
      bs.push(ele);
    } else {
      ws.push(ele);
    }
  });
  
  let result = [];
  while (bs.length > 0 || ws.length > 0) {
    let bProbability = bs.length * 0.8;
    let wProbability = ws.length * 0.2;
    let totalProbability = bProbability + wProbability;
    let whichRandom = Math.random() * totalProbability;
    if (whichRandom < bProbability) {
      let index = whichRandom * 
          bs.length / bProbability;
      result.push(bs.splice(index, 1));
    } else {
      let index = (whichRandom - bProbability) *
          ws.length / wProbability;
      result.push(ws.splice(index, 1));
    }
  }
  return result;
}

let sorted = shuffle(myArray);
console.log(sorted);

您可以使用此函数生成(伪)随机数,如果它小于概率(介于 0 和 1 之间,区间:[0,1)),则 return 为真或假。取决于结果,您可以或不执行某些操作:

const isInProbability = (probability) => {
  const rand = Math.random();
  return rand < probability;
 };

记住 Math.random() 生成一个伪随机数。如果您需要更多安全性,请使用 crypto.getRandomValues() (https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Math/random)