listでの末尾データ交換、削除

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

listでの末尾データ交換、削除

#1

投稿記事 by ランド » 10年前

Zを押すと弾情報を追加し、
弾が画面外に出ると 末尾データを代入→末尾データを削除 としたいのですが、
弾の数が3個以上のとき、画面外に出るとフリーズしてしまいます。
intでの解説+サンプルを見ながら自分なりに作ってみたので、
処理順序か何かが変な部分があると思うんですが…
(たぶんフリーズ原因はSHOTHandleだと)

とりあえず関係してる部分のソースを書き出します。
開発環境はBCC Developerです。
#include "DxLib.h"
#include <list>
#include <stdio.h>

struct ShotManage{
	int flag;	//敵か味方か
	
	double x,y;
	double movex,movey;

	int sizex,sizey;
	int type;
	int range;
	int atk;
		};

list <ShotManage> shot;

void SHOTHandle(void);
void CreateShot(int men,int human,int type,double x,double y);

void SHOTHandle(void){
	
	if( shot.empty()!=1 ){ //空で無ければ
	
	list<ShotManage>::iterator it;
	ShotManage obj;
	
	for( it = shot.begin(); it != shot.end() ; ++it){
	obj = *it;
	
		if(obj.x>800 || obj.x<-160
		 ||obj.y>480+obj.sizey/2
		 ||obj.y<0-obj.sizey/2    ){ //画面外に出たら
		
		list<ShotManage>::iterator lastobj; //末尾の1つ後
		lastobj = shot.end();
		lastobj--; //末尾にずらす
		
		obj = *lastobj; //末尾情報を消したい弾に上書き
		
		shot.pop_back(); //末尾削除
		
	if( shot.empty()==1 ){break;}
	
		}
		
		obj.x+=obj.movex;
		obj.y+=obj.movey;
		
	*it = obj;
	
	}
	
	}
}

void CreateShot(int men,int human,int type,double x,double y){
	
	ShotManage obj;
	
	obj.flag=human;//敵か味方か
	obj.x=x;obj.y=y;
	obj.type=type;
	
	GetGraphSize( pic.shot[obj.type] , &obj.sizex , &obj.sizey ) ;
	obj.range =(obj.sizex>obj.sizey)? obj.sizey:obj.sizex;
	
	if(human==mikata){
	
		if(type==0){
		
		obj.movex=8;
		obj.movey=0;
		obj.atk=1;
		
		}
	}
	
	if(human==teki){
     //敵の弾
	}
	
	shot.push_back(obj);
}
何度もすみませんが、よろしくお願いします。

ランド

Re:listでの末尾データ交換、削除

#2

投稿記事 by ランド » 10年前

vectorと違って削除部分以外のイテレータはそのまま使っても大丈夫・・・だそうなので、
書き直してみましたが、個数に関わらず要素削除時にフリーズするようになりました。
void SHOTHandle(void){
	
	list<ShotManage>::iterator it;
	ShotManage obj;
	
	for( it = shot.begin(); it != shot.end() ; ++it){
	
	
	obj = *it;
	
		obj.x+=obj.movex;
		obj.y+=obj.movey;
		
	*it = obj;
		
		if(obj.x>800 || obj.x<-160
		 ||obj.y>480+obj.sizey/2
		 ||obj.y<0-obj.sizey/2    ){

		shot.erase(it);
	
			}

	}
	
}

しっぽ

Re:listでの末尾データ交換、削除

#3

投稿記事 by しっぽ » 10年前

最初のは
for( it = shot.begin(); it != shot.end() ; ++it){
}
の中がおかしいです。

リストに2つ以上の要素があり、最後の要素がそれ自身と入れ替え対象になった場合、
shot.pop_back() で無効になったイテレータに対し
*it = obj;
という操作が行われてしまいます。


2番目のは
無効になったイテレータで、forの操作を続けるからです。

ランド

Re:listでの末尾データ交換、削除

#4

投稿記事 by ランド » 10年前

3時間かかりましたが、解決できました!
どうもありがとうございました!

*it = obj;を先に回したり、
lastobjを使わずに =back() で代入したり など色々いじってみましたが、

if( it == lastobj ){ shot.pop_back() ; break;}
をはさんでみたところ、正常に動作しました。

3個以上発生させたときに、半分ぐらいまでは正常に削除できるという不可思議な現象に悩まされてましたが、
>>最後の要素がそれ自身と入れ替え対象に~ のおかげで、
それ自身が対象になるタイミングが入れ替え動作でずれていることに気づくことができました。

また、>>無効になったイテレータで~ も、解決の糸口になりました。

//有効なイテレータかチェックする関数があればいいんですけどね、無効にならないようにすることが大事なんですかね・・・

ibis

Re:listでの末尾データ交換、削除

#5

投稿記事 by ibis » 10年前

tryブロック内でイテレータが指す要素にアクセスすれば、有効か無効か判定できますよ。

閉鎖

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