コード:
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<time.h>
#define BLACK 1 // 黒
#define WHITE -1 // 白
#define EMPTY 0 // 盤面に何もない
#define PUTOK 2 // 盤面に何か置ける
#define MASU 8 // 8x8マスの定数
//グローバル変数
int field[MASU][MASU]; // フィールド座標 X,Y
int turn = BLACK; // 初期ターン
int menu_select = 0; // メニューセレクト用
bool endflag = false; // 終了フラグ
int putokcount; // 置ける場所数える
int bcount , wcount;// 黒白数える
// -------- グローバル変数 -------------
// フィールド描画
void Draw_field(){
int i,j; // for用
// フィールド表示
printf(" 12345678\n");
for(i=0;i<MASU;i++){
printf("%d ",i+1);
for(j=0;j<MASU;j++){
// 空き
if(field[j][i] == EMPTY){
printf("*");
}
// 黒
if(field[j][i] == BLACK){
printf("○");
bcount++;
}
// 白
if(field[j][i] == WHITE){
printf("●");
wcount++;
}
// 置ける場所
if(field[j][i] == PUTOK){
printf("☆");
putokcount++;
}
}
printf("\n");
}
printf("\n");
} // ---------Draw_field-------------
// 石探し
void Check_stone(){
int i=0,j=0; // 盤面探索for
int x=0,y=0; // 自色探索for
// PUTOK初期化
for(i=0;i<MASU;i++){
for(j=0;j<MASU;j++){
if(field[i][j] == PUTOK){
field[i][j] = EMPTY;
}
}
}
// 盤面探索
for(i=0;i<MASU;i++){
for(j=0;j<MASU;j++){
// 方向用変数
int right = field[j+1][i],
left = field[j-1][i],
up = field[j][i-1],
down = field[j][i+1],
right_up = field[j+1][i-1],
right_down = field[j+1][i+1],
left_up = field[j-1][i-1],
left_down = field[j-1][i+1];
// 空きがあったとき
if(field[j][i] == EMPTY){
// 空きマスから周囲8マス探索
// その方向の駒が相手のものであり、空きでなく、☆でないものであれば、
// その方向の自駒が出るまで探索。あれば☆を置く。
// 上下左右
if(right == -1 * turn && !((j+2)>7)){
for(x=j;x<MASU;x++){
if(field[x+1][i] == PUTOK || field[x+1][i] == EMPTY){
break;
}
if(field[x+1][i] == turn){
field[j][i] = PUTOK;
break;
}
}
}
if(left == -1 * turn && !((j-2)<=0)){
for(x=j;0<=x;x--){
if(field[x-1][i] == PUTOK || field[x-1][i] == EMPTY){
break;
}
if(field[x-1][i] == turn){
field[j][i] = PUTOK;
break;
}
}
}
if(down != turn && down != EMPTY && down != PUTOK){
for(y=i;y<=MASU;y++){
if(field[j][y+1] == PUTOK || field[j][y+1] == EMPTY){
break;
}
if(field[j][y+1] == turn){
field[j][i] = PUTOK;
break;
}
}
}
if(up != turn && up != EMPTY && up != PUTOK){
for(y=i;0<=y;y--){
if(field[j][y-1] == PUTOK || field[j][y-1] == EMPTY){
break;
}
if(field[j][y-1] == turn){
field[j][i] = PUTOK;
break;
}
}
}
// 斜め
//right_up = field[j+1][i-1],
if(right_up != turn && right_up != EMPTY && right_up != PUTOK){
for(x=j,y=i;x<=MASU,0<=y;x++,y--){
if(field[x+1][y-1] == PUTOK || field[x+1][y-1] == EMPTY){
break;
}
if(field[x+1][y-1] == turn){
field[j][i] = PUTOK;
break;
}
}
}
if(right_down != turn && right_down != EMPTY && right_down != PUTOK){
for(x=j,y=i;x<MASU,y<MASU;x++,y++){
if(field[x+1][y+1] == PUTOK || field[x+1][y+1] == EMPTY){
break;
}
if(field[x+1][y+1] == turn){
field[j][i] = PUTOK;
break;
}
}
}
if(left_up != turn && left_up != EMPTY && left_up != PUTOK){
for(x=j,y=i;0<=x,0<=y;x--,y--){
if(field[x-1][y-1] == PUTOK || field[x-1][y-1] == EMPTY){
break;
}
if(field[x-1][y-1] == turn){
field[j][i] = PUTOK;
break;
}
}
}
if(left_down != turn && left_down != EMPTY && left_down != PUTOK){
for(x=j,y=i;0<=x,y<MASU;x--,y++){
if(field[x-1][y+1] == PUTOK || field[x-1][y+1] == EMPTY){
break;
}
if(field[x-1][y+1] == turn){
field[j][i] = PUTOK;
break;
}
}
}
}
}
}
}// ------- Check_stone ------------
// 石変更処理
// 引数: sx 置いた石の座標X
// sy 置いた石の座標Y
void Change_stone(int sx, int sy){
int i,j;
int x,y;
int dx=0,dy=0;
// 引数置き換え
j = sx;
i = sy;
// 方向用変数
int right = field[j+1][i],
left = field[j-1][i],
up = field[j][i-1],
down = field[j][i+1],
right_up = field[j+1][i-1],
right_down = field[j+1][i+1],
left_up = field[j-1][i-1],
left_down = field[j-1][i+1];
// 空きマスから周囲8マス探索
// その方向の駒が相手のものであり、空きでなく、☆でないものであれば、
// 自色が出てくるまで探索、出てきたらひっくり返していく。
if(right = -1 * turn && !((j+2)>7)){
dx = 0;
for(x=j;x<MASU;x++){
// 敵色のときdx++
if(field[x+1][i] == -1*turn){
dx++;
// 次のがPUTOKだったら抜ける。
}else if(field[x+1][i] == PUTOK || field[x][i] == EMPTY){
break;
// 自色のとき、戻って反転
}else if(field[x+1][i] == turn){
while(dx!=0){
dx--;
field[x-dx][i] = turn;
}
break;
}
}
}
if(left == -1 * turn && !((j-2)<0)){
dx = 0;
for(x=j;0<=x;x--){
// 敵色のときdx++
if(field[x-1][i] == -1*turn){
dx++;
// 次のがPUTOKだったら抜ける。
}else if(field[x-1][i] == PUTOK || field[x+1][i] == EMPTY){
break;
// 自色のとき、戻って反転
}else if(field[x-1][i] == turn){
while(dx!=0){
dx--;
field[x+dx][i] = turn;
}
break;
}
}
}
if(down != turn && down != EMPTY && down != PUTOK){
dy=0;
for(y=i;y<MASU;y++){
// 敵色のときdx++
if(field[j][y+1] == -1*turn){
dy++;
// 次のがPUTOKだったら抜ける。
}else if(field[j][y+1] == PUTOK || field[j][y] == EMPTY){
break;
// 自色のとき、戻って反転
}else if(field[j][y+1] == turn){
while(dy!=0){
dy--;
field[j][y-dy] = turn;
}
break;
}
}
}
if(up != turn && up != EMPTY && up != PUTOK){
dy=0;
for(y=i;0<=y;y--){
// 敵色のときdx++
if(field[j][y-1] == -1*turn){
dy++;
// 次のがPUTOKだったら抜ける。
}else if(field[j][y-1] == PUTOK || field[j][y] == EMPTY){
break;
// 自色のとき、戻って反転
}else if(field[j][y-1] == turn){
while(dy!=0){
dy--;
field[j][y+dy] = turn;
}
break;
}
}
}
if(right_up != turn && right_up != EMPTY && right_up != PUTOK){
dx=0;
dy=0;
for(x=j,y=i;x<MASU,0<=y;x++,y--){
// 敵色のときdx++
if(field[x+1][y-1] == -1*turn){
dx++;
dy++;
// 次のがPUTOKだったら抜ける。
}else if(field[x+1][y-1] == PUTOK || field[x][y] == EMPTY){
break;
// 自色のとき、戻って反転
}else if(field[x+1][y-1] == turn){
while(dx!=0 && dy!=0){
dx--;
dy--;
field[x-dx][y+dy] = turn;
}
break;
}
}
}
if(right_down != turn && right_down != EMPTY && right_down != PUTOK){
dx=0;
dy=0;
for(x=j,y=i;x<MASU,y<MASU;x++,y++){
// 敵色のときdx++
if(field[x+1][y+1] == -1*turn){
dx++;
dy++;
// 次のがPUTOKだったら抜ける。
}else if(field[x+1][y+1] == PUTOK || field[x][y] == EMPTY){
break;
// 自色のとき、戻って反転
}else if(field[x+1][y+1] == turn){
while(dx!=0 && dy!=0){
dx--;
dy--;
field[x-dx][y-dy] = turn;
}
break;
}
}
}
if(left_up != turn && left_up != EMPTY && left_up != PUTOK){
dx=0;
dy=0;
for(x=j,y=i;0<=x,0<=y;x--,y--){
// 敵色のときdx++
if(field[x-1][y-1] == -1*turn){
dx++;
dy++;
// 次のがPUTOKだったら抜ける。
}else if(field[x-1][y-1] == PUTOK || field[x-1][y-1] == EMPTY){
break;
// 自色のとき、戻って反転
}else if(field[x-1][y-1] == turn){
while(dx!=0 && dy!=0){
dx--;
dy--;
field[x+dx][y+dy] = turn;
}
break;
}
}
}
if(left_down != turn && left_down != EMPTY && left_down != PUTOK){
dx=0;
dy=0;
for(x=j,y=i;0<=x,y<MASU;x--,y++){
// 敵色のときdx++
if(field[x-1][y+1] == -1*turn){
dx++;
dy++;
// 次のがPUTOKだったら抜ける。
}else if(field[x-1][y+1] == PUTOK || field[x-1][y+1] == EMPTY){
break;
// 自色のとき、戻って反転
}else if(field[x-1][y+1] == turn){
while(dx!=0 && dy!=0){
dx--;
dy--;
field[x+dx][y-dy] = turn;
}
break;
}
}
}
}// --------Change_stone ------------
// 石置く処理
void Put_stone(){
int x,y; // 座標入力用
// どこにも置けないとき
if(putokcount == 0){
printf("どこにも置けません。\n");
turn *= -1;
}
if(turn == BLACK){
printf("○のターンです。\n");
}else{
printf("●のターンです。\n");
}
printf("石の座標Xを指定してください。\n");
scanf("%d",&x);
printf("石の座標Yを指定してください。\n");
scanf("%d",&y);
printf("\n");
// 絶対値にする。
x = abs(x);
y = abs(y);
// 数値が小さい
if(x == 0 || y == 0){
printf("======数値が小さすぎます!======\n");
// 数値が大きい
}else if(x >= MASU+1 || y >= MASU+1){
printf("======数値が大きすぎます!======\n");
// 数値が正しい
}else{
// 座標調整
x = x-1;
y = y-1;
// 黒ターン
if(turn == BLACK){
// どこにも置けないとき
if(putokcount == 0){
printf("どこにも置けません。\n");
turn = WHITE;
}else{
// 0のとき
if(field[x][y] == PUTOK){
Change_stone(x,y);
field[x][y] = BLACK; //黒置く
turn = WHITE; //ターン推移
// 何かあるとき
}else{
printf("======そこには置けません。======\n");
}
}
// 白ターン
}else if(turn == WHITE){
// どこにも置けないとき
if(putokcount == 0){
printf("どこにも置けません。\n");
turn = BLACK;
}else{
// 0のとき
if(field[x][y] == PUTOK){
Change_stone(x,y);
field[x][y] = WHITE; //白置く
turn = BLACK; //ターン推移
// 何かあるとき
}else{
printf("======そこには置けません。======\n");
}
}
}
}
}// --------- Put_stone ---------
// 単純AI
void tanjunAI(){
int i,j;
int rnd; // 乱数
bool putflag = false;
// rnd ==1 になるまで、(置かれるまで)回し続ける。
while(putflag == false){
// 置ける場所探索
for(i=0;i<MASU;i++){
for(j=0;j<MASU;j++){
// 8x8上に☆があり、ランダムが1生成されたとき
if(field[j][i] == PUTOK){
// srand 毎回起動の際に乱数を変える
srand((unsigned)time(NULL));
// 乱数を 0 ~ 1 の間で作る
rnd = rand() % 2;
// printf("%d",rnd); // 確認用printf
// ランダムで1が出たとき、PVPと同じような操作をする。
if(rnd == 1){
printf("X %d ,Y %d に置きました。\n",j+1,i+1);
Change_stone(j,i);
field[j][i] = turn;
putflag = true;
i=9;
j=9;
break;
}
}
}
}
}
}// -------- tanjunAI ---------
// 単純AI戦 石置く処理
void Put_stone_tanjun(){
int x=0,y=0; // 座標入力用
// ターン推移
if(turn == BLACK){
printf("○のターンです。\n");
}else{
printf("●のターンです。\n");
}
if(turn == BLACK){
printf("石の座標Xを指定してください。\n");
scanf("%d",&x);
printf("石の座標Yを指定してください。\n");
scanf("%d",&y);
printf("\n");
// 絶対値にする。
x = abs(x);
y = abs(y);
}
// 黒ターン
if(turn == BLACK){
// 数値が小さい
if(x == 0 || y == 0){
printf("======数値が小さすぎます!======\n");
// 数値が大きい
}else if(x >= MASU+1 || y >= MASU+1){
printf("======数値が大きすぎます!======\n");
// 数値が正しい
}else{
// どこにも置けないとき
if(putokcount == 0){
printf("どこにも置けません。\n");
turn = WHITE;
}else{
// 座標調整
x = x-1;
y = y-1;
// 0のとき
if(field[x][y] == PUTOK){
Change_stone(x,y);
field[x][y] = turn; //黒置く
turn = WHITE; //ターン推移
// 何かあるとき
}else{
printf("======そこには置けません。======\n");
}
}
}
// 白ターン
}else if(turn == WHITE){
// どこにも置けないとき
if(putokcount == 0){
printf("どこにも置けません。\n");
turn = BLACK;
}else{
tanjunAI();
turn = BLACK;
}
}
}//------- Put_stone_tanjun --------------
void End(){
int i,j;
int bcount=0,wcount=0;
// コマカウント
for(i=0;i<MASU;i++){
for(j=0;j<MASU;j++){
// 黒
if(field[j][i] == BLACK){
bcount++;
}
// 白
if(field[j][i] == WHITE){
wcount++;
}
}
}
printf("○ %d 個\n",bcount);
printf("● %d 個\n",wcount);
// 黒勝ち
if(wcount < bcount){
printf("======================\n");
printf("=== ○の勝ち!! ===\n");
printf("======================\n");
// 白勝ち
}else if(bcount < wcount){
printf("======================\n");
printf("=== ●の勝ち!! ===\n");
printf("======================\n");
}
}// ------- End -------------
// タイトル
void Title(){
printf("======================\n");
printf("=== オセロ プレイヤーVSプレイヤー ===\n");
printf("======================\n");
printf("マイナス入力は絶対値になります。\n");
printf("文字入力したらエラーおきます。\n\n");
printf("~~ ゲームメニュー ~~\n");
printf("番号を選択してください。\n");
printf("1 プレイヤーVSプレイヤー\n");
printf("2 プレイヤーVS単純AI\n");
printf("番号を入力してください→ ");
scanf("%d",&menu_select);
}// --------- Title ----------
// 先攻か後攻か決める
void senkou(){
int senkouFlag;
printf("先攻、後攻を決めてください。\n");
printf("1 先攻\n");
printf("2 後攻\n");
scanf("%d",&senkouFlag);
// 先攻であれば黒から
if(senkouFlag == 1){
turn = 1;
}else{
turn = -1;
}
}// --------- senkou ----------
// メイン
int main (void){
Title();
// 初期石追加
field[MASU/2-1][MASU/2-1] = WHITE;
field[MASU/2-1][MASU/2] = BLACK;
field[MASU/2][MASU/2] = WHITE;
field[MASU/2][MASU/2-1] = BLACK;
field[1][3] = BLACK;
field[2][3] = BLACK;
field[6][3] = BLACK;
// メニュー1 プレイヤーVSプレイヤー
if(menu_select == 1){
// 終了フラグが立っていない間ループ
while(endflag == false){
bcount = 0;
wcount = 0;
putokcount = 0;
Check_stone();
Draw_field();
printf("○%d\n●%d\nputok%d\n",bcount,wcount,putokcount);
// 白黒が0、白黒合計で64のとき終了
if(bcount == 0 || wcount == 0 || bcount+wcount >= 64){
endflag = true;
}
Put_stone();
}
}//---------- menu1 PVP -------------
// メニュー2 プレイヤーVS単純AI
if(menu_select == 2){
senkou();
// 終了フラグが立っていない間ループ
while(endflag == false){
bcount = 0;
wcount = 0;
putokcount = 0;
Check_stone();
Draw_field();
printf("○%d\n●%d\nputok%d\n",bcount,wcount,putokcount);
// 白黒が0、白黒合計で64のとき終了
if(bcount == 0 || wcount == 0 || bcount+wcount >= 64){
endflag = true;
}
Put_stone_tanjun();
}
}//-------- menu2 PV単純AI -------------
End();
return 0;
}// ------- main -----------