オセロプログラミング、コマの処理

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
tonari
記事: 28
登録日時: 6年前

オセロプログラミング、コマの処理

#1

投稿記事 by tonari » 6年前

今私はオセロのプログラミングでコマの判定はできたのですが、
表示しているコマの色と実際に処理が行われているコマの情報がおかしくなって困っています。
このプログラムだと、表示しているコマ(置いたコマ)は黒なのに、ひっくり返す判定は白になってしまいます。
また、白を置いた場合は、判定は黒になってしまいます。
おそらく、コマを置いた瞬間にターンが切り替わり、置いたコマの情報が変わってしまっていると思います。
わかりずらい文章ですが、どこがおかしくてどう変えればいいか指摘をお願いします。
(プログラム歴は3か月未満です)

コード:

 
#include "DxLib.h"
#define SCREEN_WIDIH 840
#define SCREEN_HEIGHT 640
#define CURSOR_MAX  480
#define CELLSIZE 80
#define BOARDSIZE 8
#define EMPTY  0
#define BLACK  1
#define WHITE  2

int key[256];

int gpUpdatekey()
{
	char tmpkey[256];				//現在のキーの入力状態を格納
	GetHitKeyStateAll(tmpkey);		//すべてのキーの入力状態を得る
	for (int i = 0; i < 256; ++i)
	{
		if (tmpkey[i] != 0)
		{
			++key[i];
		}
		else
		{
			key[i] = 0;
		}
	}
	return 0;
}
struct Obj {
	int x,
		y,
		w,
		h,
		Handle;
};
int board[BOARDSIZE][BOARDSIZE];
int boardGraph;
Obj black;
Obj white;
Obj cursor;
int vec_y[] = { -1,-1,0,1,1,1,0,-1 };
int vec_x[] = { 0,1,1,1,0,-1,-1,-1 };
int turn = 1;

//画像のロード
void Graph_Ini()
{
	 boardGraph   = LoadGraph("画像/オセロ.bmp");
	 black.Handle = LoadGraph("画像/クロ駒.bmp");
	 white.Handle = LoadGraph("画像/シロ駒.bmp");
	 cursor.Handle = LoadGraph("画像/選択.png");
}
//盤面の初期化
void Board_Ini()
{
	for (int y = 0; y < BOARDSIZE; ++y)
	{
		for (int x = 0; x < BOARDSIZE; ++x)
		{
			board[y][x] = EMPTY;
		}
	}
	board[BOARDSIZE / 2 - 1][BOARDSIZE / 2]		= BLACK;	//[3][4]
	board[BOARDSIZE / 2][BOARDSIZE / 2 - 1]		= BLACK;	//[4][3]
	board[BOARDSIZE / 2][BOARDSIZE / 2]  		= WHITE;	//[4][4]
	board[BOARDSIZE / 2 - 1][BOARDSIZE / 2 - 1] = WHITE;	//[3][3]
}
//カーソルの初期化
void Cursor_Ini()
{
	cursor.x = 0;
	cursor.y = 0;
}
//カーソルの移動
void Cursor_Move()
{
	if (key[KEY_INPUT_RIGHT] == 1 && cursor.x <= CURSOR_MAX)
	{
		cursor.x += CELLSIZE;
	}
	if (key[KEY_INPUT_LEFT] == 1 && cursor.x > 0)
	{
		cursor.x -= CELLSIZE;
	}
	if (key[KEY_INPUT_UP] == 1 && cursor.y > 0)
	{
		cursor.y -= CELLSIZE;
	}
	if (key[KEY_INPUT_DOWN] == 1 && cursor.y <= CURSOR_MAX)
	{
		cursor.y += CELLSIZE;
	}
}
//vecで指定された向きについてひっくり返るコマがあるか確認する(8方向のチェック)
int CheckFlip(int y, int x, int turn, int vec)
{
	int flag = 0;
	while (1)
	{
		y += vec_y[vec];
		x += vec_x[vec];

		//盤面の外に出ていたら終了(盤面内か?)
		if (x < 0 || y < 0 || x > BOARDSIZE - 1 || y > BOARDSIZE - 1)
		{
			return 0;
		}
		//空きマス(置けるマス)だったら終了(その場所はおけるか?)
		if (board[y][x] == EMPTY)
		{
			return 0;
		}
		//相手のコマがあったらフラグを立てる
		if (board[y][x] == (turn ? BLACK : WHITE))	//真なら黒(1)、偽なら白(2)
		{
			flag = 1;
			continue;
		}
		//もしフラグが立っていればループ脱出。いなければ終了
		if (flag == 1)
		{
			break;
			return 0;
		}
	}
	return 1;
}
//その場所に置くことができるかを確認
int Check(int y, int x, int turn)	//座標とターン
{
	int vec;

	//どれか一方向でもひっくり返るか確認
	for (vec = 0; vec < 8; ++vec)
	{
		if (CheckFlip(y, x, turn, vec) == 1)
		{
			return 1;	//ひっくり返るなら1を返す
		}
	}
	return 0;			//0は返せない
}
//実際に裏返す処理
void Flip(int y, int x, int turn, int vec)
{
	while (1)
	{
		y += vec_y[vec];
		x += vec_x[vec];

		//自分のコマがあったら終了
		if (board[y][x] == (turn ? WHITE : BLACK))
		{
			break;
		}
		//それ以外なら自分の駒で塗りつぶす
		board[y][x] = (turn ? WHITE : BLACK);
	}
}


