c语言翻转棋ai算法,黑白棋游戏(也叫翻转棋)(AI 版)

黑白棋(也叫翻转棋)的棋盘是一个有8*8方格的棋盘。下棋时将棋下在空格中间,而不是像围棋一样下在交叉点上。开始时在棋盘正中有两白两黑四个棋子交叉放置,黑棋总是先下子。

下子的方法:把自己颜色的棋子放在棋盘的空格上,而当自己放下的棋子在横、竖、斜八个方向内有一个自己的棋子,则被夹在中间的全部翻转会成为自己的棋子。并且,只有在可以翻转棋子的地方才可以下子。

引用了QQ游戏黑白棋的图片。

游戏运行截图如下:

a4c26d1e5885305701be709a3d33442f.png

游戏中使用了大量图片、音乐、资源文件,<

href="http://www.easyx.cn/Files/samples/201203/BlackWhiteChessAI.zip"

style="text-decoration: none; color: rgb(0, 0,

127);">点这里下载该游戏的完整 VC 项目包>。

游戏代码如下(相关图片资源请下载完整 VC 项目包):

///

// 程序名称:黑白棋AI版

// 编译环境:Visual C++ 2010/6.0,EasyX_v20120304(beta)

// 程序编写:自然向日葵 [email protected]

// 最后更新:2012-3-24

//

//说明:人机对战版

#include // EasyX_2011惊蛰版

#include

#include

#pragma comment(lib, "Winmm.lib")

#define T(c) ((c == 'B') ? 'W' : 'B')

using namespace std;

const int difficult = 6;// 难度

const int move[8][2] = {{-1, 0}, {1, 0}, {0, -1}, {0, 1},

{-1, -1}, {1, -1}, {1, 1}, {-1, 1}};

// 八个方向扩展

char map[8][8];// 棋盘

IMAGE img[5];// 保存图片

int black, white;// 双方的棋子数

int X, Y;// 白棋的下子点

void load(void);// 加载素材

void print(void);// 画棋盘

void draw(int, int, char);// 下当前子

int judge(int, int, char);// 判断当前是否可以落下

bool baidu(char);// 判断是否有棋可吃

bool quit(char);// 判断是否有棋存活

bool ask(void);// 弹出对话框

int D(char, int);// 动态规划

void play(void);// 游戏过程

void load(void)// 加载素材

{

// 加载图片

loadimage(&img[0], "图片\\空位.bmp");

loadimage(&img[1], "图片\\黑子.bmp");

loadimage(&img[2], "图片\\白子.bmp");

loadimage(&img[3], "图片\\黑子1.bmp");

loadimage(&img[4], "图片\\白子1.bmp");

// 加载音乐

mciSendString("open 音乐\\背景音乐.wma", NULL, 0, NULL);

mciSendString("open 音乐\\和局.wma", NULL, 0, NULL);

mciSendString("open 音乐\\胜利.wma", NULL, 0, NULL);

mciSendString("open 音乐\\失败.wma", NULL, 0, NULL);

mciSendString("open 音乐\\下子.wma", NULL, 0, NULL);

// 初始化棋盘

initgraph(340, 340);

IMAGE qipan;

loadimage(&qipan, "图片\\棋盘.bmp");

putimage(0, 0, &qipan);

setorigin(26, 26);

SetWindowText(GetHWnd(), "黑白棋AI版");

}

void print(void)// 画棋盘

{

int x, y;

black = white = 0;

for(x = 0; x < 8; x++)

for(y = 0; y < 8; y++)

switch(map[x][y])

{

case 0:

putimage(37 * y, 37 * x, &img[0]);

break;

case 'B':

putimage(37 * y, 37 * x, &img[1]);

black++;

break;

case 'W':

putimage(37 * y, 37 * x, &img[2]);

white++;

break;

}

}

void draw(int x, int y, char a)// 下当前子

{

char b = T(a);// 敌方子

int i, x1, y1, x2, y2;

bool sign;

for (i = 0; i < 8; i++)

{

sign = false;

x1 = x + move[i][0];

y1 = y + move[i][1];

while (0 <= x1 && x1 < 8 && 0 <= y1 && y1 < 8 && map[x1][y1])

{

if(map[x1][y1] == b)

sign = true;

else

{

if(sign)

{

x1 -= move[i][0];

y1 -= move[i][1];

x2 = x + move[i][0];

y2 = y + move[i][1];

while (((x <= x2 && x2 <= x1) || (x1 <= x2 && x2 <= x)) && ((y <= y2 && y2 <= y1) || (y1 <= y2 && y2 <= y)))

{

map[x2][y2] = a;

x2 += move[i][0];

y2 += move[i][1];

}

}

break;

}

x1 += move[i][0];

y1 += move[i][1];

}

}

map[x][y] = a;

}

int judge(int x, int y, char a)// 判断当前是否可以落下,同draw函数

{

if(map[x][y])// 如果当前不是空的返回0值

return 0;

char b = T(a);

int i, x1, y1;

int n = 0, sign;

for (i = 0; i < 8; i++)

{

sign = 0;

x1 = x + move[i][0];

y1 = y + move[i][1];

while (0 <= x1 && x1 < 8 && 0 <= y1 && y1 < 8 && map[x1][y1])

{

if(map[x1][y1] == b)

sign++;

else

{

n += sign;

break;

}

x1 += move[i][0];

y1 += move[i][1];

}

}

return n;// 返回可吃棋数

}

