【C言語】オセロをプログラミングしてみる!駒をひっくり返す処理…【サンプルコード】

C/C++

こんにちは!

前回は盤面を表示するまでのコードを書きましたが、今回は実際に駒を置いて人間同士で戦えるプログラムを作りました。

初心者が1から作ったので、書き方が変だったりコードがごちゃごちゃしていたりしますがご了承ください。

なにも参考にせず作ったので、コードが580行超えました…

追記:短くしたコードは次回の記事に載せておきます。

【C言語】簡単なオセロAIをプログラミングしてみた【サンプルコード】
こんにちは! 前回は人間同士で戦えるところまで作ったので、今回は単純思考のコンピュータ(AI)と対戦できるところまでを作りました! ランダムで駒を置くだけのAIですが(笑) 前回までの記事・オセ...

 

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>

#define L 9 //盤の広さ
#define EMPTY 0//何も置いてない場所を示す
#define BLACK -2//1だとバグが出る
#define WHITE -1

void game();
void menu();

int turn = BLACK;
int board[L][L];
int board_next[L][L];
int cnt;
int sum;
int p;
int aiueo = 1;

int angle_x[] = { 0,1,1,1,0,-1,-1,-1};
int angle_y[] = { -1,-1,0,1,1,1,0,-1};

void shokika() {//盤面リセット
	for (int i = 0; i < L; i++) {
		for (int j = 0; j < L; j++) {
			board[i][j] = EMPTY;
		}
	}
	board[4][4] = WHITE;
	board[4][5] = BLACK;
	board[5][4] = BLACK;
	board[5][5] = WHITE;
}

void turn_change() {
	if (turn == WHITE) {
		turn = BLACK;
	}
	else {
		turn = WHITE;
	}
}

void display() {//盤面表示・更新
	for (int i = 0; i < L; i++) {
		for (int j = 0; j < L; j++) {
			switch (board[i][j]) {
			case WHITE:
				printf(" ●");
				break;
			case BLACK:
				printf(" 〇");
				break;
			default:
				if (i==0||j==0) {
					if (j == 0) {
						board[i][j]=i;//縦の数字を代入
					}
					if (i == 0) {
						switch (j){
						case 1:
							printf("  1 2 3 4 5 6 7 8");//横の数字を表示
							break;
						}
					}
					else{ 
						printf(" %d", board[i][j]);//縦の数字を表示
					}
					break;
				}
				else
				{
					printf(" *");
				}
			}
			if (j == L - 1) {//改行
				printf("\n");
			}
		}
	}
	game();
}

