リスト操作

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
PAN

リスト操作

#1

投稿記事 by PAN » 12年前

リスト操作がうまくできず、また対処方法がわかりません。

その内容ですが、
全敵を格納したリストがある。
画面上で敵は整列しており、
縦に区切って、それらの列にはNoを振り、
それを各敵は保持しています。
     ●|●|●|●|●|●
     ●|●|●|●|●|●
     ●|●|●|●|●|●
 列No 0 1 2 3 4 5

時間が来ると、どれかの列に攻撃命令を出すわけですが
毎回、「どれかひとつの列だけ」がチョイスされ、
また、攻撃するのは「その列の先頭の敵だけ」です。
列はランダムに選択されます。
敵はプレイヤーによって、破壊され減らされていきますが、
チョイスされた列の先頭の敵が必ず攻撃する、
といった内容になるようにしました。

ソースです。

コード:

//攻撃する敵を決めるメソッド
void ObjectMgr::EnemyAttack(){

 //これらの最初の値設定はイニシャライズにて完了しているものとする
 this->attackNo = GetRand(4);//指定する列のNOをランダムで
 this->attackstart = 30;//攻撃する敵を決めるメソッド開始タイム
 this->attackcount = 0;//メソッドの間隔を刻むカウンター
 this->attackflg = false;//攻撃する敵を選択するソメッド開始フラグ

	list<sObject*>::iterator it;	//イテレータ宣言
	it = enemylist.begin();	//itの指すところを先頭にする

    //毎回、初期化したカウンターが攻撃開始時間を超えたらスタート
	if(this->attackcount >= this->attackstart){
		this->attackflg = true;//攻撃処理のフラグを立ててループの中へ

		while(this->attackflg == true){
			if(it!=enemylist.end()){
                  //指定番号と、敵の列番号が合わされば
					if((*it)->getlineNo() == this->attackNo){
                      //その敵の攻撃フラグを立てる
						(*it)->setenemyshot_flg(true);
						//繰り返すためにリセット
						this->attackNo = GetRand(10);
						this->attackstart = 30;
						this->attackcount = 0;
						this->attackflg = false;
						it=enemylist.begin();
						break;
					}
				it++;
				}
			}
		}
		this->attackcount++;
}
これで、最初はうまく動いてくれますが
途中でエラーが出て止まるか、フリーズします。
このメソッドを更新関数に入れると起きるので原因はここにありそうです。
エラーはリストのイテレータが不明、みたいなエラーです。
それかwhileから出れなくなったようなフリーズになります。
attackNoに格納されるチョイス列Noが、
すでに無くなってしまった列を選んだ場合の対処が入っていないからでしょうか?
「listの最後まで来てしまったら、リセットしてやりなおせ」を加えたつもりですが
うまくいきません。

コード:

//攻撃する敵を決めるメソッド
void ObjectMgr::EnemyAttack(){

 //これらの最初の値設定はイニシャライズにて完了しているものとする
 this->attackNo = GetRand(4);//指定する列のNOをランダムで
 this->attackstart = 30;//攻撃する敵を決めるメソッド開始タイム
 this->attackcount = 0;//メソッドの間隔を刻むカウンター
 this->attackflg = false;//攻撃する敵を選択するソメッド開始フラグ

	list<sObject*>::iterator it;	//イテレータ宣言
	it = enemylist.begin();	//itの指すところを先頭にする

    //毎回、初期化したカウンターが攻撃開始時間を超えたらスタート
	if(this->attackcount >= this->attackstart){
		this->attackflg = true;//攻撃処理のフラグを立ててループの中へ

		while(this->attackflg == true){
			if(it!=enemylist.end()){
                  //指定番号と、敵の列番号が合わされば
					if((*it)->getlineNo() == this->attackNo){
                      //その敵の攻撃フラグを立てる
						(*it)->setenemyshot_flg(true);
						//繰り返すためにリセット
						this->attackNo = GetRand(10);
						this->attackstart = 30;
						this->attackcount = 0;
						this->attackflg = false;
						it=enemylist.begin();
						break;
					}
				it++;
				}
				if(it==enemylist.end()){//listの最後になった(つまりその列はもう無い
					//リセットしてループを出る
					this->attackNo = GetRand(10);
					this->attackstart = 30;
					this->attackcount = 0;
					this->attackflg = false;
					break;
				}
			}
		}
		this->attackcount++;
}

なにが悪いですか?
どう修正すればいいでしょうか

PAN

Re: リスト操作

#2

投稿記事 by PAN » 12年前

あ、

 //これらの最初の値設定はイニシャライズにて完了しているものとする
 this->attackNo = GetRand(4);//指定する列のNOをランダムで
 this->attackstart = 30;//攻撃する敵を決めるメソッド開始タイム
 this->attackcount = 0;//メソッドの間隔を刻むカウンター
 this->attackflg = false;//攻撃する敵を選択するソメッド開始フラグ    』

ですが、イニシャライズで行っていて、
EnemyAttack()内には記載していない、ということです。
説明不足でしたので補足させて頂きました。

アバター
h2so5
副管理人
記事: 2212
登録日時: 15年前
住所: 東京
連絡を取る:

Re: リスト操作

#3

投稿記事 by h2so5 » 12年前

リスト内のポインタは本当に有効ですか?

PAN

Re: リスト操作

#4

投稿記事 by PAN » 12年前

h2so5 さんが書きました:リスト内のポインタは本当に有効ですか?

宣言は有効なはずです。
なにかの条件下で
Expression: list iterators incompatible
エラーとなりますが、
それまでは普通に動いてるんです。
敵たちは弾を撃ちますし、敵の数が減っても
ブレイクポイントで見るに
この関数で格納する値も思い通りに入っています。
ポインタは有効だということですよね。
しかし、デバッグ中、早くエラーが出る場合もありますし、
なかなかエラーが出ない場合もあり、
特定出来ずにいます。

しかし、どうやらこのソース文自体は問題なかった様ですね。
関数を置く位置を変えたら永久ループバグはまったく無くなりました。
h2so5さんもソース文に対するご指摘ではないですし、
別の部分が怪しいのかもしれません。
listを触っているのは上記の関数だけではありませんので。。
とりあえずもう一度調べてみます。

閉鎖

“C言語何でも質問掲示板” へ戻る