//入力を受けて裏返せるか確かめる関数
int Put(int y, int x, int turn)
{
	int vec,
		flag = 0;

	//空白でなければ終了
	if (board[y][x] != EMPTY)
	{
		return 0;
	}
	//全方向について確認
	for (vec = 0; vec < 8; ++vec)
	{
		if (CheckFlip(y, x, turn, vec) == 1)
		{
			//裏返す
			Flip(y, x, turn, vec);
			flag = 1;
		}
	}
	if (flag == 1)
	{
		//この場所にコマを置く
		board[y][x] = (turn ? WHITE : BLACK);
		return 1;
	}
	return 0;
}
//コマを置く処理
void PutPice(int &turn)
{
	for (int y = 0; y < BOARDSIZE; ++y)
	{
		for (int x = 0; x < BOARDSIZE; ++x)
		{
			if (board[y][x] == EMPTY && key[KEY_INPUT_Z] == 1 && CELLSIZE * x == cursor.x && CELLSIZE * y == cursor.y)
			{
				if (Put(y,x, turn) == 1 )
				{
					if (turn == 1)
					{
						board[y][x] = BLACK;
						turn = 0;
					}
					else
					{
						board[y][x] = WHITE;
						turn = 1;
					}
				}
			}
		}
	}
}
//終了判定
int CheckEnd(int turn)
{
	int y,
		x;
	//おける場所があるか確認
	for (y = 0; y < BOARDSIZE; ++y)
	{
		for (x = 0; x < BOARDSIZE; ++x)
		{
			//あれば普通に続行
			if (board[y][x] == EMPTY && Check(y, x, turn) == 1)
				return 0;
		}
	}
	//場所がなかったので交替して探す
	turn = (turn + 1) % 2;
	for (y = 0; y < BOARDSIZE; ++y)
	{
		for (x = 0; x < BOARDSIZE; ++x)
		{
			//あればpassして続行
			if (board[y][x] == EMPTY && Check(y, x, turn) == 1)
				return 1;
		}
	}
	//なかったのでゲーム終了
	return 2;
}
//盤面の表示
void Draw_Board()
{
	//盤面
	DrawGraph(0, 0, boardGraph, false);
	//文字の表示
	DrawFormatString(640, 50, GetColor(255,255,255),"コマ 0で黒 1で白    %d", turn);
	//コマ
	for (int y = 0; y < BOARDSIZE; ++y)
	{
		for (int x = 0; x < BOARDSIZE; ++x)
		{
				//ボードの情報がWHITEなら白コマが置かれる
				if (board[y][x] == WHITE)
				{
					DrawGraph(CELLSIZE * x, CELLSIZE * y, white.Handle, false);
				}
				//ボードの情報がBLACKなら黒コマが置かれる
				if (board[y][x] == BLACK)
				{
					DrawGraph(CELLSIZE * x, CELLSIZE * y, black.Handle, false);
				}
		}
	}
	//グリッド線を引く
	for (int x = 0; x < 9; ++x)
	{
		DrawLine(CELLSIZE * x, 0, CELLSIZE * x, SCREEN_HEIGHT, GetColor(255, 255, 255), true);
	}
	for (int y = 0; y < 9; ++y)
	{
		DrawLine(0, CELLSIZE * y, SCREEN_HEIGHT, CELLSIZE * y, GetColor(255, 255, 255), true);
	}
	//カーソル
	DrawGraph(cursor.x, cursor.y, cursor.Handle,true);
}
int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int)
{
	ChangeWindowMode(TRUE), DxLib_Init(), SetDrawScreen(DX_SCREEN_BACK);	//ウィンドウモード変更と初期化と裏画面設定
	SetGraphMode(SCREEN_WIDIH, SCREEN_HEIGHT, 32);

	Graph_Ini();
	Cursor_Ini();
	Board_Ini();

	// while(裏画面を表画面に反映、メッセージ処理、画面クリア、キーの更新)
	while(ScreenFlip() == 0 && ProcessMessage() == 0 && ClearDrawScreen() == 0 && gpUpdatekey() == 0)									//無限ループ
	{
		//ここにゲームの処理を描く------------------------------------------------
		if (turn < 2)
		{
			Cursor_Move();
			PutPice(turn);
			Draw_Board();
			switch (CheckEnd(turn))
			{
			case 1:
				turn = (turn + 1) % 2;
				break;
			}
		}
		

		//----------------------------------------------------------------------
	}
        DxLib_End();							// DXライブラリ終了処理
        return 0;
}