bool baidu(char c)// 判断是否有棋可吃

{

int x, y;

for(x = 0; x < 8; x++)

for(y = 0; y < 8; y++)

if(judge(x, y, c))

return true;

return false;

}

bool quit(char c)// 判断是否有棋存活

{

int x, y;

bool b = false, w = false;

for(x = 0; x < 8; x++)

for(y = 0; y < 8; y++)

{

if(map[x][y] == c)

return false;

}

return true;

}

bool ask(void)// 弹出对话框

{

HWND wnd = GetHWnd();

int key;

char str[50];

ostrstream strout(str, 50);

strout <

if (black == white)

strout <

else if(black > white)

strout <

else

strout <

strout <

if(black == white)

key = MessageBox(wnd, str, "和局", MB_YESNO | MB_ICONQUESTION);

else if(black > white)

key = MessageBox(wnd, str, "黑胜", MB_YESNO | MB_ICONQUESTION);

else

key = MessageBox(wnd, str, "白胜", MB_YESNO | MB_ICONQUESTION);

if(key == IDYES)

return true;

else

return false;

}

int D(char c, int step)

{

// 判断是否结束递归

if (step > difficult)// 约束步数之内

return 0;

if (!baidu(c))

{

if (baidu(T(c)))

return -D(T(c), step);

else

return 0;

}

int i, j, max = 0, temp, x, y;

bool ans = false;

// 建立临时数组

char **t = new char *[8];

for (i = 0; i < 8; i++)

t[i] = new char [8];

for (i = 0; i < 8; i++)

for (j = 0; j < 8; j++)

t[i][j] = map[i][j];

// 搜索解法

for (i = 0; i < 8; i++)

for (j = 0; j < 8; j++)

if (temp = judge(i, j, c))

{

draw(i, j, c);

temp -= D(T(c), step + 1);

if (temp > max || !ans)

{

max = temp;

x = i;

y = j;

ans = true;

}

for (int k = 0; k < 8; k++)

for (int l = 0; l < 8; l++)

map[k][l] = t[k][l];

}

// 撤销空间

for (i = 0; i < 8; i++)

delete [] t[i];

delete [] t;

// 如果是第一步则标识白棋下子点

if (step == 1)

{

X = x;

Y = y;

}

return max;// 返会最优解

}

void play(void)// 游戏过程

{

MOUSEMSG m;

int x, y;

// 初始化棋子

for(x = 0; x < 8; x++)

for(y = 0; y < 8; y++)

map[x][y] = 0;

map[3][4] = map[4][3] = 'B';

map[3][3] = map[4][4] = 'W';

// 开始游戏

print();

mciSendString("play 音乐\\背景音乐.wma from 0 repeat", NULL, 0, NULL);

do

{

if (baidu('B'))// 如果玩家有下子位置

{

A:

while(true)

{

m = GetMouseMsg();// 获取鼠标消息

if(m.uMsg == WM_LBUTTONDOWN && m.x - 26 < 37 * 8 && m.y - 26 < 37 * 8)

// 如果左键点击

break;

}

x = (m.y - 26) / 37;

y = (m.x - 26) / 37;

if(judge(x, y, 'B'))// 如果当前位置有效

{

draw(x, y, 'B');// 下子

mciSendString("play 音乐\\下子.wma from 0", NULL, 0, NULL);

print();

putimage(37 * y, 37 * x, &img[3]);// 标识下子点

}

else

goto A;

if (quit('W'))// 计算机是否失败

break;

}

if (baidu('W'))// 如果计算机有下子位置

{

clock_t start;

start = clock();

D('W', 1);// 搜索解法

while (clock() - start < CLOCKS_PER_SEC);

draw(X, Y, 'W');

print();

mciSendString("play 音乐\\下子.wma from 0", NULL, 0, NULL);

putimage(37 * Y, 37 * X, &img[4]);// 标识下子点

if (quit('B'))// 玩家是否失败

break;

}

}while (baidu('B') || baidu ('W'));

// 播放庆祝音乐

mciSendString("stop 音乐\\背景音乐.wma", NULL, 0, NULL);

if (black > white)

mciSendString("play 音乐\\胜利.wma from 0", NULL, 0, NULL);

else if (black < white)

mciSendString("play 音乐\\失败.wma from 0", NULL, 0, NULL);

else

mciSendString("play 音乐\\和局.wma from 0", NULL, 0, NULL);

}

// 主函数

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)

{

load();

do

{

play();

} while(ask());

// 关闭音乐

mciSendString("close 音乐\\背景音乐.wma", NULL, 0, NULL);

mciSendString("close 音乐\\和局.wma", NULL, 0, NULL);

mciSendString("close 音乐\\胜利.wma", NULL, 0, NULL);

mciSendString("close 音乐\\失败.wma", NULL, 0, NULL);

mciSendString("close 音乐\\下子.wma", NULL, 0, NULL);

closegraph();

return 0;

}

你可能感兴趣的:(c语言翻转棋ai算法)