目次/第02章
02Rng
同じ種からは、同じ野菜が生える
seeded pseudo random — シード付き擬似乱数
この章の3行まとめ
- 野菜を1個ずつ違う形にするには乱数が要りますが、
Math.random()は使いません。 - やり直しがきかないからです。いい形が出ても、二度と同じものは作れません。
- そこで「種(シード)」を渡すといつも同じ順番で数字が出る乱数を、自分で作ります。
野菜を1個ずつ違う形にするには乱数が要ります。でも Math.random() は使いません。
理由は単純で、やり直しがきかないからです。
「さっき出たあのジャガイモ、いい形だったな」と思っても、二度と同じものは出てきません。
バグを見つけても、同じ状況を再現できません。
そこでシード(種)付きの乱数を自分で書きます。整数をひとつ渡すと、 そこから決まりきった順番で数字が出てくる仕組みです。同じシードなら何度でも同じ列が出ます。 「ランダムに見えるけれど、実は完全に予測できる」——だから擬似(ぎじ)乱数と言います。
class Rng { constructor(seed) { this.s = seed >>> 0; } next() { this.s = (this.s + 0x6D2B79F5) | 0; let t = Math.imul(this.s ^ (this.s >>> 15), 1 | this.s); t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t; return ((t ^ (t >>> 14)) >>> 0) / 4294967296; } range(a, b) { return a + (b - a) * this.next(); } gauss(m, sd) { /* 平均 m・ばらつき sd の正規分布 */ } }
>>> や ^ は数字を2進数として混ぜる演算です。
桁をずらして重ねて、掛けて、また混ぜる。カードをシャッフルするのに近い操作で、
「規則性はあるのに人間には読めない」状態を作っています。
0x6D2B79F5 のような数は、混ざり方がよくなるように選ばれた定数です。
実験 — 種をまいてみる
同じ番号を入れれば、何度でもまったく同じ5本が生えます。
つまずきポイント
乱数の使い道は「バラバラにする」ことではなく「ありそうなばらつきを作る」ことです。
太さを完全にランダムにすると、実物には存在しない極端な個体が混ざります。
だからコードでは gauss()(正規分布)を多用します。
平均のまわりに集まり、たまに少し外れる——実物の野菜の分布はこの形です。
やってみよう
- 同じシードを2回入れて、まったく同じ形が出ることを確かめる。
- 気に入った形が出たシードの数字を、メモしておく。これが「保存」になります。
- ニンジン.js の
START_SEED(175行目あたり)を自分の誕生日(例 20260801)にして実行する。