アバター
みけCAT
記事: 6734
登録日時: 13年前
住所: 千葉県
連絡を取る:

Re: オセロプログラミング、コマの処理

#2

投稿記事 by みけCAT » 6年前

CheckFlip関数

コード:

		//相手のコマがあったらフラグを立てる
		if (board[y][x] == (turn ? BLACK : WHITE))	//真なら黒(1)、偽なら白(2)
Flip関数

コード:

		//自分のコマがあったら終了
		if (board[y][x] == (turn ? WHITE : BLACK))
		{
			break;
		}
		//それ以外なら自分の駒で塗りつぶす
		board[y][x] = (turn ? WHITE : BLACK);
Put関数

コード:

		//この場所にコマを置く
		board[y][x] = (turn ? WHITE : BLACK);
ではturnが真のとき自分のコマがWHITE、相手の駒がBLACKとしているのに、

PutPice関数

コード:

					if (turn == 1)
					{
						board[y][x] = BLACK;
						turn = 0;
					}
					else
					{
						board[y][x] = WHITE;
						turn = 1;
					}
ではturnが1(真)のとき自分のコマがBLACK、1以外(偽を含む)のとき自分のコマがWHITEとなっていて、
統一されていないのがおかしいですね。

そもそもコマを置く処理はPut関数にあるので、PutPice関数で盤面を無駄に書き換えるのをやめるといいと思います。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

tonari
記事: 28
登録日時: 6年前

Re: オセロプログラミング、コマの処理

#3

投稿記事 by tonari » 6年前

返信ありがとうございます。
本当にしょうもないミスでした・・・。
以下は直した部分です。

コード:

//コマを置く処理
void PutPice(int by, int bx, int &turn)
{
	for (int y = 0; y < BOARDSIZE; ++y)
	{
		for (int x = 0; x < BOARDSIZE; ++x)
		{
			if (board[y][x] == EMPTY && key[KEY_INPUT_Z] == 1 && CELLSIZE * x == cursor.x && CELLSIZE * y == cursor.y)
			{
				if (Put(y,x, turn) == 1 )
				{
					if (turn == 1)
					{
						board[by][bx] = WHITE;
						turn = 0;
					}
					else
					{
						board[by][bx] = BLACK;
						turn = 1;
					}
				}
			}
		}
	}
}
しかし今度は別のバグを見つけてしまいました。
以下のオセロの盤面で(見づらくてすみません)B(黒) W(白)
*に黒コマを置くと置いてはならないはずなのに置けてしまいます。
・・・・*・・・
・・・B・・・・
・・W・・・・・
・B・・・・・・
・・・・・・・・
・・・・・・・・
・・・・・・・・
・・・・・・・・
相手のコマが挟まれていてかつひっくり返っていない状態の時には、
置けないようにしたいのですが、どのように条件を書けばよいでしょうか。

アバター
asd
記事: 319
登録日時: 13年前

Re: オセロプログラミング、コマの処理

#4

投稿記事 by asd » 6年前

tonari さんが書きました: しかし今度は別のバグを見つけてしまいました。
以下のオセロの盤面で(見づらくてすみません)B(黒) W(白)
*に黒コマを置くと置いてはならないはずなのに置けてしまいます。
・・・・*・・・
・・・B・・・・
・・W・・・・・
・B・・・・・・
・・・・・・・・
・・・・・・・・
・・・・・・・・
・・・・・・・・
相手のコマが挟まれていてかつひっくり返っていない状態の時には、
置けないようにしたいのですが、どのように条件を書けばよいでしょうか。
CheckFlip関数にて指定した方向に取れる駒があるか(置いてよいか?)を判定されているかと思いますが、
自分と同じ色の駒が見つかった時点で判定は終了するはずです。
今回の場合、*の位置のすぐ左下に自分と同じ色の駒があるのでこの時点で「この駒にたどり着くまでに相手の駒があったかどうか」を判別しないといけませんし、
その判定後に処理を終わらせないとさらにその先にある相手の駒を見に行ってしまいます(自分の駒を超えた先にある相手の駒は見てはいけない)

