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

第2章24 疑似乱数で任意の範囲の整数を表示しよう

イチからゲーム作りで覚えるC言語
第2章23 疑似乱数を使おう : PREV
NEXT : 第2章25 疑似乱数のシードを時間にする :

この記事でやること

前回はプロジェクト「0190_randomize」を新しく作り、疑似乱数についてお話ししました。

今回は、新しくプロジェクト「0195_generate_rand_with_range」を作り、前回からの続きで任意の幅で疑似乱数を生成する方法についてお話します。疑似乱数は、ランダムに生成する地形や、出現する敵など、いろいろなゲーム要素で使われる重要な概念です。

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

実際にプログラムを動かして結果を見てみましょう。プロジェクト「0195_generate_rand_with_range」を新しく作成し、ソースコード「RangedRandomize.c」を作成してみてください。

 
RangedRandomize.c
#include <stdio.h>
#include <stdlib.h>
int main() {
 srand(12345);
 printf("〇か×かを乱数で表示:");
 for (int i = 0; i < 10; i++) {
   int kisuuGuusuu = rand() % 2;
   if (kisuuGuusuu == 0) {
     printf("〇");
   } else {
     printf("×");
   }
 }
 printf("\n");
 printf("与えるダメージを乱数で表示:");
 int baseDamage = 10; // 必ず与える基礎ダメージ
 int habaDamage = 4; // 与えるダメージの幅
 for (int j = 0; j < 5; j++) {
   int damage = rand() % ( habaDamage + 1 ) + baseDamage;
   printf("%d, ", damage);
 }
 printf("\n");
}

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

RangedRandomize.cの実行結果
〇か×かを乱数で表示:〇〇××〇×××〇〇
与えるダメージを乱数で表示:14, 10, 13, 12, 14,

〇か×かをそれぞれ確率50%で表示しています。(実際には rand() 関数のなかで使われている疑似乱数生成法によって偏りがあったりします。)

またダメージを10~14の幅でランダムに生成して表示しています。

実行するパソコンの環境によっては、違う結果が出てくるかもしれません。

指定の幅の数を乱数で生成する

前回お話した、乱数を生成する rand() 関数ですが、0 ~ RAND_MAX の間の整数を生成する機能を持っていました。

実際にゲームなどで乱数を使うのであれば、0~10だったり、200~220 など、目的によって指定した範囲の中で乱数を生成してほしいですよね。

0か1の乱数を生成する

rand() 関数を使って 0 か 1 の 2パターンを生成するには、下の計算で実現できます。

0か1を生成するコード
rand() % 2

ランダムに生成される rand() を 2 で割った余りですね。2で割った余りの結果は 0 か 1 のみとなるため、 0 か 1 の 2 パターンを生成することができました。

10~30 の範囲で乱数生成する

例えば 10から30の範囲で乱数を生成したい時は、さきほどの 0 か 1 の乱数を生成する式を少し応用してあげることで実現できます。

0から20の範囲の乱数を生成するコード
rand() % 21

という式で、まず 0~20 の範囲で乱数を取り出すことができますね。

これに対して、10 を足すと、 範囲は 0+10 ~ 20+10  の乱数が生成されることになります。

10から30の範囲の乱数を生成するコード
rand() % 21 + 10

結果として、20 ~ 30 の範囲が生成できました。もうすこし式を汎用的にしてみると、

乱数を生成する範囲を指定
rand() % ( 生成したい数値の幅 + 1 ) + 生成したい下限値

となります。

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

今回のソースコードの中を追ってみましょう。2行目ですが、rand関数、srand関数を使うためにはソースコードの頭に #include <stdlib.h> を書く必要があります。

 
RangedRandomize.c
#include <stdlib.h>

これで rand 関数とsrand 関数がつかえるようになりました。

4行目で srand 関数を使用しています。

前のページでお話しましたが、srand 関数は乱数の種を設定する関数です。設定した値に従って乱数の系列を生成します。

今回は適当に乱数の種は「12345」で設定しました。

 
RangedRandomize.c
 srand(12345);

〇×の2通りをランダムで表示してみる

次に、for 文と if~else文、rand文を組み合わせて、〇×をランダムで表示している箇所を見ていきましょう。

 
RangedRandomize.c
 printf("〇か×かを乱数で表示:");
 for (int i = 0; i < 10; i++) {
   int kisuuGuusuu = rand() % 2;
   if (kisuuGuusuu == 0) {
     printf("〇");
   } else {
     printf("×");
   }
 }
 printf("\n");

