
/*//////////////////////////////////////////////////////////////////////*/
//「最弱オセロ！」 ジャンル:オセロゲーム                                //
//言語：C/C++　開発環境:Visual C++ 2010 Express ライブラリ:DXライブラリ //
//作成者：またみふ                                                      //
//                                                                      //
//2011 4/18 完成                                                        //
//                                                                      //
/*//////////////////////////////////////////////////////////////////////*/

////////////////////////
//                    //
//       宣言部       //
//                    //
////////////////////////

//#define部
#define Mas 32;

//インクルード部
#include "DxLib.h"
#include <stdlib.h>
#include <string.h>

//グローバル変数宣言部
char Key[256];
int Game_music;
int koma[3];
const int H = 8;
const int W = 8;
const int init_x=0;
const int init_y=0;
//白色
const int wh = GetColor(255,255,255);
//青色
const int bl = GetColor(0,0,255);
//赤色
const int red = GetColor(255,0,0);
//緑色
const int gr = GetColor(0,255,0);
//水色
const int Haikei = GetColor(51,204,255);
//黒色
const int Kuro = GetColor(0,0,0);
//int型ステージ配列宣言
const int t_stage[H][W] =

{{0,0,0,0,0,0,0,0},
 {0,0,0,0,0,0,0,0},
 {0,0,0,0,0,0,0,0},
 {0,0,0,2,1,0,0,0},
 {0,0,0,1,2,0,0,0},
 {0,0,0,0,0,0,0,0},
 {0,0,0,0,0,0,0,0},
 {0,0,0,0,0,0,0,0}};

//評価値配列
const int val[H][W] =

{{120, -20,  20,   5,   5,  20, -20, 120},
 {-20, -40,  -5,  -5,  -5,  -5, -40, -20},
 { 20,  -5,  15,   3,   3,  15,  -5,  20},
 {  5,  -5,   3,   3,   3,   3,  -5,   5},
 {  5,  -5,   3,   3,   3,   3,  -5,   5},
 { 20,  -5,  15,   3,   3,  15,  -5,  20},
 {-20, -40,  -5,  -5,  -5,  -5, -40, -20},
 {120, -20,  20,   5,   5,  20, -20, 120}};

//構造体
struct ai{

	int x;
	int y;
	int val;
};
ai ai_val[H*W];

//列挙型宣言部

enum object{

	SIRO=-1,
	STAGE,
	KURO
};

 object stage[H][W]; //object型ステージ状態配列を確保

enum TURN{

	BLACK,	//黒のターン
	WHITE   //白のターン
};

TURN turn = BLACK;//TURN型はターンの種類

enum MODE{

	GAME_TITLE,
	GAME_MAIN,
	GAME_OPTION,
	GAME_WIN,
	GAME_LOSE,
	GAME_DRAW,
	GAME_DEMO,
	GAME_DES
};
MODE mode = GAME_TITLE;

//////////////////////////////
//　　　                    //
//　　　　　関数部          //
//                          //
//////////////////////////////

//ロード関数
void Load(){

	//画像ロード部
	LoadDivGraph("media\\osero.png", 3 , 3 , 1 , 32 ,32 ,koma);

	return;
}

//初期化関数
int init(){

	//object型に変換
	for (int i=0;i<H;i++){
		for(int j=0;j<W;j++){

			switch(t_stage[i][j]){
				case 0: stage[i][j] = STAGE;
					break;
				case 1: stage[i][j] = KURO;
					break;
				case 2: stage[i][j] = SIRO;
					break;
			}
		}
	}


	return 1;
}

//表示する関数
int draw(){
	int x = init_x,y = init_y;

	//背景表示
	DrawBox(0,0,640,480,Haikei,TRUE);
	for (int i=0;i<H;i++){
		x = init_x;
		for(int j=0;j<W;j++){

			switch(stage[i][j]){
			case STAGE:
				DrawGraph(x,y,koma[0],TRUE);
				break;
			case KURO:
				DrawGraph(x,y,koma[1],TRUE);
				break;
			case SIRO:
				DrawGraph(x,y,koma[2],TRUE);
				break;
			}
			x +=Mas;
		}
		y +=Mas;
	}

	return 1;
}

//ターンを変更する関数
void TurnChanege(TURN* turnBuf){

	if(*turnBuf==BLACK){
		*turnBuf=WHITE;
	}else{
		*turnBuf=BLACK;
	}

	return;
}