よって、自分の駒が見つかった場合にフラグが立っていれば置ける、立っていなければ置けないと判定するようにすればよいのではないでしょうか(*´ヮ`)
Advanced Supporting Developer
無理やりこじつけ(ぉ

tonari
記事: 28
登録日時: 6年前

Re: オセロプログラミング、コマの処理

#5

投稿記事 by tonari » 6年前

返信ありがとうございます。
ソースコードを以下のように直したところ、バグが治りました。
単に0をちゃんと返せてないだけ(breakしてた)でした。
ありがとうございます。

コード:

int CheckFlip(int y, int x, int turn, int vec)
{
	int flag = 0;
	while (1)
	{
		y += vec_y[vec];
		x += vec_x[vec];

		//盤面の外に出ていたら終了(盤面内か?)
		if (x < 0 || y < 0 || x > BOARDSIZE - 1 || y > BOARDSIZE - 1)
		{
			return 0;
		}
		//空きマス(置けるマス)だったら終了(その場所はおけるか?)
		if (board[y][x] == EMPTY)
		{
			return 0;
		}
		//相手のコマがあったらフラグを立てる
		if (board[y][x] == (turn ? BLACK : WHITE))	//真なら黒(1)、偽なら白(0)
		{
			flag = 1;
			//(ループを続ける)
		}
		//自分のコマがあった場合にフラグが立っていれば置ける
		if (board[y][x] == (turn ? WHITE : BLACK))
		{
			if (flag == 1)
			{
				return 1;
			}
			else
			{
				return 0;
			}
		}
	}
	return 1;
}
 

アバター
asd
記事: 319
登録日時: 13年前

Re: オセロプログラミング、コマの処理

#6

投稿記事 by asd » 6年前

tonari さんが書きました:返信ありがとうございます。
ソースコードを以下のように直したところ、バグが治りました。
単に0をちゃんと返せてないだけ(breakしてた)でした。
ありがとうございます。

コード:

int CheckFlip(int y, int x, int turn, int vec)
{
	int flag = 0;
	while (1)
	{
		y += vec_y[vec];
		x += vec_x[vec];

		//盤面の外に出ていたら終了(盤面内か?)
		if (x < 0 || y < 0 || x > BOARDSIZE - 1 || y > BOARDSIZE - 1)
		{
			return 0;
		}
		//空きマス(置けるマス)だったら終了(その場所はおけるか?)
		if (board[y][x] == EMPTY)
		{
			return 0;
		}
		//相手のコマがあったらフラグを立てる
		if (board[y][x] == (turn ? BLACK : WHITE))	//真なら黒(1)、偽なら白(0)
		{
			flag = 1;
			//(ループを続ける)
		}
		//自分のコマがあった場合にフラグが立っていれば置ける
		if (board[y][x] == (turn ? WHITE : BLACK))
		{
			if (flag == 1)
			{
				return 1;
			}
			else
			{
				return 0;
			}
		}
	}
	return 1;
}
 
解決したようで何よりですが、breakしないようにするだけで直ったということは、
私が指摘した時点では自分の駒があった時の判定まで既に実装できていたということでしょうか?

PutPice関数以外は質問当初のソースのままと思っていましたが、それ以外にも変更された箇所があったのであれば
それも併せて提示した上で質問いただけると質問者と回答者の間で見ているソースが違う…ということが防げてよいのではと思います。
Advanced Supporting Developer
無理やりこじつけ(ぉ

tonari
記事: 28
登録日時: 6年前

Re: オセロプログラミング、コマの処理

#7

投稿記事 by tonari » 6年前

質問に対しての指摘を受けたので、最終的なソースコードを書いておきます。
CheckFlip関数と、盤面がすべて埋まった時の処理を追加しました。
これで一応、人間対人間のオセロは完成したと思います。
不自然な部分や、後々の学習のために直したほうが良いところなどがあればまた指摘をお願いします。
次は簡単なAI(置ける所があれば置くようなもの)を実装するつもりです。
しばらく一人で考えて解らなかった場合,
また別のトピックを立てて質問したいと思います。

コード:

#include "DxLib.h"
#define SCREEN_WIDIH 840
#define SCREEN_HEIGHT 640
#define CURSOR_MAX  480
#define CELLSIZE 80
#define BOARDSIZE 8
#define EMPTY  0
#define BLACK  1
#define WHITE  2

int key[256];

int gpUpdatekey()
{
	char tmpkey[256];				//現在のキーの入力状態を格納
	GetHitKeyStateAll(tmpkey);		//すべてのキーの入力状態を得る
	for (int i = 0; i < 256; ++i)
	{
		if (tmpkey[i] != 0)
		{
			++key[i];
		}
		else
		{
			key[i] = 0;
		}
	}
	return 0;
}
struct Obj {
	int x,
		y,
		w,
		h,
		Handle;
};
int board_x,
	board_y;
int b,	//ゲーム終了時にコマの数を数えるための変数
	w;
int board[BOARDSIZE][BOARDSIZE];
int boardGraph;
int vec_y[] = { -1,-1,0,1,1,1,0,-1 };
int vec_x[] = { 0,1,1,1,0,-1,-1,-1 };
Obj black;
Obj white;
Obj cursor;
int turn;	//ターン、1は白が先手
//画像のロード
void Graph_Ini()
{
	 boardGraph   = LoadGraph("画像/オセロ.bmp");
	 black.Handle = LoadGraph("画像/クロ駒.bmp");
	 white.Handle = LoadGraph("画像/シロ駒.bmp");
	 cursor.Handle = LoadGraph("画像/選択.png");
}
//ゲーム情報の初期化
void Game_Ini()
{
	turn = 0;	//ターン、1は白が先手
	board_x = BOARDSIZE,
	board_y = BOARDSIZE;

}
//盤面の初期化
void Board_Ini()
{
	
	for (int y = 0; y < BOARDSIZE; ++y)
	{
		for (int x = 0; x < BOARDSIZE; ++x)
		{
			board[y][x] = EMPTY;
		}
	}
	board[BOARDSIZE / 2 - 1][BOARDSIZE / 2]		= BLACK;	//[3][4]
	board[BOARDSIZE / 2][BOARDSIZE / 2 - 1]		= BLACK;	//[4][3]
	board[BOARDSIZE / 2][BOARDSIZE / 2]  		= WHITE;	//[4][4]
	board[BOARDSIZE / 2 - 1][BOARDSIZE / 2 - 1] = WHITE;	//[3][3]
}
//カーソルの初期化
void Cursor_Ini()
{
	cursor.x = 0;
	cursor.y = 0;
}
//カーソルの移動
void Cursor_Move()
{
	if (key[KEY_INPUT_RIGHT] == 1 && cursor.x <= CURSOR_MAX)
	{
		cursor.x += CELLSIZE;
	}
	if (key[KEY_INPUT_LEFT] == 1 && cursor.x > 0)
	{
		cursor.x -= CELLSIZE;
	}
	if (key[KEY_INPUT_UP] == 1 && cursor.y > 0)
	{
		cursor.y -= CELLSIZE;
	}
	if (key[KEY_INPUT_DOWN] == 1 && cursor.y <= CURSOR_MAX)
	{
		cursor.y += CELLSIZE;
	}
}
//vecで指定された向きについてひっくり返るコマがあるか確認する(8方向のチェック)
int CheckFlip(int y, int x, int turn, int vec)
{
	int flag = 0;
	while (1)
	{
		y += vec_y[vec];
		x += vec_x[vec];

		//盤面の外に出ていたら終了(盤面内か?)
		if (x < 0 || y < 0 || x > BOARDSIZE - 1 || y > BOARDSIZE - 1)
		{
			return 0;
		}
		//空きマス(置けるマス)だったら終了(その場所はおけるか?)
		if (board[y][x] == EMPTY)
		{
			return 0;
		}
		//相手のコマがあったらフラグを立てる
		if (board[y][x] == (turn ? BLACK : WHITE))	//真なら黒(1)、偽なら白(0)
		{
			flag = 1;
			//(ループを続ける)
		}
		//自分のコマがあった場合にフラグが立っていれば置ける
		if (board[y][x] == (turn ? WHITE : BLACK))
		{
			if (flag == 1)
			{
				return 1;
			}
			//置けない
			else
			{
				return 0;
			}
		}
	}
	return 1;
}
//その場所に置くことができるかを確認
int Check(int y, int x, int turn)	//座標とターン
{
	int vec;

	//どれか一方向でもひっくり返るか確認
	for (vec = 0; vec < 8; ++vec)
	{
		if (CheckFlip(y, x, turn, vec) == 1)
		{
			return 1;	//ひっくり返るなら1を返す
		}
	}
	return 0;			//0は返せない
}
//実際に裏返す処理
void Flip(int y, int x, int turn, int vec)
{
	while (1)
	{
		y += vec_y[vec];
		x += vec_x[vec];

		//自分のコマがあったら終了
		if (board[y][x] == (turn ? WHITE : BLACK))
		{
			break;
		}
		//それ以外なら自分の駒で塗りつぶす
		board[y][x] = (turn ? WHITE : BLACK);
	}
}
//入力を受けて裏返せるか確かめる関数
int Put(int y, int x, int turn)
{
	int vec,
		flag = 0;

	//空白でなければ終了
	if (board[y][x] != EMPTY)
	{
		return 0;
	}
	//全方向について確認
	for (vec = 0; vec < 8; ++vec)
	{
		if (CheckFlip(y, x, turn, vec) == 1)
		{
			//裏返す
			Flip(y, x, turn, vec);
			flag = 1;
		}
	}
	if (flag == 1)
	{
		//この場所にコマを置く
		board[y][x] = (turn ? WHITE : BLACK);
		return 1;
	}
	return 0;
}

//コマを置く処理
void PutPice(int by, int bx, int &turn)
{
	for (int y = 0; y < BOARDSIZE; ++y)
	{
		for (int x = 0; x < BOARDSIZE; ++x)
		{
			if (board[y][x] == EMPTY && key[KEY_INPUT_Z] == 1 && CELLSIZE * x == cursor.x && CELLSIZE * y == cursor.y)
			{
				if (Put(y,x, turn) == 1 )
				{
					if (turn == 1)
					{
						board[by][bx] = WHITE;
						turn = 0;
					}
					else
					{
						board[by][bx] = BLACK;
						turn = 1;
					}
				}
			}
		}
	}
}

//終了判定
int CheckEnd(int turn)
{
	int y,
		x;
	//おける場所があるか確認
	for (y = 0; y < BOARDSIZE; ++y)
	{
		for (x = 0; x < BOARDSIZE; ++x)
		{
			//あれば普通に続行
			if (board[y][x] == EMPTY && Check(y, x, turn) == 1)
				return 0;
		}
	}
	//場所がなかったので交替して探す
	turn = (turn + 1) % 2;
	for (y = 0; y < BOARDSIZE; ++y)
	{
		for (x = 0; x < BOARDSIZE; ++x)
		{
			//あればpassして続行
			if (board[y][x] == EMPTY && Check(y, x, turn) == 1)
				return 1;
		}
	}
	//なかったのでゲーム終了
	return 2;
}
//勝敗判定
void CheckWinner()
{
		b = 0,
		w = 0;

	//コマを数え上げる
	for (int y = 0; y < BOARDSIZE; ++y)
	{
		for (int x = 0; x < BOARDSIZE; ++x)
		{
			switch (board[y][x])
			{
			case BLACK:
				++b;
				break;
			case WHITE:
				++w;
				break;
			default:
				break;
			}
		}
	}
	//勝敗決定時
	if (b > w)
	{
		DrawFormatString(680, 100, GetColor(255, 255, 255), "黒の勝ちです");
	}
	else if (b < w)
	{
		DrawFormatString(680, 100, GetColor(255, 255, 255), "白の勝ちです");
	}
	else
	{
		DrawFormatString(680, 100, GetColor(255, 255, 255), "引き分けです");
	}
}
//盤面の表示
void Draw_Board()
{
	//盤面
	DrawGraph(0, 0, boardGraph, false);
	//文字の表示
	if (turn == 1)
	{
		DrawFormatString(680, 50, GetColor(255, 255, 255), "白のターン");
	}
	if (turn == 0)
	{
		DrawFormatString(680, 50, GetColor(255, 255, 255), "黒のターン");
	}
	
	//コマ
	for (int y = 0; y < BOARDSIZE; ++y)
	{
		for (int x = 0; x < BOARDSIZE; ++x)
		{
				//ボードの情報がWHITEなら白コマが置かれる
				if (board[y][x] == WHITE)
				{
					DrawGraph(CELLSIZE * x, CELLSIZE * y, white.Handle, false);
				}
				//ボードの情報がBLACKなら黒コマが置かれる
				if (board[y][x] == BLACK)
				{
					DrawGraph(CELLSIZE * x, CELLSIZE * y, black.Handle, false);
				}
		}
	}
	//グリッド線を引く
	for (int x = 0; x < 9; ++x)
	{
		DrawLine(CELLSIZE * x, 0, CELLSIZE * x, SCREEN_HEIGHT, GetColor(255, 255, 255), true);
	}
	for (int y = 0; y < 9; ++y)
	{
		DrawLine(0, CELLSIZE * y, SCREEN_HEIGHT, CELLSIZE * y, GetColor(255, 255, 255), true);
	}
	//カーソル
	DrawGraph(cursor.x, cursor.y, cursor.Handle,true);
	
	
}
int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int)
{
	ChangeWindowMode(TRUE), DxLib_Init(), SetDrawScreen(DX_SCREEN_BACK);	//ウィンドウモード変更と初期化と裏画面設定
	SetGraphMode(SCREEN_WIDIH, SCREEN_HEIGHT, 32);

	Graph_Ini();
	Game_Ini();
	Cursor_Ini();
	Board_Ini();

	// while(裏画面を表画面に反映、メッセージ処理、画面クリア、キーの更新)
	while(ScreenFlip() == 0 && ProcessMessage() == 0 && ClearDrawScreen() == 0 && gpUpdatekey() == 0)									//無限ループ
	{
		//ここにゲームの処理を描く------------------------------------------------
		if (turn < 2)
		{
			Cursor_Move();
			PutPice(board_y, board_x,turn);
			
			switch (CheckEnd(turn))
			{
			case 1:
				turn = (turn + 1) % 2;
				break;
			case 2:
				CheckWinner();
				break;
			}
		}
		Draw_Board();
		//----------------------------------------------------------------------
	}
        DxLib_End();							// DXライブラリ終了処理
        return 0;
}
 

アバター
asd
記事: 319
登録日時: 13年前

Re: オセロプログラミング、コマの処理

#8

投稿記事 by asd » 6年前

最終的なソースの提示ありがとうございました。
また改めて解決したようでよかったです(*´ヮ`)b

