重要なお知らせ

「教えて! goo」は2025年9月17日(水)をもちまして、サービスを終了いたします。詳細はこちら>

電子書籍の厳選無料作品が豊富!

皆様こんばんは。
Objective-C(Cocos2Dフレームワーク)でiPhoneアプリ開発をしております。
ランダム関数「arc4random」および「arc4random_uniform」についての質問宜しいでしょうか。

以下のように、あるレイヤーに対して画面内のランダムな位置へ4回連続移動するアクションメソッドを組んだのですが、初回の移動アクション(for文の変数jの値が0の時)のみ、arc4random_uniform()を噛ませたX座標(pos_x[0])とY座標(pos_y[0])が同値となってしまいます。
つまり、y=x上の座標にしか移動出来ません。これはarc4random()に置き換えてみてもダメでした。

2回目のループ以降(j >= 1)ではランダムな位置へ移動してくれるのですが、どうにも腑に落ちません。擬似乱数に対して根本的な認識不足があるのでしょうか?
具体的な原因・解決法などございましたら、ご教示頂ければ幸いです。
宜しくお願い致します。

=========================================================

- (void)randomAction:(id)sender{
CCLayer *layerI = (CCLayer *)[self getChildByTag:imgLayerLockOn];//アクション実行中のレイヤーを呼び出し
[layerI stopAllActions];//実行中のアクションを停止

CGSize winSize = [[CCDirector sharedDirector] winSize];//画面サイズを取得
int win_width = winSize.width;//横幅を代入
int win_height = winSize.height;//縦幅を代入

NSMutableArray *moveRandomActions = [NSMutableArray array];//CCSequenceに組み込むアクション用の空配列

for (int j = 0; j < 5; j++){
int pos_x[j];
int pos_y[j];
pos_x[j] = arc4random_uniform(win_width);★ランダムなX座標取得
pos_y[j] = arc4random_uniform(win_height);★ランダムなY座標を取得

CCLOG(@"j == %d, pos_x is %d, pos_y is %d", j, pos_x[j], pos_y[j]);//■ログ:取得したランダム座標

id moveRandom[j];
moveRandom[j] = [CCMoveTo actionWithDuration:2 position:ccp(pos_x[j], pos_y[j])];
[moveRandomActions addObject:moveRandom[j]];

}
id moveRandomSequence = [CCSequence actionWithArray:moveRandomActions];//配列にアクションを代入
id moveRandomEaseOut = [CCEaseOut actionWithAction:moveRandomSequence rate:2];//総アクションの減速効果
[layerI runAction:moveRandomEaseOut];

}

 ■CCLOGの出力結果例■
 ログ1:j == 0, pos_x is 40, pos_y is 40 (※←初回のみ同値となってしまう)
 ログ2:j == 1, pos_x is 128, pos_y is 306
 ログ3:j == 2, pos_x is 247, pos_y is 86
 ・
 ・
 

A 回答 (1件)

出力結果以前の話として、このプログラムを動かすとエラーになりませんか?再現性がある現象なのかどうか調べるために、同等のプログラムを書いて、iOSシミュレーターで実行してみると、EXC_BAD_ACCESSというエラーで止まりました。


一行ずつ見てみると、たしかにおかしなプログラムです。

int pos_x[j];
int pos_y[j];

jが0のとき、いずれも要素数0の配列を宣言していることになります。

pos_x[j] = arc4random_uniform(win_width);★ランダムなX座標取得
pos_y[j] = arc4random_uniform(win_height);★ランダムなY座標を取得

jが1のとき、要素数1の配列の2番目(一番目がpos_x[0]、pos_y[0]、二番目がpos_x[1]、pos_y[1])に値を代入しようとしています。

そもそもそこで配列を使う意味がわかりません。

- (void)randomAction:(id)sender{
CCLayer *layerI = (CCLayer *)[self getChildByTag:imgLayerLockOn];//アクション実行中のレイヤーを呼び出し
[layerI stopAllActions];//実行中のアクションを停止

CGSize winSize = [[CCDirector sharedDirector] winSize];//画面サイズを取得
int win_width = winSize.width;//横幅を代入
int win_height = winSize.height;//縦幅を代入

NSMutableArray *moveRandomActions = [NSMutableArray array];//CCSequenceに組み込むアクション用の空配列

for (int j = 0; j < 5; j++){
int pos_x = arc4random_uniform(win_width);★ランダムなX座標取得
int pos_y = arc4random_uniform(win_height);★ランダムなY座標を取得

CCLOG(@"j == %d, pos_x is %d, pos_y is %d", j, pos_x, pos_y);//■ログ:取得したランダム座標

id moveRandom;
moveRandom = [CCMoveTo actionWithDuration:2 position:ccp(pos_x, pos_y)];
[moveRandomActions addObject:moveRandom];

}
id moveRandomSequence = [CCSequence actionWithArray:moveRandomActions];//配列にアクションを代入
id moveRandomEaseOut = [CCEaseOut actionWithAction:moveRandomSequence rate:2];//総アクションの減速効果
[layerI runAction:moveRandomEaseOut];

}

これで問題ないはずですが?

なんとなく、ここに書いたプログラムと、じっさいに動かしてみたプログラムが異なるのではないかと思えるのですが?
    • good
    • 0
この回答へのお礼

丁寧なご回答ありがとう御座いました。

>「そもそもここで配列を使う意味がわかりません」
このご指摘で何がおかしいのか気が付きました。

確かにこれでは、何のためにNSMutableArrayという可変長配列やループを使用したのかわからないですね。寝不足が祟っていたのかもしれません…。^^;

ただ、フレームワークの特性なのでしょうか、質問内容のソースコードについては、付け足したコメント部分以外丸々コピペで、こちらでは何故か実行されてしまっています。(稀に原因不明のBAD_ACCESSエラーが出る事はありましたが、多分この意味不明な配列のせいですね)

ともあれ、お陰様でスッキリです。無事想定通りのアクションを組む事が出来ました。
本当に有難う御座いました。

お礼日時:2013/04/22 09:55

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!