LoginSignup
7
5

More than 3 years have passed since last update.

要素ごとにランダムに抽出される確率(重み付け)を設定する

Last updated at Posted at 2018-01-30

なんだこれ

いわゆるガチャテーブル、『 重み付き乱択 』をes6で実装してみました。
特定のバナー画像だけ他のバナー画像よりも少し多めに表示させたり、簡易的に負荷分散をさせたり、、と使う場面は多そうです。

1. 実装

// ダーツ投げる
const throwDarts = awards => {
  const hit = rand(1, dartboard(awards));
  return dartboard(awards, hit);
}

// ダーツ盤
const dartboard = (awards, hit) => {
  let area = 0;
  for (let key in awards) {
    area += awards[key];
    if (hit && (area >= hit)) return key;
  };
  return area;
}

// 乱数(min ~ max)
const rand = (min, max) => {
  return Math.floor(Math.random() * (max - min + 1) + min);
}

// 賞品テーブル
const awards = {
  'たわし': 7,
  '温泉旅行': 2,
  'パジェロ': 1
}

// 実行
console.log(throwDarts(awards)); // たわし

メインとなる関数は dartboard() ですが、たったこれだけです。
おわかりいただけたでしょうか。

『関口宏の東京フレンドパークII』の最後にやっていた、回転するダーツ盤にダーツを打ち込むイメージです。
849be8af-a664-4452-9615-d7455ca77ce9.jpg

2. 解説

throwDarts()
const hit = rand(1, dartboard(awards));

ここでの dartboard(awards) は 賞品テーブル awards合計値(10) を返します。
乱数 hit はダーツの 着弾地点(1~10) を示します。

dartboard()
  let area = 0;
  for (let key in awards) {
    area += awards[key];
    if (hit && (area >= hit)) return key;
  };

area はダーツ盤における 賞品の面積 です。
各賞品の面積を for ループで加えていき、 hitarea の範囲内ならば賞品名を返します。
当然、面積が広い賞品ほど刺さりやすく、逆に狭い賞品には刺さりにくくなります。

goods_tawashi.png
例えると簡単ですね。
ロジックは分かったので精度を検証してみましょう。

3. 検証

100万回投げた

const awards = {
  'たわし': 50,
  '画力': 8,
  '筋力': 8,
  '集中力': 8,
  '健康': 8,
  '優しい性格': 8,
  '5000兆円': 8,
  'パジェロ': 2
}

const results = {
  'たわし': 0,
  '画力': 0,
  '体力': 0,
  '集中力': 0,
  '健康': 0,
  '優しい性格': 0,
  '5000兆円': 0,
  'パジェロ': 0
}

for (let i=0; i<1000000; i++) {
  results[throwDarts(awards)]++;
}

console.log(results);

結果

Object {
  5000兆円: 79486,
  たわし: 500800,
  パジェロ: 20037,
  健康: 79943,
  優しい性格: 79549,
  画力: 80002,
  体力: 79774,
  集中力: 80409
}

よさそう

よさそうです

4. 参考

7
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
5