あくまで私ならですが、現状はCheckFlip関数はその場所にコマを置けるかを判定するのみとなっています。
この関数をその場所にコマを置いたら何個取れるのかを返すようなものに改良すると、
AI実装するうえで「一番たくさん取れるところに置くAI」を実装する時には役に立つかもしれません。
Advanced Supporting Developer
無理やりこじつけ(ぉ

tonari
記事: 28
登録日時: 6年前

Re: オセロプログラミング、コマの処理

#9

投稿記事 by tonari » 6年前

返信が遅くなって済みません。
確かに返せるコマを計算できる処理があれば、ただ適当に置くAIよりも面白みがありますね。
今のところAIの実装ができそうでできない、といった感じです。
最近質問してばかりだったのでもう少し自分でやってみます。
アドバイスをありがとうございます。

アバター
asd
記事: 319
登録日時: 13年前

Re: オセロプログラミング、コマの処理

#10

投稿記事 by asd » 6年前

tonari さんが書きました:返信が遅くなって済みません。
確かに返せるコマを計算できる処理があれば、ただ適当に置くAIよりも面白みがありますね。
今のところAIの実装ができそうでできない、といった感じです。
最近質問してばかりだったのでもう少し自分でやってみます。
アドバイスをありがとうございます。
返信についてはお気になさらず。個人的に思ったことを書いてみただけなので参考になったらいいな程度でいましたので。
AIの実装を頑張っておられるとのことで、いろいろなパターンのAI(置き方)を作ってみるとよいかと思います。
(序盤はとにかくたくさん取れるところにおいて、中盤や終盤はコマを置く位置に重みづけをするといった感じで
状況によってAIが変わるとそれはそれで面白いかもですね)
無事にAI実装ができるとよいですね、頑張ってください(*´ヮ`)
Advanced Supporting Developer
無理やりこじつけ(ぉ

返信

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