狂ったお茶会のlog

後で起きる自分のためのメモ

ランダムな値を取得する

やりたいこと

1〜10のランダムな値を取得したい@cocos2d-x

1. rand() を使う

rand()で、0からRAND_MAX(マクロで設定されてる)までの範囲の乱数値を得ることができるので、
それを割った余り(10で割っているのであまりは0〜9の範囲となる)を出し、それに1を足すことで1〜10となる

こう

static const int NUM_MAX = 10;

int num = (rand() % NUM_MAX) + 1;

ただrand()は、毎回同じ値の羅列を出してくるっぽい(疑似乱数)
割る値がコロコロ変わる場合はこいつだけでもよさそうだが、今回はNUM_MAXが固定なのでちょっとダメ

2. srand() で初期化もする

なので、srand([ランダムな値])で毎回初期化してから使うとよい
[ランダムな値]には現在時刻を入れるのがポピュラーっぽい(毎秒違う値になるので)
つまりこう

srand((unsigned int)time(NULL));
int num = (rand() % NUM_MAX) + 1;

3. arc4random() を使う

上記を1つにまとめた関数があり、それがarc4random()
かんたんべんり

int num = (arc4random() % NUM_MAX) + 1;

ただし、arc4random()の戻り値はunsigned intなので注意
intの上限である2147483647より大きい値が来ることがあり、それをintにcastするとオーバーフローして死ぬ(マイナス値になったりする)
上記のように、2147483647以下の値で割った余りとかの場合は、それ以下の値にしかならないので問題ないという認識

4. 乱数エンジンを使う

乱数エンジンを使う方法
C++11 から使える様子 あまりよくわかってない

std::random_device rnd; //乱数エンジンのシードにする乱数を生成
std::mt19937 mt(rnd()); //乱数エンジン(こいつはメルセンヌ・ツイスタというやつ、生成値はuint32_t)で乱数を生成する

auto num = mt(); //生成された乱数

上記のmt()のままでも使えるが、ディストリビューションというやつを使うと使い勝手がいい模様
たとえばランダムな角度を求めたい時

//今回は-89〜89度の範囲の角度が欲しいとする
double degreeA = -89.0;
double degreeB = 90.0;

//degreeA以上degreeB未満のdouble値を返す設定のディストリビューションを作成
std::uniform_real_distribution<double> randDegree(degreeA, degreeB);

//上記で作成したディストリビューションに乱数エンジンを渡すと、設定した範囲の乱数が取得できる
double degree = randDegree(mt);

蛇足: 角度をラジアンに変換する

static const double PI = 3.141592653589793; //円周率

double radian = randDegree(mt) * PI / 180.0;

以上

参考

ロベールのC++教室 - 第75章 乱数 -
【cocos2dx】乱数を生成し、ランダムに値を取り出す方法 | albatrus.com
乱数の使用
C言語 「角度からラジアンに変換」 と 「ラジアンから角度に変換」 | 勇躍のゴミ箱