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.

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

Last updated at Posted at 2023-07-18

初めて自分のパソコンを持って3か月。「やさしいC」から独学でC++の勉強を始めて2か月のガチ初心者です。
for文,if文など基礎中の基礎しか扱えませんが、学んだことの実践としてオセロのAIに挑戦してみます。
第一歩として、オセロを遊べるプログラムをなんとか作りました。
「もう置いてあるところには置けない」「ちゃんと自分の色同士で挟めてないと置けない」など、コンピュータがランダムで置いても大丈夫なような設定のはずです。
明日からは相手役をコンピュータがやってくれるプログラムに挑戦します。

/追記/
ところどころバグがあったので、改良しました。
450行を超えてしまった、、、。精進します。

↓ソースコード↓(かなりぶきっちょです)

オセロ(人間vs人間)
#include <stdio.h>

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

/*Aの番に裏返す関数(ベクトル、初期位置(縦、横)、配列)*/
int bbb(int a, int b, int d, int c, char aa[12][12]);

/*Bの番に裏返す関数(ベクトル、初期位置(縦、横)、配列)*/
int ccc(int a, int b, int d, int c, char aa[12][12]);

/*Aの番にまだ打てるか確認する関数*/
int ddd(char aa[12][12]);

/*Aをそこに打てるか確認だけする関数*/
int eee(int a, int b, int d, int c, char aa[12][12]);

/*Bの番にまだ打てるか確認する関数*/
int fff(char aa[12][12]);

/*Bをそこに打てるか確認だけする関数*/
int ggg(int a, int b, int d, int c, char aa[12][12]);

/*ベクトル(a,b)
(-1,-1)(-1,0)(-1,1)
(0,-1)(d,c)(0,1)
(1,-1)(1,0)(1,1)*/

int main(void) {
	int a, b, c, d, e, f, k,n;
	int g = 0;
	int j = 0;
	int m = 0;
	int p = 0;
	char aa[12][12];

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

			if ((a == 4 && b == 5) || (a == 5 && b == 4)) {
				aa[a][b] = 'B';
				continue;
			}
			aa[a][b] = ':';
		}
	}

	/*配置を出力*/
	aaa(aa);

	printf("Aが先行です。\n");

	for (a = 0; a < 50; a++){

		while (g == 0||g==j) {

			n = ddd(aa);
			if (n == 64) {
				printf("Aをどこにも置けません\n");
				break;
			}

			/*----------Aの番-----------*/
			printf("Aの番です。どこに打ちますか?(上の数字が先)\n");

			scanf_s("%d", &c);
			scanf_s("%d", &d);

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

			if (aa[d][c] == ':') {

				/*置いて裏返す*/
				for (a = d - 1; a <= d + 1; a++) {
					for (b = c - 1; b <= c + 1; b++) {
						if (aa[a][b] == 'B') {
							e = a - d;
							f = b - c;
							k = bbb(e, f, d, c, aa);
							g++;
							if (k != 0)
								j++;
						}
					}
				}
				/*↓gはbbbを実行した回数、jは実行したけどAが置かれなかった回数*/
				if (g == 0 || g == j) {
					printf("そこには打てません\n");
					aa[d][c] = ':';
				}
			}
		}

		aaa(aa);
		g = 0;

		/*決着の確認*/
		for (a = 1; a <= 8; a++) {
			for (b = 1; b <= 8; b++) {
				if (aa[a][b] == 'A')
					m++;
				if (aa[a][b] == 'B')
					p++;
			}
		}

		if ((m + p == 64) || m == 0 || p == 0){
            m=0;
            p=0;
			break;
         }

		while (g == 0||g==j) {

			n = fff(aa);
			if (n == 64) {
				printf("Aをどこにも置けません\n");
				break;
			}

			/*----------Bの番-------------*/
			printf("Bの番です。どこに打ちますか?(上の数字が先)\n");

			scanf_s("%d", &c);
			scanf_s("%d", &d);

			j = 0;

			if (aa[d][c] != ':') {
				printf("そこには打てません\n");
				continue;
			}
			if (aa[d][c] == ':') {

				/*置いて裏返す*/
				for (a = d - 1; a <= d + 1; a++) {
					for (b = c - 1; b <= c + 1; b++) {
						if (aa[a][b] == 'A') {
							e = a - d;
							f = b - c;
							k = ccc(e, f, d, c, aa);
							g++;
							if (k != 0)
								j++;
						}
					}
				}

				/*↓gはcccを実行した回数、jは実行したけどBが置かれなかった回数*/
				if (g == 0 || g == j) {
					printf("そこには打てません\n");
					aa[d][c] = ':';
				}
			}
		}

		aaa(aa);
		g = 0;

		/*決着の確認*/
		for (a = 1; a <= 8; a++) {
			for (b = 1; b <= 8; b++) {
				if (aa[a][b] == 'A')
					m++;
				if (aa[a][b] == 'B')
					p++;
			}
		}

		if ((m + p == 64) || m == 0 || p == 0){
          m=0;
          p=0;
			break;
       }

	}

	/*勝敗の確認*/

	for (a = 1; a <= 8; a++) {
		for (b = 1; b <= 8; b++) {
			if (aa[a][b] == 'A')
				m++;
			if (aa[a][b] == 'B')
				p++;
		}
	}
	if (m > p)
		printf("%d対%dでAの勝ちです", m, p);
	if (m == p)
		printf("引き分けです");
	if (m < p)
		printf("%d対%dでBの勝ちです", p, m);

	return 0;
}

