コード:
#include "DxLib.h"
#define BAN_SIZE 64 // 盤目一つのドットサイズ
#define BAN_WIDTH 10 // 盤の幅
#define BAN_HEIGHT 10 // 盤の縦長さ
#define BAN_LEFTUP_X 0 //一番左上の盤目の左上端X座標
#define BAN_LEFTUP_Y 0 //一番左上の盤目の左上端Y座標
#define BAN 0 // 盤目
#define BLACK 1 // 黒コマ
#define WHITE 2 // 白コマ
#define WALL -1 // 折り返し用の壁
// 盤のデータ
int BanData[ BAN_HEIGHT ][ BAN_WIDTH ] =
{
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } ,
{ -1, 0, 0, 0, 0, 0, 0, 0, 0, -1 } ,
{ -1, 0, 0, 0, 0, 0, 0, 0, 0, -1 } ,
{ -1, 0, 0, 0, 0, 0, 0, 0, 0, -1 } ,
{ -1, 0, 0, 0, 2, 1, 0, 0, 0, -1 } ,
{ -1, 0, 0, 0, 1, 2, 0, 0, 0, -1 } ,
{ -1, 0, 0, 0, 0, 0, 0, 0, 0, -1 } ,
{ -1, 0, 0, 0, 0, 0, 0, 0, 0, -1 } ,
{ -1, 0, 0, 0, 0, 0, 0, 0, 0, -1 } ,
{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }
} ;
void Display(int BanData[ BAN_HEIGHT ][ BAN_WIDTH ])
{
int i, j;
int GHandle1;
int GHandle2;
int GHandle3;
int GHandle4;
GHandle1 = LoadGraph("画像/オセロ盤目.bmp");
GHandle2 = LoadGraph("画像/背景.bmp");
GHandle3 = LoadGraph("画像/黒コマ.bmp");
GHandle4 = LoadGraph("画像/白コマ.bmp");
// 盤を描く
DrawGraph(0,0,GHandle2,TRUE);
for( i = 0 ; i < BAN_HEIGHT ; i ++ )
{
for( j = 0 ; j < BAN_WIDTH ; j ++ )
{
switch(BanData[ i ][ j ] )
{
case BAN : DrawGraph(i*BAN_SIZE, j*BAN_SIZE, GHandle1, FALSE); break;
case BLACK : DrawGraph(i*BAN_SIZE, j*BAN_SIZE, GHandle3, FALSE); break;
case WHITE : DrawGraph(i*BAN_SIZE, j*BAN_SIZE, GHandle4, FALSE); break;
}
}
}
}
//向きごとの移動量
char vec_y[] = {-1,-1,0,1,1,-1,0,-1};
char vec_x[] = {0,1,1,1,0,-1,-1,-1};
//vecで指定された向きについてひっくり返るコマがあるか確認する
int checkFlip(int y,int x,int turn,int vec)
{
int flag = 1;
while(1){
y += vec_y[vec];
x += vec_x[vec];
//盤面の外に出ていたら終了
if( x < 1 || y < 1 || x > BAN_WIDTH-2 || y > BAN_HEIGHT-2) return 0;
//空きマスだったら終了
if(BanData[y][x] == BAN) return 0;
//相手のコマがあったらフラグを立てる
if(BanData[y][x] == (turn ? BLACK : WHITE)){
flag = 1;
continue;
}
//もしフラグがたっていればループ脱出。いなければ終了
if(flag == 1) break;
return 0;
}
return 1;
}
//その場所に置くことができるかを確認する関数
int check(int y,int x,int turn)
{
int vec;
//どれか一方向でもひっくり返るか確認
for(vec = 0 ; vec < 8 ; ++vec){
if(checkFlip(y,x,turn,vec) == 1) return 1;
}
return 0;
}
//実際に裏返す関数
void flip(int y,int x,int turn,int vec){
while(1){
y += vec_y[vec];
x += vec_x[vec];
//自分のコマがあったら終了
if(BanData[y][x] == (turn ? WHITE : BLACK)) break;
//それ以外なら自分のコマで塗りつぶす
BanData[y][x] = (turn ? WHITE : BLACK);
}
}
//入力を受けて裏返せるか確かめる関数
int put(int y,int x,int turn){
int vec,flag=0;
//空白でなければ終了
if(BanData[y][x] != BAN) return 0;
//全方向について確認
for(vec=0 ; vec < 8 ; ++vec){
if(checkFlip(y,x,turn,vec) == 1){
//裏返す
flip(y,x,turn,vec);
flag = 1;
}
}
if(flag == 1){
//この場所にコマを置く
BanData[y][x]= (turn ? WHITE : BLACK);
return 1;
}
return 0;
}
//入力関数
void input(int turn)
{
int oldinput;
int nowinput;
int mouse X,mouseY;
int edgeinput;
int x, y;
oldinput = 0 ; // マウスの入力情報を初期化する
nowinput = 0 ;
mouse X = 0 ;
mouseY = 0 ;
while( ProcessMessage() == 0 ) // メインループ(何かキーが押されたらループを抜ける)
{
oldinput = nowinput ; // マウスの入力情報を更新する
nowinput = GetMouseInput() ;
edgeinput = nowinput & ~oldinput ;
GetMousePoint( &mouse X, &mouseY ) ;
x = ( mouseY - BAN_LEFTUP_X ) / BAN_SIZE ; // 盤目の座標を算出する
y = ( mouse X - BAN_LEFTUP_Y ) / BAN_SIZE ;
if( ( edgeinput & MOUSE_INPUT_LEFT ) != 0 ) // マウスの左ボタンが押されたら盤目の値を変化させる
{
if( x >= 1 && x < BAN_HEIGHT -1 && // 盤目の範囲内にある場合のみマップの状態を変化させる
y >= 1 && y < BAN_WIDTH -1 )
put(y,x,turn) == 1, BanData[ y ][ x ] = turn;
else MessageBox(NULL,"盤外です","ERROR",MB_OK);
}
}
}
void CPU_AI(int turn) //CPUのAI
{
int x, y;
int val_table[BAN_HEIGHT][BAN_WIDTH] =
{
{-100,-100,-100,-100,-100,-100,-100,-100,-100,-100},
{-100,120, -20, 20, 5, 5, 20, -20, 120, -100},
{-100,-20, -40, -5, -5, -5, -5, -40, -20, -100},
{-100, 20, -5, 15, 3, 3, 15, -5, 20, -100},
{-100, 5, -5, 3, 3, 3, 3, -5, 5, -100},
{-100, 5, -5, 3, 3, 3, 3, -5, 5, -100},
{-100, 20, -5, 15, 3, 3, 15, -5, 20, -100},
{-100,-20, -40, -5, -5, -5, -5, -40, -20, -100},
{-100,120, -20, 20, 5, 5, 20, -20, 120, -100},
{-100,-100,-100,-100,-100,-100,-100,-100,-100,-100}
};
for (y = 1; y < 9; y++){
for (x = 1; x < 9; x++){
switch (val_table[y][x] )
{
case 120 : (put(y-1,x-1,turn) == 1); break;
case 20 : (put(y-1,x-1,turn) == 1); break;
case 15 : (put(y-1,x-1,turn) == 1); break;
case 5 : (put(y-1,x-1,turn) == 1); break;
case 3 : (put(y-1,x-1,turn) == 1); break;
case -5 : (put(y-1,x-1,turn) == 1); break;
case -20 : (put(y-1,x-1,turn) == 1); break;
case -40 : (put(y-1,x-1,turn) == 1); break;
}
}
}
}
int checkEnd(int turn)
{
int i,j;
//置ける場所があるか確認
for(i = 1 ; i < BAN_WIDTH -1 ; ++i){
for(j = 1 ; j < BAN_HEIGHT -1 ; ++j){
//あれば普通に続行
if(BanData[i][j] == BAN && check(i,j,turn) == 1) return 0;
}
}
//場所が無かったので交替して探す
turn = (turn + 1) % 2;
for(i = 1 ; i < BAN_WIDTH -1 ; ++i){
for(j = 1 ; j < BAN_HEIGHT -1 ; ++j){
//あればpassして続行
if(BanData[i][j] == BAN && check(i,j,turn) == 1) return 1;
}
}
//なかったのでゲーム終了
return 2;
}
//勝者判定
void checkWinner(){
int i,j,b=0,w=0;
//コマを数え上げる
for(i = 1 ; i < BAN_WIDTH -1 ; ++i){
for(j = 1 ; j < BAN_HEIGHT -1 ; ++j){
switch(BanData[i][j]){
case BLACK:
++b;
break;
case WHITE:
++w;
break;
default :
break;
}
}
}
//勝者を表示
if(b > w) MessageBox(NULL,"黒が勝ちました","結果発表",MB_OK);
else if(b < w) MessageBox(NULL,"白が勝ちました","結果発表",MB_OK);
else MessageBox(NULL,"引き分けです","結果発表",MB_OK);
}
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow )
{
ChangeWindowMode(TRUE); // ウィンドウモードに設定
SetGraphMode( 640 , 640 , 32 ) ;
DxLib_Init(); // DXライブラリ初期化処理
int USERturn;
int turn = 0;
Display(BanData); //盤面の初期化
if(MessageBox(NULL,"先手を取りますか?","選択",MB_YESNO) == IDYES) //プレーヤー、先手か後手か選択
USERturn=BLACK;
else
USERturn=WHITE;
while(turn < 2) //ゲームのメインループ
{
Display(BanData); //盤面表示
//入力
switch(turn){
case 0:
turn = BLACK;
input(turn);
break;
case 1:
CPU_AI(turn);
break;
default:
MessageBox(NULL,"予期せぬエラー","ERROR",MB_OK);
return -1;
}
//手番交替
turn = (turn + 1) % 2;
//終了判定
switch(checkEnd(turn)){
case 1:
MessageBox(NULL,"置ける場所が無いためパスします","確認",MB_OK);
turn = (turn + 1) % 2;
break;
case 2:
MessageBox(NULL,"ゲームが終了しました","確認",MB_OK);
turn = 2;
break;
default:
break;
}
}
checkWinner();
DxLib_End() ; // DXライブラリ使用の終了処理
return 0 ; // ソフトの終了
}