int w_while(int w_x, int w_y) {
	int flag[8] = { 0,0,0,0,0,0,0,0 };
	memcpy((void*)board_next, (void*)board, sizeof(board));
	board_next[w_y][w_x] = WHITE;
	for (int i = 0; i < 8; i++) { cnt = 1; switch (board[w_y + angle_y[i]][w_x + angle_x[i]]) {//置きたい場所の周りに敵の石があるか確認 case BLACK: do { if (i == 0) {//上方向の時 if (board_next[w_y - cnt][w_x] == BLACK) { board_next[w_y - cnt][w_x] = WHITE; cnt++; flag[0] = 1; if (board_next[w_y - cnt][w_x] == EMPTY || w_y - cnt == 1 && board_next[w_y - cnt][w_x] == BLACK||w_y-cnt==0) { int a = cnt - 1; flag[0] = 0; do { board_next[w_y - a][w_x] = BLACK; a--; } while (a >= 1);
						}
					}
					else {
						break;
					}
				}
				else if (i == 1) {//右上
					if (board_next[w_y - cnt][w_x + cnt] == BLACK) {
						board_next[w_y - cnt][w_x + cnt] = WHITE;
						cnt++;
						flag[1] = 1;
						if (board_next[w_y - cnt][w_x + cnt] == EMPTY || w_y - cnt == 1 && board_next[w_y - cnt][w_x + cnt] == BLACK|| w_x + cnt == 8 && board_next[w_y - cnt][w_x + cnt] == BLACK||w_y-cnt==0||w_x+cnt==9) {
							int a = cnt - 1;
							flag[1] = 0;
							do {
								board_next[w_y - a][w_x + a] = BLACK;
								a--;
							} while (a >= 1);
						}
					}
					else {
						break;
					}
				}
				else if (i == 2) {//右
					if (board_next[w_y][w_x + cnt] == BLACK) {
						board_next[w_y][w_x + cnt] = WHITE;
						cnt++;
						flag[2] = 1;
						if (board_next[w_y][w_x + cnt] == EMPTY || w_x + cnt == 8 && board_next[w_y][w_x + cnt] == BLACK||w_x+cnt==9) {
								int a = cnt - 1;
								flag[2] = 0;
								do {
									board_next[w_y][w_x + a] = BLACK;
									a--;
								} while (a >= 1);
							}
					}
					else {
						break;
					}
				}
				else if (i == 3) {//右下
					if (board_next[w_y + cnt][w_x + cnt] == BLACK) {
						board_next[w_y + cnt][w_x + cnt] = WHITE;
						cnt++;
						flag[3] = 1;
						if (board_next[w_y + cnt][w_x + cnt] == EMPTY||w_y + cnt == 8 && board_next[w_y + cnt][w_x + cnt] == BLACK || w_x + cnt == 8 && board_next[w_y + cnt][w_x + cnt] == BLACK ||w_y+cnt==9||w_x+cnt==9) {
								int a = cnt - 1;
								flag[3] = 0;
								do {
									board_next[w_y + a][w_x + a] = BLACK;
									a--;
								} while (a >= 1);
							}
					}
					else {
						break;
					}
				}
				else if (i == 4) {//下
					if (board_next[w_y + cnt][w_x] == BLACK) {
						board_next[w_y + cnt][w_x] = WHITE;
						cnt++;
						flag[4] = 1;
						if (board_next[w_y + cnt][w_x] == EMPTY || w_y + cnt == 8 && board_next[w_y + cnt][w_x] == BLACK||w_y+cnt==9) {
								int a = cnt - 1;
								flag[4] = 0;
								do {
									board_next[w_y + a][w_x] = BLACK;
									a--;
								} while (a >= 1);
							}
					}
					else {
						break;
					}
				}
				else if (i == 5) {//左下
					if (board_next[w_y + cnt][w_x - cnt] == BLACK) {
						board_next[w_y + cnt][w_x - cnt] = WHITE;
						cnt++;
						flag[5] = 1;
						if (board_next[w_y + cnt][w_x - cnt] == EMPTY || w_y + cnt == 8 && board_next[w_y + cnt][w_x - cnt] == BLACK ||w_x - cnt == 1 && board_next[w_y + cnt][w_x - cnt] == BLACK||w_y+cnt==9||w_x-cnt == 0) {
							int a = cnt - 1;
							flag[5] = 0;
							do {
								board_next[w_y + a][w_x - a] = BLACK;
								a--;
							} while (a >= 1);
						}
					}
					else {
						break;
					}
				}
				else if (i == 6) {//左
					if (board_next[w_y][w_x - cnt] == BLACK) {
						board_next[w_y][w_x - cnt] = WHITE;
						cnt++;
						flag[6] = 1;
						if (board_next[w_y][w_x - cnt] == EMPTY || w_x - cnt == 1 && board_next[w_y][w_x - cnt] == BLACK||w_x - cnt == 0) {
							int a = cnt - 1;
							flag[6] = 0;
							do {
								board_next[w_y][w_x - a] = BLACK;
								a--;
							} while (a >= 1);
						}
					}
					else {
						break;
					}
				}
				else if (i == 7) {//左上
					if (board_next[w_y - cnt][w_x - cnt] == BLACK) {
						board_next[w_y - cnt][w_x - cnt] = WHITE;
						cnt++;
						flag[7] = 1;
						if (board_next[w_y - cnt][w_x - cnt] == EMPTY || w_y - cnt == 1 && board_next[w_y - cnt][w_x - cnt] == BLACK || w_x - cnt == 1 && board_next[w_y - cnt][w_x - cnt] == BLACK||w_y-cnt==0||w_x-cnt==0) {
							int a = cnt - 1;
							flag[7] = 0;
							do {
								board_next[w_y - a][w_x - a] = BLACK;
								a--;
							} while (a >= 1);
						}
					}
					else {
						break;
					}
				}
				if (flag[i] == 0) {
					break;
				}
			} while (1);
			if (cnt == 1) { board_next[w_y][w_x] = EMPTY; return 2; }
			p = 1;
			break;
		default:
			break;
		}
	}
	if (p == EMPTY) {
		board_next[w_y][w_x] = EMPTY;
		return 2;
	}

	for (int i = 0; i < 8; i++) {
		sum += flag[i];
	}
	if (sum ==EMPTY) {
		board_next[w_y][w_x] = EMPTY;
		return 2;
	}
	sum = EMPTY;

	if (aiueo == 1) { aiueo = 0; return 3; }//all_check中なのでここで終了

		memcpy((void*)board, (void*)board_next, sizeof(board_next));
		turn = BLACK;
		p = 0;
		display();//再描画
		return 3;
}

