0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

re:re:C++でオセロAIを作る1(超初心者です)

Last updated at Posted at 2023-07-21

早くAIを作りたいのに、ところどころ気になってしまって、また改良。
名前を入力できるようにしました。

↓ソースコード↓

オセロ再改良版
#include <stdio.h>
#include <string.h>

 /*実行する関数(どっちの番か、ボード配列)戻り値→置けたら0,置ける場所がなかったら1*/
int run(char user[20], char board[12][12],char user1[20],char user2[20]);

/*配置を出力する関数*/
void outputBoard(char board[12][12]);

/*裏返す関数(どっちの番か、ベクトル、初期位置(縦、横)、配列)*/
int revers(char user[20], int i, int j, int vertical, int horizon, char board[12][12],char user1[20],char user2[20]);

/*まだ打てる場所があるか確認する関数(どっちの番か、ボード配列)、戻り値→置けない場所の数*/
int check(char user[20], char board[12][12],char user1[20],char user2[20]);

/*そこに打てるか確認だけする関数*/
int spe_check(char user[20], int i, int j, int vertical, int horizon, char board[12][12], char user1[20], char user2[20]);


/*ベクトル(dir_ver,dir_hor)
(-1,-1)(-1,0)(-1,1)
(0,-1)(vertical,horizon)(0,1)
(1,-1)(1,0)(1,1)*/

int main(void) {

	int i, j, cntNoRev;
	int cntB = 0;
	int cntW = 0;
	char user1[20] ;
	char user2[20] ;
	char partner = 'W';
	char disc = 'B';
	char board[12][12];

	/*最初の配置を配列に代入(縦がi)*/
	for (i = 0; i < 12; i++) {
		for (j = 0; j < 12; j++) {
			if ((i == 4 && j == 4) || (i == 5 && j == 5)) {
				board[i][j] = 'B';
				continue;
			}

			if ((i == 4 && j == 5) || (i == 5 && j == 4)) {
				board[i][j] = 'W';
				continue;
			}
			board[i][j] = ':';
		}
	}

	/*配置を出力*/
	outputBoard(board);

	/*名前の入力*/
	printf("先攻のプレイヤーの名前を入力してください。");
	scanf_s("%s", user1, 20);
	printf("後攻のプレイヤーの名前を入力してください。");
	scanf_s("%s", user2, 20);

	/*----実行-----*/

	while (1) {

		/*---------Bの番---------*/

		cntNoRev = run(user1, board, user1, user2);

		if (cntNoRev == 0) {
			outputBoard(board);
		}

		cntB = 0;
		cntW = 0;

		/*決着の確認*/
		for (i = 1; i <= 8; i++) {
			for (j = 1; j <= 8; j++) {
				if (board[i][j] == 'B')
					cntB++;
				if (board[i][j] == 'W')
					cntW++;
			}
		}

		if ((cntB + cntW == 64) || cntB == 0 || cntW == 0)
			break;

		cntB = 0;
		cntW = 0;

		/*---------Wの番---------*/

		cntNoRev = run(user2, board, user1, user2);

		if (cntNoRev == 0) {
			outputBoard(board);
		}

		cntB = 0;
		cntW = 0;

		/*決着の確認*/
		for (i = 1; i <= 8; i++) {
			for (j = 1; j <= 8; j++) {
				if (board[i][j] == 'B')
					cntB++;
				if (board[i][j] == 'W')
					cntW++;
			}
		}

		if ((cntB + cntW == 64) || cntB == 0 || cntW == 0)
			break;

		cntB = 0;
		cntW = 0;

	}

	/*勝敗の確認*/

	cntB = 0;
	cntW = 0;

	for (i = 1; i <= 8; i++) {
		for (j = 1; j <= 8; j++) {
			if (board[i][j] == 'B')
				cntB++;
			if (board[i][j] == 'W')
				cntW++;
		}
	}

	if (cntB > cntW)
		printf("%d対%dであなたの勝ちです", cntB, cntW);
	if (cntB == cntW)
		printf("引き分けです");
	if (cntB < cntW)
		printf("%d対%dでの勝ちです", cntB, cntW);

	return 0;
}

/*配置を出力する関数*/
void outputBoard(char board[12][12])
{
	int i, j;

	for (i = 1; i <= 8; i++) {
		printf("\t%d", i);
	}
	printf("\n");

	for (i = 1; i <= 8; i++) {
		printf("%d\t", i);
		for (j = 1; j <= 8; j++) {
			printf("%c\t", board[i][j]);
		}
		printf("\n\n");
	}
}

/*実行する関数(どっちの番か、ボード配列)戻り値→置けたら0,置ける場所がなかったら1*/
int run(char user[20], char board[12][12], char user1[20], char user2[20])
{
	int i, j, horizon, vertical, dir_ver, dir_hor, tmp1, tmp2;
	int cntRev = 0;//revers_to_Aを実行した回数をカウント
	int cntNoPut = 0;//revers_to_Aを実行したけど置けなかった回数をカウント
	int cntNoRev = 0;//どこにも置けない→+1
	char disc = 'W';
	char partner = 'B';
	char you[20] ;
	char computer[20] ;
	strcpy_s(you, user1);
	strcpy_s(computer, user2);

	if (strcmp(you, user) == 0) {
		disc = 'B';
		partner = 'W';
	}
	else if (strcmp(computer, user) == 0) {
		disc = 'W';
		partner = 'B';
	}

	while (cntRev == 0 || cntRev == cntNoPut) {

		tmp1 = check(user, board, user1,  user2);
		if (tmp1 == 64) {
			printf(" %cをどこにも置けません\n", disc);
			cntNoRev++;
			break;
		}

		printf("%sの番です。どこに%cを打ちますか?(上の数字が先)\n", user, disc);

		scanf_s("%d", &horizon);
		scanf_s("%d", &vertical);

		j = 0;
		if (board[vertical][horizon] != ':') {
			printf("そこには打てません\n");
			continue;
		}

		if (board[vertical][horizon] == ':') {

			/*置いて裏返す*/
			for (i = vertical - 1; i <= vertical + 1; i++) {
				for (j = horizon - 1; j <= horizon + 1; j++) {
					if (board[i][j] == partner) {
						dir_ver = i - vertical;
						dir_hor = j - horizon;
						tmp2 = revers(user, dir_ver, dir_hor, vertical, horizon, board, user1,  user2);
						cntRev++;
						if (tmp2 != 0)
							cntNoPut++;
					}
				}
			}

			if (cntRev == 0 || cntRev == cntNoPut) {
				printf("そこには打てません\n");
				board[vertical][horizon] = ':';
			}
		}
	}

	return cntNoRev;
}


