初めて自分のパソコンを持って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;
}