ページ 11

ゲーム中のフリーズについて

Posted: 2011年4月01日(金) 21:55
by えん
今、オセロ形式のゲームを作っています。
一応石をオセロのルールで置く&ひっくり返すところまで作ったのですが、
石を黒白合わせて半分くらい置いたところですべての処理が停止するバグが起きてしまいます。
(Osero.exeは応答していませんしません、というエラー文が出てきます)

どうやらスペースキー(石を置くキー)を押した瞬間にフリーズするようなのですが、
カンストするようなものはおいてありません。

何かカンスト以外にフリーズする原因とかはありますでしょうか?

コードを貼るとすごく長くなってしまうのですが、
コードを見ないと分からない等であれば要点だけまとめて貼ります。

多少説明不足のところもあるかと思いますが、
ご回答よろしくお願いいたします。

Re: ゲーム中のフリーズについて

Posted: 2011年4月01日(金) 23:44
by h2so5
コードが無いとまず答えようがありません。
えん さんが書きました:何かカンスト以外にフリーズする原因とかはありますでしょうか?
「カンスト」とはどのような意味で使っているのでしょうか?
オーバーフローのことですか?

フリーズする原因としてはメモリのアクセス違反や、無限ループなどがあります。

Re: ゲーム中のフリーズについて

Posted: 2011年4月02日(土) 01:09
by softya(ソフト屋)
VC++などをお使いでしたら、デバッガの機能で中断すると何処でループしているか調べられます。
石が置けるか調べているところで無限ループしている可能性が高いと思いますが、コードが見れていないので断言できません。

Re: ゲーム中のフリーズについて

Posted: 2011年4月02日(土) 09:55
by えん
カンストではなくオーバーフローでした。あいまいで申し訳ありません・・・

以下スペースを押した際の処理