/*配置を出力する関数*/
void aaa(char aa[12][12])
{
	int a, b;

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

	for (a = 1; a <= 8; a++) {
		printf("%d\t", a);
		for (b = 1; b <= 8; b++) {
			printf("%c\t", aa[a][b]);
		}
		printf("\n\n");
	}
}


/*Aの番に裏返す関数(ベクトル、初期位置(縦、横)、配列)*/
int bbb(int a, int b, int d, int c, char aa[12][12])
{
	int e = 1;
	int f, g, h;
	g = c;
	h = d;
	int i = 0;

	aa[d][c] = 'A';

	while (aa[h + a][g + b] == 'B') {


		if (aa[d + a * 2][c + b * 2] == ':') {
			i++;
			break;
		}

		if (aa[d + a * 2][c + b * 2] == 'B') {
			c += b;
			d += a;
			e++;
		}

		if (aa[d + a * 2][c + b * 2] == 'A') {

			for (f = 0; f <= e; f++) {

				if (a != 0 && b != 0)
					aa[d + a * 2 - a - a * f][c + b * 2 - b - b * f] = 'A';

				if (a == 0)
					aa[d][c + b * 2 - b - b * f] = 'A';

				if (b == 0)
					aa[d + a * 2 - a - a * f][c] = 'A';

			}

		}

	}

	return i;

}

/*Bの番に裏返す関数(ベクトル、初期位置(縦、横)、配列)*/
int ccc(int a, int b, int d, int c, char aa[12][12])
{
	int e = 1;
	int f, g, h;
	g = c;
	h = d;
	int i = 0;

	aa[d][c] = 'B';

	while (aa[h + a][g + b] == 'A') {

		if (aa[d + a * 2][c + b * 2] == ':') {
			i++;
			break;
		}

		if (aa[d + a * 2][c + b * 2] == 'A') {
			c += b;
			d += a;
			e++;
		}

		if (aa[d + a * 2][c + b * 2] == 'B') {

			for (f = 0; f <= e; f++) {

				if (a != 0 && b != 0)
					aa[d + a * 2 - a - a * f][c + b * 2 - b - b * f] = 'B';

				if (a == 0)
					aa[d][c + b * 2 - b - b * f] = 'B';

				if (b == 0)
					aa[d + a * 2 - a - a * f][c] = 'B';

			}

		}

	}

	return i;

}

/*Aの番にまだ打てるか確認する関数*/
int ddd(char aa[12][12]) 
{
	int a,b,e,f,k,c, d;
	int g = 0;
	int j = 0;
	int n = 0;//打てなかった数をカウント
	for (d = 1; d <= 8; d++) {
		for (c = 1; c <= 8; c++) {

			if (aa[d][c] != ':') {
				n++;
				continue;
			}

			for (a = d - 1; a <= d + 1; a++) {
				for (b = c - 1; b <= c + 1; b++) {
					if (aa[a][b] == 'B') {
						e = a - d;
						f = b - c;
						k = eee(e, f, d, c, aa);
						g++;
						if (k != 0)
							j++;
					}
				}
			}
			/*↓gはbbbを実行した回数、jは実行したけどAが置けなかった回数*/
			if (g == 0 || g == j) {
				n++;
			}

			g = 0;
			j = 0;

		}
	}

	return n;
}

/*Aをそこに打てるか確認だけする関数*/
int eee(int a, int b, int d, int c, char aa[12][12]) 
{

	int  g, h;
	g = c;
	h = d;
	int i = 0;

	while (aa[h + a][g + b] == 'B') {


		if (aa[d + a * 2][c + b * 2] == ':') {
			i++;
			break;
		}

		if (aa[d + a * 2][c + b * 2] == 'B') {
			c += b;
			d += a;
		}

		if (aa[d + a * 2][c + b * 2] == 'A') {

			break;
		}

	}

	return i;

}

/*Bの番にまだ打てるか確認する関数*/
int fff(char aa[12][12])
{
	int a, b, e, f, k, c, d;
	int g = 0;
	int j = 0;
	int n = 0;//打てなかった数をカウント
	for (d = 1; d <= 8; d++) {
		for (c = 1; c <= 8; c++) {

			if (aa[d][c] != ':') {
				n++;
				continue;
			}

			for (a = d - 1; a <= d + 1; a++) {
				for (b = c - 1; b <= c + 1; b++) {
					if (aa[a][b] == 'A') {
						e = a - d;
						f = b - c;
						k = ggg(e, f, d, c, aa);
						g++;
						if (k != 0)
							j++;
					}
				}
			}
			/*↓gはbbbを実行した回数、jは実行したけどAが置けなかった回数*/
			if (g == 0 || g == j) {
				n++;
			}

			g = 0;
			j = 0;

		}
	}

	return n;
}

/*Bをそこに打てるか確認だけする関数*/
int ggg(int a, int b, int d, int c, char aa[12][12])
{
	int  g, h;
	g = c;
	h = d;
	int i = 0;

	while (aa[h + a][g + b] == 'A') {


		if (aa[d + a * 2][c + b * 2] == ':') {
			i++;
			break;
		}

		if (aa[d + a * 2][c + b * 2] == 'A') {
			c += b;
			d += a;
		}

		if (aa[d + a * 2][c + b * 2] == 'B') {

			break;
		}

	}

	return i;
}
0
0
4

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?