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

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

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

#1

投稿記事 by えん » 14年前

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

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

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

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

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

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

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

#2

投稿記事 by h2so5 » 14年前

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

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

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

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

#3

投稿記事 by softya(ソフト屋) » 14年前

VC++などをお使いでしたら、デバッガの機能で中断すると何処でループしているか調べられます。
石が置けるか調べているところで無限ループしている可能性が高いと思いますが、コードが見れていないので断言できません。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

えん

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

#4

投稿記事 by えん » 14年前

カンストではなくオーバーフローでした。あいまいで申し訳ありません・・・

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

コード:

 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には今カーソルがどこのマスにいるかを入れています。

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

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

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

#5

投稿記事 by softya(ソフト屋) » 14年前

>もしかしたらアクセス違反が原因かもしれないです。
アクセス違反ならプログラムが停止しますので、それも間違いですね。

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

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

コード:

        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)なんでしょうか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

えん

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

#6

投稿記事 by えん » 14年前

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;
        }
としたところ、フリーズがなくなりました。

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

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

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

#7

投稿記事 by softya(ソフト屋) » 14年前

最後にアドバイスをひとつ。
check_storn_blackとcheck_storn_whiteに分かれているみたいですが、check_storn(int checkStone,int revarseStone)とか引数にすれば関数をまとめられますね。
上下左右チェックも再帰呼び出しや上下左右の情報が入った配列でループなどを工夫すれば、もっとシンプルになりますよ。
気になったら質問してくださいね。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

えん

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

#8

投稿記事 by えん » 14年前

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

たいちう
記事: 418
登録日時: 14年前

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

#9

投稿記事 by たいちう » 14年前

解決してるようだけど、53行目は&&の間違いじゃないかな。その他3箇所も。
私の勘違いならば申し訳ないです。

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

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 14年前
住所: 東海地方
連絡を取る:

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

#10

投稿記事 by softya(ソフト屋) » 14年前

revarseを間違ったのは私ですね。
失礼しました。正解はreverse(逆の)です。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

閉鎖

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