【はじプロ】重複しない乱数を攻略:中級者にステップアップできる技術を解説してみた(失敗事例あり)

はじプロ解説
この記事はこんな人に読んでもらいたい
  • ランダム要素をもったゲームを作りたいあなた
  • 重複しない乱数の作り方を探しているあなた
  • はじプロに慣れてきて、中級レベルのプログラムを知りたいあなた
この記事を読めばこんなことがわかる
  • 重複しない乱数をつくるには、ランダムノードンからの出力を使わずに、順位を乱数として使う
  • 順位を決めるには総当たり表をつくる
  • 総当たり表をつくるには、くらべるノードンとNOTノードンを使う

お疲れ様です。YUmarunosuke(ゆうまるのすけ @YUmaru16061307)です。

YUmarunosukeのゲームは、毎回ちがう数字のならびかたで始まるよね?

このしくみはどうやってつくっているの?

それは『重複しない乱数』をつかっているからだよ。

以前、「ナビつき!つくってわかる はじめてゲームプログラミング」(はじプロ)で使用するランダムノードンについて解説をしました。

ランダムノードンの解説ページをつくったのは、次の2つの理由があったからです。

解説するノードンとしてランダムノードンをとりあげた理由
  1. YUmarunosuke がつくったゲームで使用しており解説したいから
  2. 『重複しない乱数』を見つけて感動したから

前段の会話のとおり、私がつくったゲームの最初は1〜4の数字を順番にタッチする、というものです。

しかし、毎回おなじ並び方だと、いくら時間制限があってもつまらないですよね?

だからランダムノードンを使って、ゲームが始まるたびにパネルに書かれる数字を変更するしくみを作りました。

YUmaru自作のゲーム画面
画面をタッチするゲームでは毎回数字の並び順が変わります。

しかし、私も自身でゲームをつくっている際、発生する乱数が重複(ちょうふく・じゅうふく)してしまう問題にぶち当たりました。

そのときに調べた際に見つけたプログラムが『重複しない乱数』だったのです。

ランダムノードンの出力をそのまま使うのではなく、ランダムノードンの大小関係を使ってランダムな順番を生み出す、という言葉では表現しにくいしくみが考えられています。

発想が柔軟だと思って感動し、ぜひ知ってもらいたいと思ったので、まずは基礎知識として必要なランダムノードンの解説をしました。

今回は、私が発想に感動した『重複しない乱数』の作り方について解説します。

なお、過去に私が作ったゲームをご紹介しています。

ぜひ一度ご覧になってから、あるいは何度かプレイしてから読んでいただければ、より理解が深まります。

重複しない乱数の作り方!ランダムノードン同士で『順位』をつけよう!

過去の記事【はじプロ】ランダムノードンを攻略:初心者がつまづきやすいポイントを解説してみたの復習です。

ランダムノードンの特徴を一言でいうと、

ランダムノードン = ビンゴゲームのガラガラ

でしたね。

ランダムノードンをわかりやすく例えると1
ランダムノードンをわかりやすく例えるとビンゴゲームのガラガラ

さて、今から次のようなゲームを作りたいと考えているとします。

今から作りたいゲーム

1、2、3の数字がかかれたパネルを順番にタッチする

ノードンガレージでつくろうとすると、まずはこのような形が思い浮かぶのではないかと思います。

重複しない乱数 やりがちな組み方
注記:タッチするプログラムは省いています

それぞれのランダムノードンでは、1〜3の数字が出力されるように設定しています。

ランダムノードンの設定

ゲームを開始すると、それぞれのランダムノードンに入力があり、ガラガラから出た数字(1〜3)を出力します。

うまくいけば、3つのランダムノードンから出力される数字がバラバラで、ゲームとして成り立ちます。

何も工夫をしていないときの結果その1

しかし、それぞれのランダムノードンは他のランダムノードンに興味はないので、

どれか2つ、あるいは3つ全部のランダムノードンが同じ数字を出力してしまう可能性もありますよね。

