前回、乱数の種について書きましたが、同じ種からは決まった順序で乱数が発生することが問題となりました。
それを解決する策として、時間を使うと言いましたが、時間の取得を考えて見ましょう。
コンピュータでの時間は、どのように管理されているのでしょうか。
多くの方はWindowsを使っていると思いますので、画面の右下に時刻が表示されていると思います。
この時間を取得してきます。
当然時計が狂っていれば、正確な時間は取得できませんが、今回は正確な時刻は必要ありません。
なぜか?は後述します。
<sample program 022-01>
#include <stdio.h> #include <time.h> int main(void) { printf("%d\n", time(NULL)); return 0; } |
<実行結果>
1165929545 続行するには何かキーを押してください・・・
※実行した時間によって値は変わります。
まずは、プログラムの説明からします。
#include <time.h>
これは、前回説明しました。
色々なヘッダファイルをinclude(含む)ことによって、様々な命令(関数)が使えるようになる、というものです。
今回は、timeヘッダですから、時間に関する命令(関数)が使えるようになります。
printfで表示しているものが「時間」になるのですが、timeという命令(関数)が書かれています。
time(NULL)
と書いてある部分が時間を取ってくる命令(関数)になります。
しかし、時間を表示してみると「00:00:00」といった時分秒で表されず、訳の分からない数値が表示されています。
これは、グリニッジ標準時の1970年1月1日 0時0分0秒から1秒単位で数えた数値になっています。
なんだかややこしい話になってきましたが、今回はグリニッジ標準時だろうが日本時間だろうが、あまり問題ではありません。
このプログラムを何度か実行してみてください。
プログラムを実行する度に数値が変化することがわかりますか?
これが重要なのです。
乱数の種に時間が使えれば、秒単位で種を変えることが出来ます。
前回のプログラムに組み込んで見ましょう。
<sample program 022-02>
#include <stdio.h> #include <stdlib.h> #include <time.h> int main(void) { int number; srand(time(NULL)); number = rand(); printf("乱数 %d\n", number); number = rand(); printf("乱数 %d\n", number); number = rand(); printf("乱数 %d\n", number); return 0; } |
<実行結果>
乱数 27818 乱数 9274 乱数 22013 続行するには何かキーを押してください・・・
このプログラムも、実行する時間によって結果は変わりますが、何度か実行してみると、毎回乱数が変わっていることに気づくはずです。
秒単位で時間が変化していますので、1秒の間に2回以上実行した場合は、変化がありません。
これで、乱数を使う準備が出来ましたが、よく見てみると「警告」が出ています。
<コンパイル結果>
warning C4244: '関数' : 'time_t' から 'unsigned int' への変換です。データが失われる可能性があります。
「srand」という命令(関数)はunsigned int型の値を受け取るようになっています。
時間は、time_tという型(特殊な型ではないのですが、これについては後々書きます)で取得しますので、「型が違うけど大丈夫?」という意味で「警告」が表示されます。
乱数を使うたびに表示されるのは鬱陶しいので、対処方法を書いておきます。
<sample program 022-03>
#include <stdio.h> #include <stdlib.h> #include <time.h> int main(void) { int number; srand((unsigned int)time(NULL)); number = rand(); printf("乱数 %d\n", number); number = rand(); printf("乱数 %d\n", number); number = rand(); printf("乱数 %d\n", number); return 0; } |
<実行結果>
乱数 27818 乱数 9274 乱数 22013 続行するには何かキーを押してください・・・
time(NULL) の前に「(unsigned int)」と追加します。
これは、キャストという方法ですが、非常に危険性を含んだ命令ですので、詳しいことは後述します。
今のところは、こう書けば警告を出さずに乱数が使える、と思っておいてください。
ついでに、NULLという文字はアルファベットの大文字ですよね。
C言語は基本的にアルファベットの小文字で記述する言語ですが、アルファベットの大文字は慣例として特殊な意味を持っています。
この「NULL」を説明するとなると、「ポインタ」に言及することになりますので、これも「とりあえずこう書けば良い」くらいに思っておいてください。
では、いよいよゲームを作ってみましょう!
といいたいところですが、もう少し乱数に付き合ってください・・・