2日前から、ずーと考えていたのが、「重複なしでランダムな数字」を取り出すことができないかということです。 現在考えているゲームなんですが、オブジェクトの位置を決めずに、ランダムに配置をしたいと考えています。ゲームを考え始めた時から懸念に感じていたことが、このオブジェクトの配置が実装できるかどうかでした。
これまで作成してきたゲームに関しては、オブジェクトの位置は固定されていたので、そのようなことは考えていなかったので、凄く悩みました。 本日、ようやく「重複なしでランダムな数字」を取り出すことに成功しましたので、そのやり方を今回、ブログで紹介をしたいと思います。
【追記 10/28】 twitterで、もっと簡単にできる方法を教えていただきましたので、追記をしています。
以下のような順番で説明をします。
- ランダムな数字を取り出す
- 整数型の配列
- 実際のコード
ランダムな数字を取り出す
まずは、ランダムな数字を取り出す方法です。 これは、以前ブログにも書いたのですが、C++には専用のメソッドが用意されていますので、これを利用します。
[c]
//これがないと、ランダムでも同じ数字になってしまう。
srand((unsigned int)time(NULL));
//rand()%の後に、どこまでの範囲から値を取得するかを指定(例では0~9までの整数) int randomNum = rand()%10;
[/c]
【追記】 上記の方法でもランダムな数字を出すことができますが、以下のコードの方が簡単です。
[c]
int randomNum = arc4random()%10;
[/c]
上記のコードで、rand()を呼び出すごとに、ランダムな数字を取得できます。
整数型の配列
今回は、重複をしない数字を取り出すということで、以下のようにして、ランダムな数字を取り出します。
- 0~9の整数が格納されている配列を準備
- 配列から、rand()を利用して、数字を一つ取り出す
- 取り出した数字を除いた配列を作成する
- 2に戻る
このような方法で、ランダムな数字を一つづつ取り出していきます。
動的配列(vector) まずは配列を作成しなくてはいけないのですが、cocos2dxの配列といえばCCArrayクラスがあります。 ただ、これはint型のオブジェクトを格納できないので、どうしようか色々と考えました。
それで利用したのが、「動的配列(vector)」というものです。
これは、C++から使えるモノみたいで、配列の生成、追加、削除ができるといったものです。
こんな感じで利用をしています。 [c]
std::vector
//0~9までの配列を作成 for( int i = 0; i < 10; i++ ) { array.push_back( i ); }
//配列の個数を取り出す int arrNUm = array.size();
//配列をクリアにする array.clear();
[/c]
【追記】 配列に関しては、CCIntegerクラスを利用すれば、CCArrayで利用ができます。 これを利用すれば、もっと簡単です。
[c]
CCInteger *hogehoge =CCInteger::create(1001);
CCInteger *hogehoge2 =CCInteger::create(1002);
CCArray *_arr = CCArray::create();
_arr->addObject(hogehoge);
_arr->addObject(hogehoge2);
//int型で取り出すには、getValue()を使います。
CCObject *obj = NULL;
CCARRAY_FOREACH(_arr, obj){
CCInteger *num= (CCInteger*)obj;
CCLOG("%i",num->getValue());
}
[/c]
CCArrayについてはこちらのリファレンスを見れば、「追加」「削除」などが載っています。 CCArray | Cocos2d-x
こちらを参考にコードを組み立てて下さい。
参考
全く知識がないので、こちらのサイトを参考にしました。実際のコード
実際のコードを書いていきます。 正しい値を返しているので、多分大丈夫だと思います。 もし、もっといい方法があれば教えて欲しいです。[c]
std::vector
void GameLayer::setObject(){
srand((unsigned int)time(NULL));
//ランダムの数字の範囲(0~9)で配列を作成
for( int i = 0; i < 10; i++ )
{
ary1.push_back( i );
}
//取り出す数字の総数 (今回は5つの数字を取り出しています)
for (int i = 0; i < 5; i++) {
//下記メソッドから、ランダムな数字を取り出します。
int xPos = this->returnRandomNum(cary1);
//取り出した数字を利用して、オブジェクトを配置
GameObject *obj = GameObject::create();
obj->setPosition(32 + 64 * xPos,-300);
this->addChild(obj,3);
}
}
int GameLayer::returnRandomNum(std::vector
vector<int> ary2;
//配列に格納されている数字の数を取り出す int arrayNum = array.size();
//ランダムな数字を取り出す int randomNum = rand()%arrayNum;
//配列から取り出した数字を取り出す(これが欲しい数字です) int getNum = ary1[randomNum];
//取り出した数字を抜いた、新しい配列を作成します。 for( int i = 0; i < arrayNum; i++ ) {
if (i == randomNum) {
}else{
//新しい配列に数字を格納します。
ary2.push_back(ary1[i]);
}
}
//クリア
ary1.clear();
ary1 = ary2;
return getNum;
}
[/c]
最後に
全くと言っていいほど、プログラミングの知識がないので、この辺りの基礎をしっかりしないといけないなあと感じています。 おそらくとても簡単なことだとは思うのですが、とても苦労しています。 数字を取り出しただけど、まだ上手く利用ができていないので、もっと頭を使わないといけなあ。もし、何か参考にできる部分があれば幸いです。