//サーチ関数（同時に裏返しもしてくれる）
int search(int KomaY, int KomaX, int PulasX, int PulasY, TURN turn){
	
	object check,myturn,enumturn;

	int y,x,i=0;
	y = KomaY;
	x = KomaX;
	switch(turn){

		case BLACK:
			myturn = KURO;
			enumturn = SIRO;
			break;
		case WHITE:
			myturn = SIRO;
			enumturn = KURO;
			break;
	}
	    //ここからサーチする
	do{
		// メッセージループに代わる処理をする
		if( ProcessMessage() == -1 )
		{
			return -1;		// エラーが起きたらループを抜ける

		}
		i++;
		KomaX += PulasX;
		KomaY += PulasY;
		if(0 > KomaX ||  0 > KomaY || H <= KomaY || W <= KomaX){

			return 0;
		}

		check	= stage[KomaY][KomaX];

	}while(check == enumturn);
	
	if(i==1){

		return 0;

		//ここから裏返し処理
	}else if(stage[KomaY][KomaX] == myturn){

			for(int j=0; j!=i; j++){

				if(0 > KomaX ||  0 > KomaY || H <= KomaY || W <= KomaX){
					return 0;
				}
				
				KomaX -= PulasX;
				KomaY -= PulasY;


				stage[KomaY][KomaX] = myturn;
			}
			return 1;

	}else{

		return 0;
	}

	return -1;
	
}

//コマをサーチする関数（成功＝1、失敗＝0)
//ここは適当です
int SearchMain(int y, int x,TURN turn){

	int ok = 0;
	ok += search(y,x,0,-1,turn);
	ok += search(y,x,0,1,turn);
	ok += search(y,x,1,0,turn);
	ok += search(y,x,-1,0,turn);
	ok += search(y,x,1,1,turn);
	ok += search(y,x,-1,1,turn);
	ok += search(y,x,1,-1,turn);
	ok += search(y,x,-1,-1,turn);
	if(ok > 0){
		return 1;
	}else{
		return 0;
	}


}







//打てる手があるか確かめる関数
int CheckPass(TURN turn ,bool msg){
	
	object check;
	object stage2[H][W];
	int SeCheck,set=0,flag;

	for(int i=0; i<H; i++){
		for(int j=0; j<W; j++){
			check=stage[i][j];
			switch(check){
			case STAGE:

				memcpy(stage2,stage,sizeof(stage));
				SeCheck=SearchMain(i,j,turn);
				if(SeCheck==0){

					memcpy(stage,stage2,sizeof(stage2));

				}else{

					memcpy(stage,stage2,sizeof(stage2));
					return 0;
		
				}
				break;

			case KURO:
			case SIRO:
				break;
			}
		}
	}

	if(msg==TRUE){
	draw();

	flag=MessageBox(
                GetMainWindowHandle(),
                TEXT("パスです") ,
                TEXT("パス") , 
                MB_OK | MB_ICONASTERISK);

        if(flag==IDOK)
			TurnChanege(&turn);
	}

		return 1;
}

//勝敗を決める関数
void CheckClear(){

	int bl=0,wh=0,pass=0;
	object th;
	

	for(int i=0;i<H;i++){
		for(int j=0;j<W;j++){
			th = stage[i][j];

			switch(th){
			case STAGE:
				return;
			case KURO:
				bl++;
				break;
			case SIRO:
				wh++;
				break;
			}
		}
	}
	pass += CheckPass(BLACK,FALSE);
	pass += CheckPass(WHITE,FALSE);

	if(pass==2){
		
		if(bl>wh){
			mode = GAME_WIN;
		}else if(bl==wh){
			mode = GAME_DRAW;
		}else{
			mode = GAME_LOSE;
		}

		return;
	}

}


//勝利関数
void Win(){

	int ini,flag;

	draw();
	  
        flag=MessageBox(
                GetMainWindowHandle(),
                TEXT("あなたが勝利しました！") ,
                TEXT("Your Win!") , 
                MB_OK | MB_ICONASTERISK);

        if(flag==IDOK)
			ini = init();

		if(ini==1){

		mode = GAME_TITLE;
		}
		return;
}

//敗北関数
void Lose(){

	int ini,flag;

	draw();
	  
        flag=MessageBox(
                GetMainWindowHandle(),
                TEXT("あなたは敗北しました・・・"),
                TEXT("Your Lose・・・") , 
                MB_OK | MB_ICONASTERISK);

        if(flag==IDOK)
			ini = init();

		if(ini==1){

		mode = GAME_TITLE;
		}
		return;
}

//引き分け
void Draw(){

	int ini,flag;

	draw();
	  
        flag=MessageBox(
                GetMainWindowHandle() ,
                TEXT("引き分けです") ,
                TEXT("DRAW") , 
                MB_OK | MB_ICONASTERISK);

        if(flag==IDOK)
			ini = init();

		if(ini==1){

		mode = GAME_TITLE;
		}
		return;
}

//比較関数
int comp( const void *c1, const void *c2 )
{
  ai test1 = *(ai*)c1;
  ai test2 = *(ai*)c2;

  int tmp1 = test1.val;
  int tmp2 = test2.val;

  return tmp1 - tmp2;
}