/*裏返す関数(ベクトル、初期位置(縦、横)、配列),裏返せた→0、裏返せない→1*/
int revers(char user[20], int dir_ver, int dir_hor, int vertical, int horizon, char board[12][12], char user1[20], char user2[20])
{
	int move = 1;
	int i, tmp_hor, tmp_ver;
	tmp_hor = horizon;
	tmp_ver = vertical;
	int isReversed = 0;
	char disc = 'B';
	char partner = 'W';
	char you[20] ;
	char computer[20] ;
	strcpy_s(you, user1);
	strcpy_s(computer, user2);

	if (strcmp(you, user) == 0) {
		disc = 'B';
		partner = 'W';
	}
	else if (strcmp(computer, user) == 0) {
		disc = 'W';
		partner = 'B';
	}

	board[vertical][horizon] = disc;

	while (board[tmp_ver + dir_ver][tmp_hor + dir_hor] == partner) {


		if (board[vertical + dir_ver * 2][horizon + dir_hor * 2] == ':') {
			isReversed++;
			break;
		}

		if (board[vertical + dir_ver * 2][horizon + dir_hor * 2] == partner) {
			horizon += dir_hor;
			vertical += dir_ver;
			move++;
		}

		if (board[vertical + dir_ver * 2][horizon + dir_hor * 2] == disc) {

			for (i = 0; i <= move; i++) {

				if (dir_ver != 0 && dir_hor != 0)
					board[vertical + dir_ver - dir_ver * i][horizon + dir_hor - dir_hor * i] = disc;

				if (dir_ver == 0)
					board[vertical][horizon + dir_hor - dir_hor * i] = disc;

				if (dir_hor == 0)
					board[vertical + dir_ver - dir_ver * i][horizon] = disc;

			}

		}

	}

	return isReversed;

}


/*打てる場所を確認する関数、戻り値→置けない場所の数*/
int check(char user[20], char board[12][12], char user1[20], char user2[20])
{
	int i, j, dir_ver, dir_hor, is, horizon, vertical;
	int cntRev = 0;
	int cntNoPut = 0;
	int cnt = 0;//打てなかった数をカウント
	char disc = 'B';
	char partner = 'W';
	char you[20] ;
	char computer[20] ;
	strcpy_s(you, user1);
	strcpy_s(computer, user2);

	if (strcmp(you, user) == 0) {
		disc = 'B';
		partner = 'W';
	}
	else if (strcmp(computer, user) == 0) {
		disc = 'W';
		partner = 'B';
	}

	for (vertical = 1; vertical <= 8; vertical++) {
		for (horizon = 1; horizon <= 8; horizon++) {

			if (board[vertical][horizon] != ':') {
				cnt++;
				continue;
			}

			for (i = vertical - 1; i <= vertical + 1; i++) {
				for (j = horizon - 1; j <= horizon + 1; j++) {
					if (board[i][j] == 'W') {
						dir_ver = i - vertical;
						dir_hor = j - horizon;
						is = spe_check(user, dir_ver, dir_hor, vertical, horizon, board, user1, user2);
						cntRev++;
						if (is != 0)
							cntNoPut++;
					}
				}
			}

			if (cntRev == 0 || cntRev == cntNoPut) {
				cnt++;
			}

			cntRev = 0;
			cntNoPut = 0;

		}
	}

	return cnt;
}

/*そこに打てるか確認だけする関数(打てる→0、打てない→1)*/
int spe_check(char user[20], int dir_ver, int dir_hor, int vertical, int horizon, char board[12][12], char user1[20], char user2[20])
{

	int  tmp_ver, tmp_hor;
	tmp_hor = horizon;
	tmp_ver = vertical;
	int is = 0;
	char disc = 'B';
	char partner = 'W';
	char you[20] ;
	char computer[20];
	strcpy_s(you, user1);
	strcpy_s(computer, user2);

	if (strcmp(you, user) == 0) {
		disc = 'B';
		partner = 'W';
	}
	else if (strcmp(computer, user) == 0) {
		disc = 'W';
		partner = 'B';
	}

	while (board[tmp_ver + dir_ver][tmp_hor + dir_hor] == partner) {

		if (board[vertical + dir_ver * 2][horizon + dir_hor * 2] == ':') {
			is++;
			break;
		}

		if (board[vertical + dir_ver * 2][horizon + dir_hor * 2] == partner) {
			horizon += dir_hor;
			vertical += dir_ver;
		}

		if (board[vertical + dir_ver * 2][horizon + dir_hor * 2] == disc) {
			break;
		}

	}

	return is;

}
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?