ゲームの「ランダム」は本当にランダムか
遊びを見つける執筆にClaudeを使用しています。

サイコロを振るたびに違う目が出る、宝箱を開けるたびに違うアイテムが入っている——ゲームの中の「ランダム」は、見た目には偶然そのものです。しかし、コンピューターはそもそも決まった計算しかできない機械です。では、あの「バラバラな数」はどこから来ているのでしょうか。 結論から言うと、ゲームで使われる乱数のほとんどは「擬似乱数(ぎじらんすう)」と呼ばれる、計算で作り出した数列です。本当の意味でランダムではなく、出発点となる数(シード値)が同じならまったく同じ順番で繰り返されます。これを知っているかどうかで、ゲームの見え方はかなり変わります。 この記事では、擬似乱数の仕組み・ゲームデザインへの応用・「ランダムに見せる」工夫・そして作る側が意識すべき判断基準を、順を追って整理します。
擬似乱数とは何か
擬似乱数は、ある数学的な計算式に「種」となる数(シード値)を与えることで生成される数列です。代表的なアルゴリズムに「メルセンヌ・ツイスター」があり、JavaScriptのMath.random()など多くの環境で広く使われてきた仕組みの土台になっています。
重要な性質が二つあります。
- 再現性:同じシード値を与えると、同じ乱数列が出続けます。
- 周期性:十分に長い数列ですが、いつかは同じパターンに戻ります。
シード値には、多くの場合「現在時刻のミリ秒」や「ユーザーのマウス動作」などが使われます。毎回違う瞬間に起動するため、プレイヤーには毎回違う結果に見えます。しかし出発点が固定されたゲームでは、まったく同じ操作を繰り返すと同じ結果が再現できます。「ツール支援プレイ(TAS)」でゲームが完璧な再現を見せるのは、この性質を利用しています。
ゲームデザインでどう使われるか
擬似乱数はゲームの至る所に組み込まれています。RPGの「会心の一撃」の発生率、カードゲームのデッキシャッフル、横スクロールアクションの敵出現パターン、ローグライクのマップ生成——これらはすべて計算された乱数列が動かしています。
ここで興味深いのが「シード共有」という遊び方です。マップや世界がシード値で決まるゲームでは、そのシード値を友人に教えると相手がまったく同じ地形でプレイできます。有名なサンドボックスゲームで長年親しまれてきた文化で、「良いシードを探す」という攻略行動すら生まれています。
一方、カードゲームやガチャ系のゲームでは「連続して外れが続く確率」が問題になることがあります。純粋な確率計算では「10回連続でハズレ」も起こり得ますが、これがプレイヤーの不満に直結します。そこで多くのゲームは「天井」や「保証システム」を設け、一定回数以内には必ず当たりが出るよう乱数を補正しています。これは「ランダムに見えるが、実は管理された乱数」です。
「ランダムに感じさせる」設計の工夫
純粋な擬似乱数をそのまま使うと、人間には「ランダムっぽくない」と感じられることがあります。コインを10回投げたとき、表が7回続く場面があっても統計的には不思議ではありません。しかし人はそれを見て「何かおかしい」と感じます。
この現象を踏まえ、ゲームデザイナーは次のような調整を加えます。
- 直近の結果を避ける補正:同じ結果が連続しないよう、直前の履歴を乱数に反映させる。
- バッグ方式:カードゲームでいう「デッキから引く」発想で、一定のサイクル内で各結果が均等に出るよう管理する。テトリスの「7-bag」方式が有名です。
- 確率の動的変動:外れるたびに当選確率を少しずつ上げ、当たったらリセットする「ルーレット補正(プソイドランダム分布)」。MOBAジャンルのゲームでクリティカル率の管理に使われます。
これらは「ランダムらしく感じさせる」ための意図的な介入です。純粋な乱数より「人間の感覚に寄り添った乱数」のほうがゲームとして楽しいという判断が背景にあります。
真のランダムが必要な場面とその入手方法
オンラインカジノや一部の競技ゲームでは、擬似乱数では足りない場面があります。計算式で再現できる数列は、理論上は予測できてしまうからです。
こうした場面で使われるのが「真の乱数(ハードウェア乱数)」です。放射性崩壊・熱雑音・光子の経路といった物理現象の測定値を乱数の源泉とします。OSレベルでは/dev/random(Linux)などがこれに近い仕組みを提供しており、暗号用途ではこちらが推奨されます。
ブラウザゲームを作る場合、暗号学的に安全な乱数が必要ならcrypto.getRandomValues()というWebの標準APIを使う選択肢があります。Math.random()より処理は重めですが、予測困難性が必要な場面(チート対策・公平性の保証が求められる対戦など)では有効です。ただし「ゲームを楽しく動かす」だけの用途なら、Math.random()で十分なケースがほとんどです。
作り手として知っておきたい判断基準
ゲームに乱数を組み込むとき、「どの乱数をどこに使うか」は品質に直結します。以下の考え方が判断の出発点になります。
用途で使い分ける
- 演出・エフェクトのバラツキ、推奨する乱数の種類:Math.random()、理由:予測困難性不要、軽量
- マップ・ステージ生成、推奨する乱数の種類:シード付き擬似乱数、理由:再現性が必要
- 暗号・対戦の公平性保証、推奨する乱数の種類:crypto.getRandomValues()、理由:予測不能性が必要
「外れが続く」問題への対処
レアアイテムの抽選など、連続外れがプレイヤー体験を大きく損なう場面では、バッグ方式や天井設計を最初から組み込むことを検討します。後から追加するより、設計段階で考えておくほうが修正コストが低くなります。
シード管理と再現性
バグ報告を受けたとき「あの時の乱数列を再現できるか」は、デバッグの難易度を左右します。ゲームの起動時シードをログに残す習慣をつけておくと、再現困難なバグの追跡がしやすくなります。
見た目のランダム感
同じ種類のイベントが短い間隔で連続しないよう、直近履歴を参照した補正を加えるだけで、プレイヤーの「不公平感」が下がることが多いです。乱数の質より「感じさせ方の設計」が体験を決める場面は少なくありません。
次の行動
ゲームの乱数を試したいなら、まずブラウザの開発者コンソールでMath.random()を何度か呼んでみるのが手軽な出発点です。シード付き擬似乱数を試したい場合は「seedrandom.js」などのライブラリが公開されていますので、公式ドキュメントで使い方を確認してみてください。作ったゲームをほかの人に遊んでもらいたいときは、HTMLファイルやZIPをアソバース(https://aso-verse.com)に投稿して公開できます。
参考資料
- MDN Web Docs「Math.random()」
- MDN Web Docs「Crypto.getRandomValues()」
- Mersenne Twister公式サイト(松本眞・西村拓士)
- Wikipedia「擬似乱数生成器」