//評価値計算関数
void AI(int set, int x,int y){

	ai_val[set].x = x;
	ai_val[set].y = y;

	for(int i=0;i<H;i++){
		for(int j=0;j<W;j++){

			if(turn==WHITE){
			ai_val[set].val += val[i][j] * stage[i][j];
			}else{
			ai_val[set].val += -1*  (val[i][j] * stage[i][j]);
			}

		}
	}
	return;
}

//敵の処理（AIはここから）
void EnumAI(){

	object check;
	object stage2[H][W];
	int SeCheck,set=0,pas;
	
	pas = CheckPass(turn,TRUE);//打てる手があるか確かめる
	if(pas==1){
		
		TurnChanege(&turn);
		return;

	}

	for(int i=0; i<H; i++){
		for(int j=0; j<W; j++){
			check=stage[i][j];
			switch(check){
			case STAGE:

				memcpy(stage2,stage,sizeof(stage));
				SeCheck=SearchMain(i,j,turn);
				if(SeCheck==0){

					memcpy(stage,stage2,sizeof(stage2));

				}else{
					AI(set,j,i);
					memcpy(stage,stage2,sizeof(stage2));
					set++;
		
				}
				break;

			case KURO:
			case SIRO:
				break;
			}
		}
	}
	qsort(ai_val,set,sizeof(ai),comp);
	SearchMain(ai_val[0].y,ai_val[0].x,turn);
	memset(ai_val,0,sizeof(ai_val));
	WaitTimer(1000);
	TurnChanege(&turn);
	return;
}

//プレイヤー関数
void Player(){

	int MouseX,MouseY,x,y,Sok;
	
	CheckPass(turn,TRUE);//打てる手があるか確かめる

		if( ( GetMouseInput() & MOUSE_INPUT_LEFT ) != 0 ){
			GetMousePoint(&MouseX,&MouseY);
			x = MouseX / Mas;
			y = MouseY / Mas;
			x -= init_x / Mas;
			y -= init_y / Mas;

			if(0 <= x && x < W && 0 <= y && y < H){
				if(stage[y][x] != STAGE){

					return;

				}else{
					Sok = SearchMain(y,x,turn);

					if(Sok == 1){
						TurnChanege(&turn);//ターン終了
					}else{
						return;
					}
				
				}

				return;


			}
		}
	return;

}


//タイトル関数
void Title(){

	SetFontSize(30);
	DrawString(35,100,"最弱オセロ！",wh);

	SetFontSize(22);
	DrawString(5,150,"Zキーを押してください",bl);

	if(Key[KEY_INPUT_Z]==1){
		mode = GAME_MAIN;
	}
	return;

}

//ゲームメイン処理
void MyMain(){


	if(Key[KEY_INPUT_X]){
		
		int flag,ini;
        flag=MessageBox(
                GetMainWindowHandle(),
                TEXT("やり直しますか？") ,
                TEXT("注意") , 
                MB_YESNO | MB_ICONQUESTION );

        if(flag==IDYES){
			ini = init();

			if(ini==1)
				return;
		}
	}


	switch(turn){
	case BLACK:
		Player();
		draw();
		break;
	case WHITE:
		EnumAI();
		draw();
		break;
	}
	return;
}

//////////////////////////////
//                          //
//        メイン関数        //
//                        　// 
//////////////////////////////

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE 
	hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){
        if( SetGraphMode(256,256,32)!=DX_CHANGESCREEN_OK ||SetMainWindowText("最弱オセロ！")== -1 || ChangeWindowMode(TRUE) != DX_CHANGESCREEN_OK || DxLib_Init() == -1 ) return -1; //初期化処理

		Load();
		init();

		SetDrawScreen( DX_SCREEN_BACK );        //裏画面に設定

		//ゲームループ
		while(!ProcessMessage() && !ClearDrawScreen() && !GetHitKeyStateAll( Key )&& Key[KEY_INPUT_ESCAPE] != 1){
              //↑ﾒｯｾｰｼﾞ処理         ↑画面をｸﾘｱ          ↑ｷｰﾎﾞｰﾄﾞ入力状態取得       ↑ESCが押されていない

			switch(mode){
			case GAME_TITLE://タイトル処理
				Title();
				break;
			case GAME_MAIN://ゲーム処理
				MyMain();
				CheckClear();//クリアしてるかどうか確かめる
				break;
			case GAME_OPTION:
				break;
			case GAME_WIN://勝利処理
				Win();
				break;
			case GAME_LOSE://敗北処理
				Lose();
				break;
			case GAME_DRAW:
				Draw();
				break;
			case GAME_DES://終了処理
				break;
			}

			ScreenFlip();//裏画面を表画面に反映
		}
        DxLib_End();
        return 0;
}