何も工夫をしていないときの結果その1

こうなってしまっては、ゲームのプレイヤーは、

どのパネルを押せばいいのかわからないよ・・・

と困ってしまいますよね。

では、1〜3の数字をかぶらせないようにするためには、どのような工夫が考えられるでしょうか?

プログラミングに正解はありませんので、もしかしたら別の方法があるのかもしれませんが、

今回解説する方法はつぎのとおりです。

ランダムノードンの出力(1〜3)をかぶらせないようにする工夫

それぞれのランダムノードンから出力された数値を使って『順位』をつけ、『順位』を乱数として表示する。

擬人化すると次のようなイメージです。

重複しない乱数の仕組み解説0
【前提】順位がわかりやすくなるように1〜10の数字をガラガラにいれます
重複しない乱数の仕組み解説1
重複しない乱数の仕組み解説1

ランダムノードンの出力をそのまま乱数として使うのではなく、『順位』というワンクッションを入れるというアイデアに気づいたときに、考案された方の頭の柔軟さに感動しました。

ガレージノードンでどうやってつくればいいの?

『重複しない乱数』をつくりあげるための考え方を示しました。

では、実際にかたちにするにはどのようにプログラミングをすればよいか、解説していきます。

さて、プログラムのなかで実現しなければならないゴールは次のとおりです。

重複しない乱数を表示させるために実現させなければならないこと
  • ランダムノードンに出力させる
  • 出力させた数値に対して順位をつける
  • 順位を数つきモノノードンに表示させる

ここで、皆さんに考えていただきたいのは2つめの『出力させた数値に対して順位をつける』です。

今回の例でいうと、

3つのランダムノードンそれぞれに対して、『1位』『2位』『3位』の冠をそれぞれ誰にかぶせるか?

を決めるプログラムを構築する必要があります。

順位を決めるには、ランダムノードン同士で対決させて、勝ち負けを決める方法がありますね。

では、どのようなプログラムを組むべきでしょうか?

この答えは、皆さんが生活しているなかで必ず見たことがある仕組みを使います。

スクロールをする前にちょっと考えてみましょう。

では解答です。下の図をご覧ください。

重複しない乱数の仕組み解説3
勝ったノードンには1点を与え、勝ち点の多さで順位を決めます

スポーツが好きな方はよく見るかもしれませんね。総当たり表です。

3つのランダムノードンの順位を決めるには、{(3×3)−3}÷2=3戦の勝敗を決める必要があります。

総当たり表をノードンガレージで作るには、どんなノードンを使えばよいでしょうか?

答えは、

  • くらべるノードン
  • NOTノードン

の2つを使います。使い方・考え方は次の図で解説します。

重複しない乱数の仕組み解説4
くらべるノードンとNOTノードンで総当たり表を埋めることができます

まずは、黄色のノードン(4)と緑色のノードン(9)をくらべるノードンを使って勝敗を決めます。

①くらべるノードンを使った勝敗判別のしかた
くらべるノードンの設定

入力1≧入力2なら1を出力する。入力1<入力2なら0を出力する。

くらべるノードンに入る入力と出力

入力1:黄色ランダムノードンの出力=4

入力1:緑色ランダムノードンの出力=9

入力1<入力2なので、くらべるノードンは0を出力する。

②NOTノードンを使った勝敗判別のしかた
NOTノードンに入る入力と出力

入力:くらべるノードンからの出力=0

出力:1

入力1<入力2なので、くらべるノードンは0を出力する。

この2つの手順を、残り2つの組み合わせ(黄色vs青色、緑色vs青色)についても行って総当たり表を完成させます。

これらのしくみを、実際にノードンガレージでつくりあげると次のようになります。

(ゲーム画面)

最後にくらべるノードン・NOTノードンからの出力を、けいさんノードンで足し合わせることによって『勝ち点』を求めます。

