オセロを作っていたのですが・・

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

オセロを作っていたのですが・・

#1

投稿記事 by やす » 8年前

はじめまして、やすと申します。
初めてここを利用させて頂くので失礼な所があればすみません。

私はC言語を独学で勉強し始めた(プログラミング自体始めてです)学生です。
そこでコマンドプロンプト上でプレイできるオセロを作ろうと思い自分なりにコードを書いてみたのですがうまくいきません、
コードは下に記述していますが、実行結果が思うようにいかないのです。

まずオセロの盤面をchar型の配列で作って 黒石をB白石をW空きマスを@で表現し
黒の番であれば縦の列の番号、横の列の番号を順に入力してもらい、
そこが空いているマス、つまり@であるかどうか調べ
その後@なら周り8方向の文字がWかどうかチェックし
例えば上の方向がWならそのまま上をチェックしてBがあれば今までチェックしたWを全部Bに変える。
という風に書いたつもりだったのですが・・。

どこかのwhile文から出れていないのか実行すると縦、横の数字の入力を求めたあと
プログラム自体が終了せずに止まってしまいます。

どこがおかしいのか調べてみたのですが自分ではわかりませんでした。
使っているコンパイラはVisual C++ 2008です
よろしくお願いします。

コード:

#include <stdio.h>

int main(void)
{
	char osero[10][10] ={{" 12345678\n"},
						 {"1@@@@@@@@\n"},
						 {"2@@@@@@@@\n"},
						 {"3@@@@@@@@\n"},
						 {"4@@@WB@@@\n"},
						 {"5@@@BW@@@\n"},
						 {"6@@@@@@@@\n"},
						 {"7@@@@@@@@\n"},
						 {"8@@@@@@@@\n"},
						 {"         "}};
	char str[10];
	int yoko,tate,y,x;
	int i,j;
	int count = 0;
	
	printf("%s\n",osero);
	
	while(1){
		while(1){
			printf("黒の番です\n");
			printf("石を置きたい場所の縦の数字を入力してください\n");
			fgets(str,sizeof(str),stdin);
			sscanf(str,"%1d",&tate);
			printf("横の数字を入力してください\n");
			fgets(str,sizeof(str),stdin);
			sscanf(str,"%1d",&yoko);
			
			if((tate >= 1) && (tate <= 8) && (yoko >= 1) && (yoko <= 8)){ /* ここでオセロの盤面上の座標かチェック */
				break;
			}
		}
		if(osero[tate][yoko] == '@'){/* ここで空いているマスかチェック */
				
				y = tate;
				x = yoko;
				
				while(1){ /* 上方向をチェック */
					if(osero[y-1][x] == 'W'){
						--y;
					}
					else if((y != tate) && (osero[y-1][x] == 'B')){
						for(i = tate;i >= y;--i){
							osero[i][x] = 'B';
						}
					}
					else{
						y = tate;
						x = yoko;
						break;
					}
				}
				
				while(1){ /* 右上方向をチェック */
					if(osero[y-1][x+1] == 'W'){
						--y;
						++x;
					}
					else if((y != tate) && (osero[y-1][x+1] == 'B')){
						for(i = tate;i >= y;--i){
							j = yoko;
							osero[i][j] = 'B';
							++j;
						}
					}
					else{
						y = tate;
						x = yoko;
						break;
					}
				}
				
				while(1){ /* 右方向をチェック */
					if(osero[y][x+1] == 'W'){
						++x;
					}
					else if((x != yoko) && (osero[y][x+1] == 'B')){
						for(j = yoko;j <= x;++j){
							osero[y][j] = 'B';
						}
					}
					else{
						y = tate;
						x = yoko;
						break;
					}
				}
				
				while(1){ /* 右下方向をチェック */
					if(osero[y+1][x+1] == 'W'){
						++y;
						++x;
					}
					else if((y != tate) && (osero[y+1][x+1] == 'B')){
						for(i = tate;i <= y;++i){
							j = yoko;
							osero[i][j] = 'B';
							++j;
						}
					}
					else{
						y = tate;
						x = yoko;
						break;
					}
				}
				
				while(1){ /* 下方向をチェック */
					if(osero[y+1][x] == 'W'){
						++y;
					}
					else if((y != tate) && (osero[y+1][x] == 'B')){
						for(i = tate;i <= y;++i){
							osero[i][x] = 'B';
						}
					}
					else{
						y = tate;
						x = yoko;
						break;
					}
				}
				
				while(1){ /* 左下方向をチェック */
					if(osero[y+1][x-1] == 'W'){
						++y;
						--x;
					}
					else if((y != tate) && (osero[y+1][x-1] == 'B')){
						for(i = tate;i <= y;++i){
							j = yoko;
							osero[i][j] = 'B';
							--j;
						}
					}
					else{
						y = tate;
						x = yoko;
						break;
					}
				}
				
				while(1){ /* 左方向をチェック */
					if(osero[y][x-1] == 'W'){
						--x;
					}
					else if((x != yoko) && (osero[y][x-1] == 'B')){
						for(j = yoko;j >= x;--j){
							osero[y][j] = 'B';
						}
					}
					else{
						y = tate;
						x = yoko;
						break;
					}
				}
				
				while(1){ /* 左上方向をチェック */
					if(osero[y-1][x-1] == 'W'){
						--y;
						--x;
					}
					else if((y != tate) && (osero[y-1][x-1] == 'B')){
						for(i = tate;i >= y;--i){
							j = yoko;
							osero[i][j] = 'B';
							--j;
						}
					}
					else{
						y = tate;
						x = yoko;
						break;
					}
				}
		}
		break;
	}
	
	printf("%s%d%d\n",osero,y,x);
	
	return 0;
}
[/size]

アバター
へろりくしょん
記事: 92
登録日時: 9年前
住所: 福岡

Re: オセロを作っていたのですが・・

#2

投稿記事 by へろりくしょん » 8年前

ざらっと見ただけですが。

言葉だけで説明するのはちょっと大変なので、結論だけざっくりいきます。

相手の石をひっくり返す処理を行った後も、延々とひっくり返しているようです。
上方向ならば、46行目の for() ループを抜けた時点で、41行目の while() ループを抜けるようにする必要があります。

というより、ひっくり返せるかチェックする処理・ひっくり返す処理は、関数化した方がいいですよ。
そうすれば、このコードもざっくりと半分以下に減らす事が出来ますし、とても見通しが良くなる上に、バグの箇所の特定も迅速に行えるようになります。

ちなみに、この手のバグはトレースすれば一発です。
Visual Studio はフリーのものであれ、とても高級な IDE で、非常に強力なデバッガを搭載してますので、デバッガの使い方を覚える事を是非ともお勧めします。

やす

Re: オセロを作っていたのですが・・

#3

投稿記事 by やす » 8年前

返信が遅れました、ありがとうございます。
気付いてみるとすごく初歩的なミスでしたね・・
自分ではなかなか気づけなかったので本当に助かりました!
へろりーなさんの言うとおり被っている処理は関数化してデバッガの使い方も覚えたいと思います。

閉鎖

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