int b_while(int b_x, int b_y) {
	int flag[8] = { 0,0,0,0,0,0,0,0 };
	memcpy((void*)board_next, (void*)board, sizeof(board));
	board_next[b_y][b_x] = BLACK;
	for (int i = 0; i < 8; i++) { cnt = 1; switch (board[b_y + angle_y[i]][b_x + angle_x[i]]) {//置きたい場所の周りに敵の石があるか確認 case WHITE: do { if (i == 0) {//上方向の時 if (board_next[b_y - cnt][b_x] == WHITE) { board_next[b_y - cnt][b_x] = BLACK; cnt++; flag[0] = 1; if (board_next[b_y - cnt][b_x] == EMPTY|| b_y - cnt == 1 && board_next[b_y - cnt][b_x] == WHITE||b_y-cnt==0) { int a = cnt - 1; flag[0] = 0; do { board_next[b_y - a][b_x] = WHITE; a--; } while (a >= 1);
						}
					}
					else {
						break;
					}
				}
				else if (i == 1) {//右上
					if (board_next[b_y - cnt][b_x + cnt] == WHITE) {
						board_next[b_y - cnt][b_x + cnt] = BLACK;
						cnt++;
						flag[1] = 1;
						if (board_next[b_y - cnt][b_x + cnt] == EMPTY || b_y - cnt == 1 && board_next[b_y - cnt][b_x + cnt] ==WHITE|| b_x + cnt == 8 && board_next[b_y - cnt][b_x + cnt] == WHITE || b_y-cnt == 0||b_x+cnt==9) {
							int a = cnt - 1;
							flag[1] = 0;
							do {
								board_next[b_y - a][b_x + a] = WHITE;
								a--;
							} while (a >= 1);
						}
					}
					else {
						break;
					}
				}
				else if (i == 2) {//右
					if (board_next[b_y][b_x + cnt] == WHITE) {
						board_next[b_y][b_x + cnt] = BLACK;
						cnt++;
						flag[2] = 1;
						if (board_next[b_y][b_x + cnt] == EMPTY || b_x + cnt == 8 && board_next[b_y][b_x + cnt] == WHITE || b_x + cnt == 9) {
							int a = cnt - 1;
							flag[2] = 0;
							do {
								board_next[b_y][b_x + a] = WHITE;
								a--;
							} while (a >= 1);
						}
					}
					else {
						break;
					}
				}
				else if (i == 3) {//右下
					if (board_next[b_y + cnt][b_x + cnt] == WHITE) {
						board_next[b_y + cnt][b_x + cnt] = BLACK;
						cnt++;
						flag[3] = 1;
						if (board_next[b_y + cnt][b_x + cnt] == EMPTY || b_y + cnt == 8 && board_next[b_y + cnt][b_x + cnt] == WHITE || b_x + cnt == 8 && board_next[b_y + cnt][b_x + cnt] == WHITE||b_y+cnt == 9 || b_x + cnt == 9) {
							int a = cnt - 1;
							flag[3] = 0;
							do {
								board_next[b_y + a][b_x + a] = WHITE;
								a--;
							} while (a >= 1);
						}
					}
					else {
						break;
					}
				}
				else if (i == 4) {//下
					if (board_next[b_y + cnt][b_x] == WHITE) {
						board_next[b_y + cnt][b_x] = BLACK;
						cnt++;
						flag[4] = 1;
						if (board_next[b_y + cnt][b_x] == EMPTY || b_y + cnt == 8 && board_next[b_y + cnt][b_x] == WHITE || b_y + cnt == 9) {
							int a = cnt - 1;
							flag[4] = 0;
							do {
								board_next[b_y + a][b_x] = WHITE;
								a--;
							} while (a >= 1);
						}
					}
					else {
						break;
					}
				}
				else if (i == 5) {//左下
					if (board_next[b_y + cnt][b_x - cnt] == WHITE) {
						board_next[b_y + cnt][b_x - cnt] = BLACK;
						cnt++;
						flag[5] = 1;
						if (board_next[b_y + cnt][b_x - cnt] == EMPTY || b_y + cnt == 8 && board_next[b_y + cnt][b_x - cnt] == WHITE|| b_x - cnt == 1 && board_next[b_y + cnt][b_x - cnt] == WHITE || b_y+cnt==9||b_x-cnt == 0) {
							int a = cnt - 1;
							flag[5] = 0;
							do {
								board_next[b_y + a][b_x - a] = WHITE;
								a--;
							} while (a >= 1);
						}
					}
					else {
						break;
					}
				}
				else if (i == 6) {//左
					if (board_next[b_y][b_x - cnt] == WHITE) {
						board_next[b_y][b_x - cnt] = BLACK;
						cnt++;
						flag[6] = 1; 
						if (board_next[b_y][b_x - cnt] == EMPTY || b_x - cnt == 1 && board_next[b_y][b_x - cnt] == WHITE || b_x-cnt == 0) {
							int a = cnt - 1;
							flag[6] = 0;
							do {
								board_next[b_y][b_x - a] = WHITE;
								a--;
							} while (a >= 1);
						}
					}
					else {
						break;
					}
				}
				else if (i == 7) {//左上
					if (board_next[b_y - cnt][b_x - cnt] == WHITE) {//さらに先の駒が白であるか確認
						board_next[b_y - cnt][b_x - cnt] = BLACK;//黒に反転
						cnt++;
						flag[7] = 1;
						if (board_next[b_y - cnt][b_x - cnt] == EMPTY || b_y - cnt == 1 && board_next[b_y - cnt][b_x - cnt] ==WHITE || b_x - cnt == 1 && board_next[b_y - cnt][b_x - cnt] == WHITE || b_y - cnt == 0 || b_x - cnt == 0) {//先の駒がない
							int a = cnt - 1;
							flag[7]=0;
							do {
								board_next[b_y - a][b_x - a] = WHITE;
								a--;
							} while (a >= 1);
						}
					}
					else {
						break;
				
					}
				}
				if (flag[i] == 0) {
					break;
				}
			} while (1);
			if (cnt == 1) { board_next[b_y][b_x] = EMPTY; return 2; }
			p = 1;
			break;
		default:
			break;
		}
	}

	if (p == EMPTY) {
		board_next[b_y][b_x] = EMPTY;
		return 2;
	}
	for (int i = 0; i < 8; i++) {
		sum += flag[i];
	}
	if (sum == EMPTY) {
		board_next[b_y][b_x] = EMPTY;
		return 2;
	}
	sum = EMPTY;

	if (aiueo == 1) { aiueo = 0; return 3; }//all_check中なのでここで終了

		memcpy((void*)board, (void*)board_next, sizeof(board_next));
			turn = WHITE;
		p = 0;
		display();//再描画
}

