- 乱数
乱数とは、次にどんな数字が来るか、予想出来ない数字の羅列と考えて欲しい.例えば、0〜9の乱数を発生させたとして、今の値が1の場合,次に来る値は、0〜9の何れかが、ほぼ10%の確率で現れる数字列の事である.
話はさらに脱線するが、その昔、俺が未だC言語を始めた頃、そのC言語環境には、標準では乱数randomがサポートされていなかった.乱数が無い状況では、簡単なモグラ叩きゲームさえも作れないのが現実なのだ.俺は悩んだ揚げ句、友人に相談して、自分でランダム数を発生させる関数を作成する事にしたのだった.今や、乱数などは当たり前の様にサポートされているので、結局はそちらを使うのだが、基本的な考え方については、知っていて損は無いと思う.
(Jan.10/2001)
- 乱数の基本
まず、乱数には、種(ランダムシード)というものが必要になる.これは、どんな数字でも良いのだが、毎回同じ値を指定したのでは、同じ乱数しか得られないので、普通は、時計などの常に違う値を示しているものを採用して初期値とするのだ.
例えば、種(_RANDOM_SEED)が、0だったとして、簡単に乱数を発生させる方法を考えてみよう.0〜9の数値の乱数を連続で発生させたい場合は、_RANDOM_SEEDの下一桁つまり、(_RANDOM_SEED%10)を乱数の値として返し、7を足した値を_RANDOM_SEEDとして保存しておく.これを繰り返せば、0,7,4,1,8,5,2,9,6,3,0,7,4...という数字列になる.まあ、これでは10個の数字が10個周期で繰り返して現れるだけなので、使えないのであるが、少しは乱数らしくなっただろう.しかし、上記から分かる様に、足し算を繰り返すだけでは、その周期は自ずと短くなってしまうのだ.
では、計算をもう少し複雑にしてみよう.例えば、_RANDOM_SEEDに11を掛けた数と、11で割った数を足し、更に119を引いた値の絶対値を保存する方法を考えてみよう.こうすれば、得られる数列は、0,9,0,0,8,7,1,3,6,1,0,8,3,4,2,7,1,8,3,....となり、更に乱数的になってくる.結局,これにしても、230位の周期を繰り返すのだが、この程度の乱数になれば、簡単なゲーム位には使用できる筈である.
int _RANDOM_SEED ;
int iabs(int a)
{
return((-2*(a<0)+1)*a) ;
}
void randomizex(int rseed)
{
_RANDOM_SEED=iabs(rseed) ;
}
int randomx(void)
{
int rndmv ;
rndmv=_RANDOM_SEED%10 ;
_RANDOM_SEED=iabs(_RANDOM_SEED*11+(int)(_RANDOM_SEED/11)-119) ;
return(rndmv) ;
}
|
関数iabs()は、ランダムシードを0以上の整数に維持する為に用意した.
(Jan.11/2001)
- 実際の乱数
さて、上記は簡単な例を示したが、実際にC言語等に実装されている乱数のルーチンは、もう少し大きい数で計算を行って、一旦_RANDOM_SEEDを32767で割り,その答えを0〜1(0.999999...まで)の実数で返している.0〜9の整数の乱数が必要な場合は、それを10倍して使用する.
(Jan.11/2001)
|