C初級:乱数の基本的な使い方

C言語初級カテゴリのロゴ画像 C言語初級

乱数についての大まかな説明

ゲームではプレイするたびに違う位置から敵が出現したりすることがあります。
ドラクエに出てきたゴーレムも一匹一匹HPが異なっていたりします。

ドラクエ‗ゴーレムのステータス画像

これには乱数というものを使って表現しています。
毎回違う数値を人間ではなくコンピュータに作らせるときに乱数を使う、と憶えておいてくれれば大丈夫です。

乱数は、c言語では、rand()関数を使うことで表現できます。
rand関数を使うにはヘッダーファイルstdlib.hを取り込む必要があるため、基本的な使い方は次の通りとなります。

乱数を表示するための基本的な記述

rand0.c

/* rand0.c: 乱数を使う */
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
	int x;

	x = rand();
	printf("x = %d\n", x);
	
	return 0;
}

実行結果

x = 130

解説
3行目:rand()関数を使うにはstdlib.hが必要です。
9行目:x = rand(); で乱数表から乱数を1つ取り出して変数xに代入しています。
ちなみに実行結果は何度実行しても変わりません(笑)
これでは、ぜんぜん乱数ではないですよね。
わたしの環境では、上記の通り130が何度実行しても表示されました。
理由は簡単です。
乱数表というものがコンピュータ内部にある、とイメージして下さい。
上記のプログラムは、その乱数表の先頭から順に乱数を取り出す処理をしています。

乱数表がこんな感じだったとして。

130
10982
1090
11656
7117
17595
6415
22948
31126
9004

:
:

並んでいる数値は、バラバラですが先頭の数値は、130と変わりません。
上記のプログラムでは、乱数表の先頭の数値を取り出して表示しているだけですので何度実行しても同じ数値が表示されるわけです。

毎回違う数字がでないと乱数とは言えません。

毎回違う乱数を表示するようにする

次に実行するたびに違う数を表示するようにプログラムを変更します。

これにはsrand関数をプログラムの先頭で1回だけ呼び出します。
srand関数は、引数に適当な数値を指定して

srand(123);

のように使いますが、このままでは残念ながら実行する度に違う数値とはなりません。
ですので通常は、

srand((unsigned)time(NULL));

のように現在時刻を指定して毎回違った引数にして使います。

rand1.c

/* rand1.c: 毎回違う乱数を表示する */
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main(void)
{
	int x;
	
	/* 乱数表に時間を掛け合わせる */
	srand((unsigned)time(NULL));
	
	/* 乱数を取得 */
	x = rand();
	printf("x = %d\n", x);
	
	return 0;
}

実行結果1

x = 3599

実行結果2

x = 11795

試しに

/* 乱数を取得 */
x = rand();
printf(“x = %d\n”, x);

の部分をループに入れて、10個の乱数を発生させてみます。

rand2.c

/* rand2.c: 乱数を10個表示する */
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main(void)
{
	int x, i;
	
	/* 乱数表に時間を掛け合わせる */
	srand((unsigned)time(NULL));
	
	/* 乱数を取得 */
	for(i=0; i<10; i++){
		x = rand();
		printf("x = %d\n", x);
	}
	
	return 0;
}

実行結果

x = 28591
x = 29616
x = 2049
x = 12088
x = 21870
x = 732
x = 17858
x = 24772
x = 7567
x = 17450

きちんと(というのも変ですが)バラバラな数値が表示されます。
乱数を使いたいときは、大抵指定した範囲の乱数が欲しいはずです。(たぶん)
次に乱数の範囲を指定した使い方を見ていきます。

乱数の範囲を指定して取得する

例として、

サイコロだと1~6の範囲。
ドラクエのゴーレムのHPだと53~70の範囲などなど。

rand()関数で取得できる乱数は、整数です。
%演算子を使って、割り算の余りを利用すると目的の範囲の乱数を取り出せます。

サイコロなら

x = rand() % 6 + 1;

とします。(xは整数型変数)

rand() % 6 だけですと、6で割った余りとなるので、0~5の範囲しか取得できません。
そこで1を足してrand() % 6 + 1としています。

先ほどのゴーレムであれば53~70の範囲なので、

x = rand() % 18 + 53;

となります。

実際のプログラム例 rand_range.c

/* rand_range.c: 指定範囲の乱数を発生させる */
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main(void)
{
	int x, i;
	
	/* 乱数表に時間を掛け合わせる */
	srand((unsigned)time(NULL));
	
	/* サイコロ(1~6)の乱数を取得 */
	printf("サイコロの目\n--------------------\n");
	for(i=0; i<10; i++){
		x = rand() % 6 + 1;
		printf("%2d\n", x);
	}
	
	/* ゴーレムのHP(53~70)の乱数を取得 */
	printf("\nゴーレムのHP\n--------------------\n");
	for(i=0; i<10; i++){
		x = rand() % 18 + 53;
		printf("HP: %2d\n", x);
	}

	return 0;
}

実行結果

サイコロの目
——————–
3
5
3
3
6
1
2
2
2
6

ゴーレムのHP
——————–
HP: 60
HP: 70
HP: 65
HP: 56
HP: 53
HP: 54
HP: 66
HP: 56
HP: 56
HP: 70

色々と応用は効くと思います。

コメント

タイトルとURLをコピーしました