■この記事の概要
この記事では、C言語の乱数関数rand()が同じ結果を返す問題を解決する方法を解説します。
rand()を正しく使うためには、srand()関数を使用して乱数の種(シード)を設定する必要があります。
例として、srand(time(NULL))を使ったコードも紹介し、毎回異なる結果を得る方法を詳述しています。
実務ではより安全なrandom()関数の使用も推奨されています。
■乱数の種まきをする
●srand関数による乱数の種まきをしないと
結果がいつも同じになります。
●実務ではrand関数よりrandom関数を使おう。
■乱数の種をまかないと結果はいつも同じ
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void 乱数の種なし(void){
printf("%s\t",__func__);
for(int i = 0 ;i<10;i++){
switch (rand() % 4) {
case 0: printf("風"); break;
case 1: printf("林"); break;
case 2: printf("火"); break;
case 3: printf("山"); break;
}
}
printf("\n");
}
int main(void){
乱数の種なし();
}
乱数の種を蒔いていないので、何度実行しても同じ結果になります。
●乱数の種を蒔かないと毎回同じ実行結果
+ ./a.out
乱数の種なし 山火林山林山火風林林
+ sleep 1
+ ./a.out
乱数の種なし 山火林山林山火風林林
+ sleep 1
+ ./a.out
乱数の種なし 山火林山林山火風林林
+ sleep 1
+ ./a.out
乱数の種なし 山火林山林山火風林林
+ sleep 1
■乱数の種まきを追加した例
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void 乱数の種あり(void){
printf("%s\t",__func__);
srand((unsigned int) time(NULL));//★乱数の種まき=seed設定
for(int i = 0 ;i<10;i++){
switch (rand() % 4) {
case 0: printf("風"); break;
case 1: printf("林"); break;
case 2: printf("火"); break;
case 3: printf("山"); break;
}
}
printf("\n");
}
int main(void){
乱数の種あり();
}
srand関数を使用して乱数の種を蒔きます。
乱数の種として現在時刻time(NULL)を使用するのが一般的です。
●毎回違う実行結果
+ ./a.out
乱数の種あり 風火風山林山火山山山
+ sleep 1
+ ./a.out
乱数の種あり 山火風火火風山火林火
+ sleep 1
+ ./a.out
乱数の種あり 火山火林風山火風林火
+ sleep 1
+ ./a.out
乱数の種あり 風山山火林林風風火林
+ sleep 1
注意:1秒以内に ./a.out を連打すると、
time(NULL)の結果が変わらないので乱数の結果も変わりません。
■じゃんけんプログラムの例
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
typedef enum {
グー,チョキ,パー,
} じゃんけん;
int main(void) {
srand((unsigned int)time(NULL));
for(int i = 1; i <= 10; i++) {
printf("%d回目: ", i);
じゃんけん 私 = rand() % 3;
じゃんけん 貴方 = rand() % 3;
switch(私){
case グー:
switch(貴方){
case グー: puts("引き分けGG"); break;
case チョキ: puts("私の勝ちGC"); break;
case パー: puts("私の負けGP"); break;
}
break;
case チョキ:
switch(貴方){
case グー: puts("私の負けCG"); break;
case チョキ: puts("引き分けCC"); break;
case パー: puts("私の勝ちCP"); break;
}
break;
case パー:
switch(貴方){
case グー: puts("私の勝ちPG"); break;
case チョキ: puts("私の負けPC"); break;
case パー: puts("引き分けPP"); break;
}
break;
}
}
}
ここまで読んでいただいて恐縮ですが乱数を生成には
rand関数ではなくて
random関数のほうが良いそうです。
詳細は下記CERT-Cを参照ください。