void finish() {
	int cntb=0, cntw=0;
	for (int i = 1; i < L; i++) {
		for (int j = 1; j < L; ++j) { switch (board[i][j]){ case BLACK: cntb++; break; case WHITE: cntw++; break; default: break; } } } printf("置ける場所が無くなったのでゲーム終了です。\n結果\n黒 %d個\n白 %d個\n",cntb,cntw); if (cntb > cntw) {
		printf("黒の勝ち\n\n");
	}
	else if(cntw>cntb){
		printf("白の勝ち\n\n");
	}
	else {
		printf("引き分け\n\n");
	}
	menu();
}

int check(int a, int b) {
	if (EMPTY != board[b][a]) {
		return 0;
	}
	if (turn == WHITE) {
		return w_while(a, b);
	}
	else {
		return b_while(a, b);
	}
}

void all_check() {
	aiueo = 1;
	for (int w = 0; w < 2; w++) {
		for (int i = 1; i < L; i++) {
			for (int j = 1; j < L; j++) { if (3 == check(j, i)) { if (w == 0) { return; }else{ printf("どこにも置けないのでパスします。\nもう一度"); return; } } } } turn_change(); } finish(); } void game() { int x; int y; all_check(); if (turn == BLACK) { printf("黒の手番です。手を入力してください。\nXを入力"); } else { printf("白の手番です。手を入力してください。\nXを入力"); } while (1) { if (scanf("%d", &x) >= 1) {//数値だけを入力させる
			break;
		}
		scanf("%*s");
		printf("もう一度入力してください。\n");
	}
	
	printf("Yを入力");

	while (1) {
		if (scanf("%d", &y) >= 1) {//数値だけを入力させる
			break;
		}
		scanf("%*s");
		printf("もう一度入力してください。\n");
	}

	if (1 != check(x, y)) {
		printf("そこには置けません。\n");
		game();
	}
}



void menu() {
	int start = 0;
	printf("Main menu:\n1)人間vs人間\nQ)Quit program\nPlease enter your selection:");
		while(1) {
			if (scanf("%d", &start) != 1) {//数値だけを入力させる
				scanf("%*s");
				printf("もう一度入力してください。\n");
				continue;
			}
			if (start == 1) {
				break;
			}
		}
	switch (start) {
	case 1:
		shokika();
		display();
		game();
	default:
		printf("もう一度入力してください。\n");
		menu();
	}
}

int main(int argc, char* argv[])
{
	menu();
	return 0;
}

ひっくり返す処理はすぐにできるだろうと思って作業に取り組んでいましたが、実際にコードを書いてみるとかなり難しかったです…

次回はAIと対戦できるプログラムを作って記事にします。

コメント