求!!c语言黑白棋提示功能怎么写,就是设置一个提示按钮,点一下系统帮你下下一步
原体代码如下
```c
#include // EasyX
#include
#include
#include
#pragma comment(lib, "Winmm.lib")
#define T(c) ((c == 'B') ? 'W' : 'B') //定义一个标识符来表示一个常量
using namespace std;
/*******************************定义全局变量*****************************/
const int difficult = 3; // 难度
// 八个方向扩展
const int HImove[8][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1},
{-1, -1}, {1, -1}, {1, 1}, {-1, 1} };
char map[8][8]; // 棋盘
IMAGE img[6]; // 保存图片
int black, white; // 双方的棋子数
int X, Y; // 白棋的下子点
/**********************************函数声明*****************************/
void load(); // 加载素材
void print(); // 画棋盘
void draw(int x, int y, char a); // 下当前子
int judge(int x, int y, char a); // 判断当前是否可以落下
bool check(char a); // 判断是否有棋可吃
bool quit(char a); // 判断是否有棋存活
bool ask(); // 弹出对话框
int D(char a, int); // 动态规划
void play(); // 游戏过程
/**********************************定义函数*****************************/
void load() // 加载素材
{
// 加载图片
loadimage(&img[0], "图片\\空位.bmp");
loadimage(&img[1], "图片\\de.jpg");
loadimage(&img[2], "图片\\la.jpg");
loadimage(&img[3], "图片\\de1.jpg");
loadimage(&img[4], "图片\\la1.jpg");
loadimage(&img[5], "图片\\提示.jpg");
// 加载音乐
mciSendString("open 音乐\\背景音乐.mp3", 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(380, 340);//初始化窗体
IMAGE qipan;
loadimage(&qipan, "图片\\背景.jpg");
putimage(0, 0, &qipan);
setorigin(26, 26);//图片插入原点
SetWindowText(GetHWnd(), "德克萨斯与拉普兰德");
}
void print() // 画棋盘
{
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]);//因为图片的像素是37*37,所以宽度也是37的倍数
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 + HImove[i][0];
y1 = y + HImove[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 -= HImove[i][0];
y1 -= HImove[i][1];
x2 = x + HImove[i][0];
y2 = y + HImove[i][1];
while (((x <= x2 && x2 <= x1) || (x1 <= x2 && x2 <= x)) && ((y <= y2 && y2 <= y1) || (y1 <= y2 && y2 <= y)))
{
map[x2][y2] = a;
x2 += HImove[i][0];
y2 += HImove[i][1];
}
}
break;
}
x1 += HImove[i][0];
y1 += HImove[i][1];
}
}
map[x][y] = a;
}
// 判断当前下子可吃敌方棋子数量
int judge(int x, int y, char a)
{
if (map[x][y])// 如果当前不是空的返回0值
return 0;
char b = T(a);//对方棋子
int i, x1, y1;
int sum; //单方向可吃棋子数量
int count=0; // 总可吃棋子数
for (i = 0; i < 8; i++)
{
sum = 0;//计算当前方向对方棋子的数量
x1 = x + HImove[i][0];
y1 = y + HImove[i][1];
while (0 <= x1 && x1 < 8 && 0 <= y1 && y1 < 8 && map[x1][y1])
{
if (map[x1][y1] == b)
sum++;
else
{
count += sum;
break;
}
x1 += HImove[i][0];
y1 += HImove[i][1];
}
}
return count; // 返回可吃棋数
}
// 判断是否有棋可吃
bool check(char c)
{
int x, y;
for (x = 0; x < 8; x++)
for (y = 0; y < 8; y++)
if (judge(x, y, c)>0)
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 << "黑:" << black << " 白:" << white << endl;
if (black == white)
strout << "世界和平";
else if (black > white)
strout << "不堪一击。";
else
strout << "德克萨斯做的到吗!";
strout << "\n再来一局吗?" << ends;
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 (!check(c))
{
if (check(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 音乐\\背景音乐.mp3 from 0 repeat", NULL, 0, NULL);
do
{
if (check('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 (check('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 (check('B') || check('W'));
// 播放庆祝音乐
mciSendString("stop 音乐\\背景音乐.mp3", 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 main()
{
load();
do
{
play();
} while (ask());
// 关闭音乐
mciSendString("close 音乐\\背景音乐.mp3", 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);
_getch();
closegraph();
return 0;
}
```
为了实现这个功能,可以使用极大极小值算法(alpha-beta pruning算法)来评估棋盘上每一步的最优结果,根据评估结果来决定下一步最优的走法。极大极小值算法是一种类似于推理的搜索算法,大方向上是基于搜索树来寻找最优走法,帮助黑白棋系统判断当前哪一步最具有优势以及对局面最有利。
以下是一个完整的黑白棋游戏的C++代码,其中包含了提示功能的实现。这个程序使用EasyX图形库和Windows API,需要在Windows操作系统下运行。
#include <graphics.h> // EasyX图形库
#include <strstream>
#include <ctime>
#include <conio.h>
#include <windows.h>
#include <mmsystem.h>
#pragma comment(lib, "Winmm.lib")
#define T(c) ((c == 'B') ? 'W' : 'B') //定义一个标识符来表示一个常量
using namespace std;
/*******************************定义全局变量*****************************/
const int difficult = 3; // 难度
// 八个方向扩展
const int HImove[8][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1},
{-1, -1}, {1, -1}, {1, 1}, {-1, 1} };
char map[8][8]; // 棋盘
IMAGE img[6]; // 保存图片
int black, white; // 双方的棋子数
int X, Y; // 白棋的下子点
/**********************************函数声明*****************************/
void load(); // 加载素材
void print(); // 画棋盘
void draw(int x, int y, char a); // 下当前子
int judge(int x, int y, char a); // 判断当前是否可以落下
bool check(char a); // 判断是否有棋可吃
bool quit(char a); // 判断是否有棋存活
bool ask(); // 弹出对话框
int D(char a, int); // 动态规划
void play(); // 游戏过程
void tip(); // 提示功能
/**********************************定义函数*****************************/
void load() // 加载素材
{
// 加载图片
loadimage(&img[0], "images\\empty.jpg");
loadimage(&img[1], "images\\black.jpg");
loadimage(&img[2], "images\\white.jpg");
loadimage(&img[3], "images\\black_1.jpg");
loadimage(&img[4], "images\\white_1.jpg");
loadimage(&img[5], "images\\tip.jpg");
// 加载音乐
mciSendString("open audios\\bgm.mp3", NULL, 0, NULL);
mciSendString("open audios\\draw.mp3", NULL, 0, NULL);
mciSendString("open audios\\drawn.mp3", NULL, 0, NULL);
mciSendString("open audios\\equal.mp3", NULL, 0, NULL);
mciSendString("open audios\\win.mp3", NULL, 0, NULL);
mciSendString("open audios\\lose.mp3", NULL, 0, NULL);
// 初始化棋盘
initgraph(380, 340);
IMAGE qipan;
loadimage(&qipan, "images\\bg.jpg");
putimage(0, 0, &qipan);
setorigin(26, 26);
SetWindowText(GetHWnd(), "黑白棋");