【cocos2dx】重複のないランダムな数字を取り出す(追記あり)

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()を呼び出すごとに、ランダムな数字を取得できます。

整数型の配列

今回は、重複をしない数字を取り出すということで、以下のようにして、ランダムな数字を取り出します。

  1. 0~9の整数が格納されている配列を準備
  2. 配列から、rand()を利用して、数字を一つ取り出す
  3. 取り出した数字を除いた配列を作成する
  4. 2に戻る

このような方法で、ランダムな数字を一つづつ取り出していきます。

動的配列(vector)

まずは配列を作成しなくてはいけないのですが、cocos2dxの配列といえばCCArrayクラスがあります。 ただ、これはint型のオブジェクトを格納できないので、どうしようか色々と考えました。

それで利用したのが、「動的配列(vector)」というものです。

これは、C++から使えるモノみたいで、配列の生成、追加、削除ができるといったものです。

こんな感じで利用をしています。 [c]

std::vectorarray;

//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

こちらを参考にコードを組み立てて下さい。

参考

全く知識がないので、こちらのサイトを参考にしました。

配列よりSTL
動的配列(vector) ...

実際のコード

実際のコードを書いていきます。 正しい値を返しているので、多分大丈夫だと思います。 もし、もっといい方法があれば教えて欲しいです。

[c]

std::vectorary1;

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 array){

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]

最後に

全くと言っていいほど、プログラミングの知識がないので、この辺りの基礎をしっかりしないといけないなあと感じています。 おそらくとても簡単なことだとは思うのですが、とても苦労しています。 数字を取り出しただけど、まだ上手く利用ができていないので、もっと頭を使わないといけなあ。

もし、何か参考にできる部分があれば幸いです。