重複しない乱数の仕組み解説5r
くらべるノードンを使って勝ち負けを決めます(勝ち=1、負け=0)
重複しない乱数の仕組み解説6
総当たり表の反対側にあるNOTノードンへ出力します

最後に勝ち点から乱数をつくりだします。

勝ち点は0〜2、本来ほしい乱数は1〜3です。

ここで、先ほど示した総当たり表の『勝ち点』と『順位(=乱数)』を見てみると、

『勝ち点』+『順位(=乱数)』=3

という法則があることがわかると思います。

重複しない乱数の仕組み解説3
勝ち点と順位を足すと必ず3になります。

そこで、3から『勝ち点(0〜2)』を引くと、ほしい『乱数(1〜3)』を得ることができます。

重複しない乱数の仕組み解説9
3から勝ち点を引くとほしい乱数(1〜3)が得られます

なお、乱数4つにするには総当たり表を増やすだけ、つまりくらべるノードンとNOTノードンを増やすだけです。

オリジナルの作品:はじカミ Nintendo Switch『ナビつき! つくってわかる はじめてゲームプログラミング』のゲームID共有サイト 『重複しない乱数』と形は違いますが、仕組みは同じです。

興味がある方はぜひ見比べてみてください。

重複しない乱数の仕組み解説10
重複しない乱数4つバージョン

うまくいかなかったプログラミング方法

もともと、前述のプログラミングにめぐり合うまで、次のようなプログラミングを組んでいました。

重複しない乱数失敗作
重複しない乱数 失敗作
うまくいかなかった乱数作成のプログラミングの流れ
  1. ゲームスタート時に3つのランダムノードンに入力をいれる
  2. くらべるノードンをつかって、1つめと2つめの入力が同じならば、2つめのランダムノードンの「リセット」に入力をいれる
  3. くらべるノードンをつかって、1つめと3つめの入力が同じならば、1つめのランダムノードンの「リセット」に入力をいれる
  4. くらべるノードンをつかって、2つめと3つめの入力が同じならば、3つめのランダムノードンの「リセット」に入力をいれる

このプログラミングの問題点は3つありました。

YUmarunosukeがつくった重複しない乱数プログラムの問題点3点
  1. 出力される乱数が重複してしまう
  2. そもそも重複しない乱数がそろう前に処理が終わってしまう
  3. 重複しない乱数が準備されるまでに時間がかかる

手順2〜4で重複してしまった際に再度出力するようプログラムを組んでいます。

しかし、問題点の1つ目(重複してしまう)という問題が解決していないので、何度も何度もリセットしてしまいます。

そのため、重複しない乱数が完成するまで時間がかかってしまい、ゲームの仕様のせいなのか処理が止まってしまいました。

考え方としては間違っていないと思うのですが、このようにつくってもダメだと反面教師にしてください。

まとめ

今回は、はじプロで『重複しない乱数』の作る方法について解説を行っていきました。

本記事のまとめ
  • 重複しない乱数をつくるには、ランダムノードンからの出力を使わずに、順位を乱数として使う
  • 順位を決めるには総当たり表をつくる
  • 総当たり表をつくるには、くらべるノードンとNOTノードンを使う

もしかしたら、これ以外にも『重複しない乱数』をつくる方法はあるかもしれません。

以前、【親・指導者向け】プログラミング教育において子供にかけるべき言葉は?でもお話していますが、あるべき姿にさえ到達してしまえばどのような手順を作り上げてもよいのです。

プログラミング的思考を身に着けていくことができれば、今後たくさんの選択肢を思い浮かべることができるようになります。

今回の記事から『ノードンの組み方』だけを参考にするのではなく、ぜひ『考え方』や『発想』を自分のものにしていただけると、記事を頑張って書いた甲斐があります。

では、次の記事までごきげんよう。

コメント

はじプロから次のステップへ
詳細をチェック!
はじプロから次のステップへ
詳細をチェック!
タイトルとURLをコピーしました