コード:

 void board_storn(){
	if(Key[KEY_INPUT_SPACE]==1){
		switch(board.turn){
			case BLACK://黒の番の時
				if(board.board[board.cursor_point_x][board.cursor_point_y]==0)
					check_storn_black();
				if(board.check_flag_black==1)
					board.turn=WHITE;
				break;
			case WHITE://白の番の時
				if(board.board[board.cursor_point_x][board.cursor_point_y]==0)
					check_storn_white();
				if(board.check_flag_white==1)
					board.turn=BLACK;
				break;
			default:
				printfDx("エラー\n");
				break;
		}
	}


以下check_storn_black()(check_storn_white()も似たような感じです)

コード:

 void check_storn_black(){
	int i=0, j;
	if(board.cursor_point_x<7){//右にマスがあるとき
		while(board.board[board.cursor_point_x+1+i][board.cursor_point_y]==WHITE){//右側が白の時
			if(board.cursor_point_x+1+i!=7)//右側が8列目の時を除く
				i++;
		}
		if(i!=0 && board.board[board.cursor_point_x+1+i][board.cursor_point_y]==BLACK){
			board.check_flag_black=1;
			for(j=0;j<i+1;j++)
				board.board[board.cursor_point_x+j][board.cursor_point_y]=BLACK;
		}
	}
	i=0;
	if(board.cursor_point_x>0){//左にマスがあるとき
		while(board.board[board.cursor_point_x-1-i][board.cursor_point_y]==WHITE){//左側が白の時
			if(board.cursor_point_x-1-i!=0)//左側が1列目の時を除く
				i++;
		}
		if(i!=0 && board.board[board.cursor_point_x-1-i][board.cursor_point_y]==BLACK){
			board.check_flag_black=1;
			for(j=0;j<i+1;j++)
				board.board[board.cursor_point_x-j][board.cursor_point_y]=BLACK;
		}
	}
	i=0;
	if(board.cursor_point_y>0){//上にマスがあるとき
		while(board.board[board.cursor_point_x][board.cursor_point_y-1-i]==WHITE){//上側が白の時
			if(board.cursor_point_y-1-i!=0)//上側が1列目の時を除く
				i++;
		}
		if(i!=0 && board.board[board.cursor_point_x][board.cursor_point_y-1-i]==BLACK){
			board.check_flag_black=1;
			for(j=0;j<i+1;j++)
				board.board[board.cursor_point_x][board.cursor_point_y-j]=BLACK;
		}
	}
	i=0;
	if(board.cursor_point_y<7){//下にマスがあるとき
		while(board.board[board.cursor_point_x][board.cursor_point_y+1+i]==WHITE){//下側が白の時
			if(board.cursor_point_y+1+i!=7)//下側が8列目の時を除く
				i++;
		}
		if(i!=0 && board.board[board.cursor_point_x][board.cursor_point_y+1+i]==BLACK){
			board.check_flag_black=1;
			for(j=0;j<i+1;j++)
				board.board[board.cursor_point_x][board.cursor_point_y+j]=BLACK;
		}
	}
	i=0;
	if(board.cursor_point_x<7 && board.cursor_point_y<7){//右下にマスがあるとき
		while(board.board[board.cursor_point_x+1+i][board.cursor_point_y+1+i]==WHITE){//右下側が白の時
			if(board.cursor_point_x+1+i!=7 || board.cursor_point_y+1+i!=7)//右側が8列目、下側が8列目の時を除く
				i++;
		}
		if(i!=0 && board.board[board.cursor_point_x+1+i][board.cursor_point_y+1+i]==BLACK){
			board.check_flag_black=1;
			for(j=0;j<i+1;j++)
				board.board[board.cursor_point_x+j][board.cursor_point_y+j]=BLACK;
		}
	}
	i=0;
	if(board.cursor_point_x>0 && board.cursor_point_y<7){//左下にマスがあるとき
		while(board.board[board.cursor_point_x-1-i][board.cursor_point_y+1+i]==WHITE){//左下側が白の時
			if(board.cursor_point_x-1-i!=0 || board.cursor_point_y+1+i!=7)//左側が1列目、下側が8列目の時を除く
				i++;
		}
		if(i!=0 && board.board[board.cursor_point_x-1-i][board.cursor_point_y+1+i]==BLACK){
			board.check_flag_black=1;
			for(j=0;j<i+1;j++)
				board.board[board.cursor_point_x-j][board.cursor_point_y+j]=BLACK;
		}
	}
	i=0;
	if(board.cursor_point_x<7 && board.cursor_point_y>0){//右上にマスがあるとき
		while(board.board[board.cursor_point_x+1+i][board.cursor_point_y-1-i]==WHITE){//右上側が白の時
			if(board.cursor_point_x+1+i!=7 || board.cursor_point_y-1-i!=0)//右側が8列目、上側が1列目の時を除く
				i++;
		}
		if(i!=0 && board.board[board.cursor_point_x+1+i][board.cursor_point_y-1-i]==BLACK){
			board.check_flag_black=1;
			for(j=0;j<i+1;j++)
				board.board[board.cursor_point_x+j][board.cursor_point_y-j]=BLACK;
		}
	}
	i=0;
	if(board.cursor_point_x>0 && board.cursor_point_y>0){//左上にマスがあるとき
		while(board.board[board.cursor_point_x-1-i][board.cursor_point_y-1-i]==WHITE){//左上側が白の時
			if(board.cursor_point_x-1-i!=0 || board.cursor_point_y-1-i!=0)//左側が1列目、上側が1列目の時を除く
				i++;
		}
		if(i!=0 && board.board[board.cursor_point_x-1-i][board.cursor_point_y-1-i]==BLACK){
			board.check_flag_black=1;
			for(j=0;j<i+1;j++)
				board.board[board.cursor_point_x-j][board.cursor_point_y-j]=BLACK;
		}
	}
}


長くて申し訳ないです!
board.board[8][8]にそれぞれのマス目の情報(黒か白か何もないか)を入れ、
board.cursor_pointには今カーソルがどこのマスにいるかを入れています。

何度かテストプレイをしたのですが、ボードの端に近いところに石を置くとフリーズしやすかったので、
もしかしたらアクセス違反が原因かもしれないです。
が、どこが原因だかはっきりとはわかりませんでした。

Re: ゲーム中のフリーズについて

Posted: 2011年4月02日(土) 11:44
by softya(ソフト屋)
>もしかしたらアクセス違反が原因かもしれないです。
アクセス違反ならプログラムが停止しますので、それも間違いですね。

私が提案したデバッガで調べてもらえたのでしょうか?
それともデバッガが何か分からないんでしょうか?
何も答えてもらっていないのでスルーした理由をお聞かせください。

それとソースコードで気になったのが、

コード:

        while(board.board[board.cursor_point_x+1+i][board.cursor_point_y]==WHITE){//右側が白の時
            if(board.cursor_point_x+1+i!=7)//右側が8列目の時を除く
                i++;
        }
このコードだとboard.cursor_point_x=6のときboard.board[board.cursor_point_x+1+i][board.cursor_point_y]==WHITEだと無限ループになりませんか?
これが原因な気がしますが、なんのためにある if(board.cursor_point_x+1+i!=7)なんでしょうか?

Re: ゲーム中のフリーズについて

Posted: 2011年4月02日(土) 14:02
by えん
softya(ソフト屋) さんが書きました: 私が提案したデバッガで調べてもらえたのでしょうか?
それともデバッガが何か分からないんでしょうか?
何も答えてもらっていないのでスルーした理由をお聞かせください。
若干言い訳臭くなってしまうのですが、
デバッガの方法を知らなかったので、他サイトで調べていた傍ら
答えてくださったお二方が「ソースがないと何とも言えない」とのことでしたのであわててソースを書き込んだので、
デバッガを試さずに返信してしまいました。
申し訳ありませんでした。
softya(ソフト屋) さんが書きました: それとソースコードで気になったのが、

コード:

        while(board.board[board.cursor_point_x+1+i][board.cursor_point_y]==WHITE){//右側が白の時
            if(board.cursor_point_x+1+i!=7)//右側が8列目の時を除く
                i++;
        }
このコードだとboard.cursor_point_x=6のときboard.board[board.cursor_point_x+1+i][board.cursor_point_y]==WHITEだと無限ループになりませんか?
これが原因な気がしますが、なんのためにある if(board.cursor_point_x+1+i!=7)なんでしょうか?
if(board.cursor_point_x+1+i!=7)は、端まで全部WHITEだった場合は
次のboard.board[board.cursor_point_x+1+i][board.cursor_point_y]で存在しない領域にアクセスしないようにつけたものです。

softyaさんのおっしゃるとおり、そこで無限ループが起こっていたようです。

コード:

        while(board.board[board.cursor_point_x+1+i][board.cursor_point_y]==WHITE){//右側が白の時
            if(board.cursor_point_x+1+i!=7)//右側が8列目の時を除く
                i++;
      else
                break;
        }
としたところ、フリーズがなくなりました。

答えてくださったお二方、本当にありがとうございました!

Re: ゲーム中のフリーズについて

Posted: 2011年4月02日(土) 14:27
by softya(ソフト屋)
最後にアドバイスをひとつ。
check_storn_blackとcheck_storn_whiteに分かれているみたいですが、check_storn(int checkStone,int revarseStone)とか引数にすれば関数をまとめられますね。
上下左右チェックも再帰呼び出しや上下左右の情報が入った配列でループなどを工夫すれば、もっとシンプルになりますよ。
気になったら質問してくださいね。

Re: ゲーム中のフリーズについて

Posted: 2011年4月02日(土) 14:57
by えん
softya(ソフト屋) さんが書きました:最後にアドバイスをひとつ。
check_storn_blackとcheck_storn_whiteに分かれているみたいですが、check_storn(int checkStone,int revarseStone)とか引数にすれば関数をまとめられますね。
上下左右チェックも再帰呼び出しや上下左右の情報が入った配列でループなどを工夫すれば、もっとシンプルになりますよ。
気になったら質問してくださいね。
なるほど!ありがとうございますm(__)m
一度全体の形を完成させてから、もしかしたら質問させていただくかもしれないです。
そのときはまたお手間をかけさせますが、よろしくお願いします。

Re: ゲーム中のフリーズについて

Posted: 2011年4月02日(土) 22:07
by たいちう
解決してるようだけど、53行目は&&の間違いじゃないかな。その他3箇所も。
私の勘違いならば申し訳ないです。

ついでに、あやしい英単語はマメに辞書で確認する習慣を付けた方が良いと思う。
stornとかrevarseとか。PCならば殆ど手間はかからないし。

Re: ゲーム中のフリーズについて

Posted: 2011年4月03日(日) 11:48
by softya(ソフト屋)
revarseを間違ったのは私ですね。
失礼しました。正解はreverse(逆の)です。