5行目で「〇か×かを乱数で表示:」という文字を表示しています。右側に改行は入っていません。

6行目~13行目は for 文でのループ処理となっています。

for ( int i = 0 ; i < 10 ; i++ ) {…} ですので、 i が 0~9の間繰り返し処理を実行する(つまり合計 10 回実行される)ことになります。

7行目で、整数 kisuuGuusuu に 「rand() % 2」 の結果を代入しています。 「rand() % 2 」は「rand() で生成された乱数を、2で割った余り」ですので、答えは 0 か 1 になりすね。kisuuGuusuu に 0 か 1 が代入されることになります。

8行目~12行目は if ~ else 文です。こちらのページでお話した、条件によって違う処理をさせたい時に使う文を使っています。

9行目は、「もし kisuuGuusuu が 0」のときのみ実行されます。

11行目は、「もし kisuuGuusuu が 0 でないとき」のみ実行されます。

このランダムに〇か×を表示する処理を 10 回ほど繰り返し、for 文が完了します。

14行目の printf("\n"); で改行され、見た目をわかりやすく区切っています。

10~14の整数をランダムで表示してみる

ソースコードの続きで、今度は指定した範囲の整数をランダムで生成しています。

 
RangedRandomize.c
 printf("与えるダメージを乱数で表示:");
 int baseDamage = 10; // 必ず与える基礎ダメージ
 int habaDamage = 4; // 与えるダメージの幅
 for (int j = 0; j < 5; j++) {
   int damage = rand() % ( habaDamage + 1 ) + baseDamage;
   printf("%d, ", damage);
 }
 printf("\n");

15行目は「与えるダメージを乱数で表示:」を改行なしで表示しています。

16~17行目では変数を宣言&初期化しています。

18~21行目では for 文で繰り返し処理を行っています。

「for ( int j = 0 ; j < 5 ; j++ ) {…}」ですので、j が 0 から 4 の間、繰り返し処理を行うことになりますね。

19行目では下のような式になっています。

damage = rand() % ( habaDamage + 1 ) + baseDamage;

右辺の「rand() % ( habaDamage + 1 )」は「rand() % 5」と置き換えられます。乱数を 5 で割った余りですので、答えは 0~4  の乱数となります。

「0~4の乱数 + baseDamage」は「10~14の乱数」であり、変数 damage に結果が代入されます。

20行目では乱数の結果を表示しています。

「printf("%d, ", damage);」で 「damage の中身」+「,」カンマ を表示して、一つ一つのダメージがわかりやすいようにしています。

for 文が終了した後、22行目で改行して結果を読みやすくしています。

あとがき

今回はゲームで非常によく使われる rand 関数の使い方をお話しました。実際にゲーム内で使うときは、ゲームの環境によって乱数の結果が変わらないように、自分で乱数を生成するプログラムを書いてしまうことが多いと思います。

(乱数で生成されるマップデータなどを考えた時、別のPC上にデータを持って行って遊ぼうとしたらまったく違うマップになってしまっては困るなどの場合があります。)

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

ページの更新履歴

更新日 更新内容
2018.7.31 初版公開
2018.11.25 ソースコードのインデックスがおかしかったのを修正 アイキャッチ画像、トップ画像を追加
イチからゲーム作りで覚えるC言語
第2章23 疑似乱数を使おう : PREV
NEXT : 第2章25 疑似乱数のシードを時間にする :
 
 
送信しました!

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

なんかエラーでした

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

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

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

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

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

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

#ツール#ゲームプログラミング✎ 2021-01-24
ゲームなどで使えるループ画像、パターンテクスチャのツール、手動での作り方をまとめ
広告領域
追従 広告領域
目次
第2章24 疑似乱数で任意の範囲の整数を表示しよう
第2章24 疑似乱数で任意の範囲の整数を表示しよう
この記事でやること
この記事でやること
疑似乱数を行うプログラム
疑似乱数を行うプログラム
指定の幅の数を乱数で生成する
指定の幅の数を乱数で生成する
0か1の乱数を生成する
0か1の乱数を生成する
10~30 の範囲で乱数生成する
10~30 の範囲で乱数生成する
ソースコードを追ってみよう
ソースコードを追ってみよう
〇×の2通りをランダムで表示してみる
〇×の2通りをランダムで表示してみる
10~14の整数をランダムで表示してみる
10~14の整数をランダムで表示してみる
あとがき
あとがき
非常に参考になったサイトさまや、参考文献など
非常に参考になったサイトさまや、参考文献など
ページの更新履歴
ページの更新履歴
Nodachisoft © 2020