ゲームにはランダムな要素がだいたい必要です。ランダムな要素が無い場合は、パターンプレーが可能になります。それはそれでちゃんと計算されてゲームデザインされれば楽しいのですが、例えばカードゲームとかで、毎回同じ手しか出てこないのは大問題となります。今回はこの乱数に実装について解説していきます。
--
いきなりここに飛んで来ちゃった人は、よろしければ下記からご覧ください。
C言語基礎講座インデックス


  • 乱数を初期化する

乱数はC言語に標準でサポートされています。乱数を使うには <stdlib.h> #include します。必要な命令は、乱数の初期化取得の二つです。

srand(乱数の種);

これが初期化です。乱数の種は unsigned int です。ここで初めて unsigned という型が出てきました。unsigned とは、符号無しを指定する型指定子です。int や char 等の整数型にのみ指定する事が出来ます。特に指定がなければ、これらの整数型は符号付きですが、signed と符号付きとして明記する事も出来ます。※ 私は signed を使った事はありませんが…

話を乱数の種に戻します。乱数の種が同じだと、以後、乱数の取得は同じ順番でランダムな値が取得できるようになります。つまり再現性のある乱数が作れます。例えば、迷路の自動生成などで、この乱数の種を保存しておければ、出来あがった迷路データを保存しておかなくても、種さえ保存しておけば以前の迷路が再現できたりします。ドルアーガの塔の迷路はこのような仕組みでデータ量を減らしています。

再現性がない乱数にしたい場合は、この乱数の種は起動毎に変化する値が好ましいです。そこでオススメするのが時間です。C言語では、時間も最初から使えるようにライブラリ化されています。時間を使うには <time.h>#include します。時間の取得は

time_t t = time(NULL);


こんな記述となります。time が時間取得関数です。NULL を引数に与えていますが、戻り値で処理する場合は NULL を指定します。値の受け取りで time_t という不思議な型になっていますが、これは時間を受け取る別名定義された専用の型です。余談ですが、この型のサイズが32bitなシステムで2038年問題が起きます。最新のシステムでは64bitに拡張されています。

time() で取得できるのは現在時刻の連番ですが、これをそのまま乱数の種として扱ってしまいます。特に拘りがなければ乱数の初期化には

srand((unsigned)time(NULL));

このような記述で問題ないと考えます。この初期化は最初に一度呼び出しておくだけで良いため、main() の最初に記述しておくのが良いかと思います。なお、キャストの (unsigned) は unsigned int の省略形です。unsigned とすると自動的に符号無しの int として扱われます。この明示的なキャストがないと、VS2022 先生に警告を受けますのでご注意ください😁

※ HDDケースです。RAIDも何もありません。ではこのケースのメリットは何かというと、一本のケーブルでHDDを4台まとめてPCに接続できる事です。既にUSBで外付けHDDが2台繋がっている人なら、この恩恵が理解できるかも。超オススメします!


  • 乱数を使う

初期化が出来たら次は取得です。取得は rand() 関数を使います。

int num = rand();

たったこれだけで、num にランダムな値が入ります。ランダムな値の範囲はシステムによって異なりますが、VS2022 だと 32767 となっています。この最大値は RAND_MAX という定数がシステムによって定義されています。気になる場合は確認してください。

ランダムな値と言うだけあって、呼び出す毎に異なる値が返ります。例えば、

srand((unsigned int)time(NULL)); printf("%d\n", rand()); printf("%d\n", rand()); printf("%d\n", rand());

この単純なプログラムを動かすと実行するたびに…
実行結果1実行結果2実行結果3
このように表示される値が毎回変わります。範囲が大きいランダム値のままだと使いづらいので、自分が希望する範囲に乱数を変更したいですよね。そこで役に立つのが % 剰余算なのです。例えば、0 ~ 9 のランダムな値が欲しければ

int num = rand() % 10;

このように記述すれば、欲しい範囲のランダム値が手に入ります。-5 ~ +5 の範囲が欲しければ…

int num = (rand() % 11) - 5;


このように記述します。0 ~ 10 の値が剰余算で抜き出されてから、5 が引かれますので、目的の範囲を得る事が出来ます。% 剰余算の計算優先度に不安がある場合は、上記サンプルのように () を付けておくと良いでしょう。ちなみに今回の場合は計算優先度的には不要です。0 ~ 10 までの偶数が欲しければ…

int num = (rand() % 6) * 2;


これで OK です。

>> C言語013 ループに進む

※ NASでRAIDもとなるとお値段的にはこちらがオススメ。どうしても単にPC直付けと比べると少しお高くなりますが、データの信頼性は高くなります。長い目で見ればこちらがオススメです。