Nodachisoft Nodachi Sword Icon
  
@あまじ✎ 2018年7月31日に更新

第2章23 疑似乱数を使おう

イチからゲーム作りで覚えるC言語
第2章22 繰り返し処理のネスト構造と break、continue などのジャンプ文 : PREV
NEXT : 第2章24 疑似乱数で任意の範囲の整数を表示しよう :

この記事でやること

前回はプロジェクト「0180_nested_loop」を新しく作り、繰り返し処理の入れ子(ネスト構造)についてお話ししました。

今回は、新しくプロジェクト「0190_randomize」を作り、疑似乱数についてお話します。疑似乱数は、ランダムに生成する地形や、出現する敵など、いろいろなゲーム要素で使われる重要な概念です。

疑似乱数を行うプログラム

疑似乱数を使ったソースコードを実際にプログラムを動かして結果を見てみましょう。プロジェクト「0190_randomize」を新しく作成し、ソースコード「DispRandom.c」を作成してみてください。

 
DispRandom.c
#include <stdio.h>
#include <stdlib.h>
int main() {
 unsigned int randomSeed = 123;
 srand( randomSeed );
 for (int i = 1; i < 4; i++) {
   int gold = rand();
   printf("%d 個目の宝箱の中身は金貨が %d 枚でした。\n", i, gold);
 }
}

このコードを実行してみるとこんな結果になったかと思います。

DispRandom.cの実行結果
1 個目の宝箱の中身は金貨が 440 枚でした。
2 個目の宝箱の中身は金貨が 19053 枚でした。
3 個目の宝箱の中身は金貨が 23075 枚でした。

宝箱の中身(金貨)がランダムにとれます。実行するパソコンの環境によっては、違う枚数が出てくるかもしれません。

疑似乱数とは

疑似乱数(imp}pseudo-random numbers)とは、完全なランダムではなく何かの規則に従って出力される(一見)ランダムな数値のことです。今回のプログラムも一見ランダムに金貨の枚数が出ているように見えますが、このプログラムをもう一度実行してみた結果を確認してもらうと、まったく同じ順番で同じ数(金貨の枚数)がでます。

疑似乱数をつくる関数やシステムのことを疑似疑似乱数列生成器と呼びます。

様々なゲームで乱数は使われています。挙げたらきりがないですが、例えば、

  • 自動生成されるマップ
  • 適当な距離を歩くとランダムで出現するモンスター
  • カジノゲーム

などです。疑似乱数列生成器は、キーとなる値を指定すると、キーとなる値から計算した同じ乱数の結果(数列)を返してくれるように作られているものが多くあります。このキーとなる値を乱数の種(Random Seed)とよく呼びます。サンドボックス系のゲームではマップのシード値とか呼ばれてたりします。

C言語であらかじめ用意されている疑似乱数の関数を使うには、

include <stdlib.h> を書いてあげる必要があります。

ソースコードを追ってみよう

今回のプログラムのソースコードを一行づつ追ってみましょう。

 
DispRandom.c
int main() {
 unsigned int randomSeed = 123;
 srand( randomSeed );

4行目では、unsigned int 型(負の値をとらない int 型)で変数 randomSeed に 123 を代入しています。

5行目の srand関数乱数の種を設定する関数です。

関数 srand の1つ目の引数(第1引数)に randomSeed を設定して関数を呼び出しています。

ワンポイント

srand の s は seed for a new sequence of pseudo-random numbers (疑似乱数が生成する新しい系列のシード値)の略っぽい気がしますが、 元ネタの記載がみつからず、本当の正解はわからずです。分かる方、いらっしゃったら教えてくださいー。 この乱数の種(今回なら変数 randomSeed )が違う整数なら、違う乱数の数値が違う順序で吐き出されることになります。

6行目~9行目は for 文によるループとなっています。

ループするとき変数 i が 1,2,3,4 と増えていき、4となったとき、ループが終了します。

ですので、3回、for 文の繰り返し処理が実行されることになりますね。

 
DispRandom.c
 for (int i = 1; i < 4; i++) {
   int gold = rand();
   printf("%d 個目の宝箱の中身は金貨が %d 枚でした。\n", i, gold);
 }

7 行目は、int型の変数 gold に rand() の結果を代入しています。

この rand() 関数は、疑似乱数を生成して整数を返します。呼び出すたびに、異なる整数が疑似乱数のアルゴリズムによって生み出され、返ってきます。

8 行目で、変数 i と gold の中身を表示しています。

ワンポイント

N1570 の仕様によるとsrand 関数を使わずに rand 関数を使った場合、自動的に最初に srand( 1 ) と設定したものと同じ乱数が生成されるようです。

rand() 関数が生成する乱数の幅

rand() 関数は呼び出すたびに、C言語側で用意されたアルゴリズムに従って整数を生成します。この乱数は 0以上、少なくとも 32767 以下の範囲で数値を生成します。

{uyelllow}乱数の生成する値の最大は「少なくとも 32767」ということまでは仕様で決まっていますが、 実際にはもっと大きな数をかえすようなアルゴリズムが使われている可能性があります。

自身のビルド環境で、rand()が返す最大値を確認するには、

rand()が返す最大の値
printf("rand()が返す最大の整数 = %d\n", RAND_MAX);

として、実行すると、乱数で得られる最大の整数である RAND_MAX の中身を見ることで表示できます。

あとがき

乱数を使えるようになったことで、いままで同じ結果しか得られなかったアプリが、だいぶゲーム性らしさが出てくるようになると思います。

実行するたびに、異なる結果がでてくるようなプログラムについては次回お話しようと思います。

今回はここまで。おつかれさまでした。

非常に参考になったサイトさまや、参考文献など

ページの更新履歴

更新日 更新内容
2018/7/31 初版公開
2018/11/24 ゴミの記載が残っていたので削除
2018/11/25 アイキャッチ画像作成
イチからゲーム作りで覚えるC言語
第2章22 繰り返し処理のネスト構造と break、continue などのジャンプ文 : PREV
NEXT : 第2章24 疑似乱数で任意の範囲の整数を表示しよう :
 
 
送信しました!

コメント、ありがとうございます。

なんかエラーでした

ごめんなさい。エラーでうまく送信できませんでした。ご迷惑をおかけします。しばらくおいてから再度送信を試していただくか、以下から DM などでご連絡頂ければと思います。

Twitter:@NodachiSoft_jp
お名前:
 
連絡先:
 
メッセージ:
 
戻る
内容の確認!

以下の内容でコメントを送信します。よろしければ、「送信」を押してください。修正する場合は「戻る」を押してください

お名前:
 
連絡先:
 
メッセージ:
 
Roboto からの操作ではないという確認のため確認キーを入れてください。
確認キー=95
戻る
 / 
送信確認へ
コメント欄
コメント送信確認へ

関連ありそうな記事(5件)です!

ゲーム等で使えるつなぎ目のないループするテクスチャ画像の作り方

#ツール#ゲームプログラミング✎ 2021-01-24
ゲームなどで使えるループ画像、パターンテクスチャのツール、手動での作り方をまとめ
広告領域
追従 広告領域
目次
第2章23 疑似乱数を使おう
第2章23 疑似乱数を使おう
この記事でやること
この記事でやること
疑似乱数を行うプログラム
疑似乱数を行うプログラム
疑似乱数とは
疑似乱数とは
ソースコードを追ってみよう
ソースコードを追ってみよう
あとがき
あとがき
非常に参考になったサイトさまや、参考文献など
非常に参考になったサイトさまや、参考文献など
ページの更新履歴
ページの更新履歴
Nodachisoft © 2020