2021-06-11

#include <stdio.h>
#include <tchar.h>
#include <stdlib.h>//实现数值转换,内存分配
#include <graphics.h>//图形库头文件
#include <conio.h>//getch()函数需要
#pragma comment(lib,“winmm.lib”) //表示链接winmm.lib这个多媒体库;为了正常使用PlaySound函数
#undef UNICODE

void initgame();
void begingame();
void renjibegingame();
void gameover();
int panduan(COLORREF, int, int);
//void arrayqizhi();
//void rjarrayqizhi();
//void rrarrayqizhi();
int shpanduan(COLORREF, int, int, int, int);
int scorepanduan(int, int);

//设置光标结构体类型
typedef struct//方便下面声明变量
{
int x;
int y;
}post;//post为类型名

//设置人机结构体类型
typedef struct
{
int x;
int y;
int score;
}alph;

//设置光标
post xy;

//用一个数的奇偶性来判断产生棋子的黑白,进行棋子的变换 偶数表示黑棋 当color == 225即棋子全部布满棋局的时候表明平局
int color = 0;

//用一个开关来控制游戏的背景音乐; 奇数表示开
int bgm = 1;

//为了防止出现随意悔棋的情况 所以规定每个人只能悔当前下的棋 所以定义一个光标记录将要悔棋的地点
post huixy;

//人悔了一步棋,机器也要退回上一个的位置
alph rjhuixy;

//定义一个稍微大一点的结构体数组来存放每一步棋子顺序(人人)
post array[1000] = { 0 };

//定义一个稍微大一点的结构体数组来存放每一步棋子顺序(人机)
alph rjarray[1000] = { 0 };

int main()
{
initgame();
begingame();
gameover();
system(“pause”);//暂停,等待用户操作,防止程序闪退
return 0;
}

//游戏初始化
void initgame()
{
initgraph(500, 750);//初始化图形系统 设置窗口大小

B:;//定义一个标签B,后面通过goto语句使用
//加载图片
IMAGE backgrand;
loadimage(&backgrand, L"back.jpg", 500, 750);//装载背景图
putimage(0, 0, &backgrand);
//设置背景颜色
setbkcolor(RGB(193, 203, 204)); //目的是为了让显示的文字看起来没有边框
//设置五张图片来显示出颜色动态效果
IMAGE ch1, ch2, ch3, ch4;
loadimage(&ch1, L"(1).jpg", 500, 750);
loadimage(&ch2, L"(2).jpg", 500, 750);
loadimage(&ch3, L"(3).jpg", 500, 750);
loadimage(&ch4, L"(4).jpg", 500, 750);

//游戏界面选择
MOUSEMSG m;		// 定义鼠标消息   
while (true)
{
	m = GetMouseMsg();// 获取一条鼠标消息
	FlushMouseMsgBuffer();//清除上一下鼠标缓存
	putimage(0, 0, &backgrand);//避免黑屏
	switch (m.uMsg)
	{
	case WM_MOUSEMOVE:
		if (m.x >= 150 && m.x <= 334 && m.y >= 350 && m.y <= 400.27)  //开始游戏
		{
			putimage(0, 0, &ch1);
		}
		if (m.x >= 150 && m.x <= 334 && m.y >= 410 && m.y <= 460.27) // 进入人机挑战
		{
			putimage(0, 0, &ch2);
		}
		if (m.x >= 150 && m.x <= 334 && m.y >=470 && m.y <= 522.27)  //游戏说明
		{
			putimage(0, 0, &ch3);
		}
		if (m.x >= 150 && m.x <= 334 && m.y >= 530 && m.y <=580.27) //  退出游戏
		{
			putimage(0, 0, &ch4);
		}
		break;

	case WM_LBUTTONDOWN:      //长是190  宽是40
		if (m.x >= 150 && m.x <= 334 && m.y >= 350 && m.y <= 400.27)  // 开始游戏
		{
			goto A;
		}
		if (m.x >= 150 && m.x <= 334 && m.y >= 410 && m.y <= 460.27) // 进入人机挑战
		{
			renjibegingame();
		}
		if (m.x >= 150 && m.x <= 334 && m.y >= 470 && m.y <= 522.27) //  游戏说明 
		{
			IMAGE explain;
			loadimage(&explain, L"游戏说明.jpg", 500, 750);
			putimage(0, 0, &explain);
			system("pause");
			goto B;
		}
		if (m.x >= 150 && m.x <= 334 && m.y >= 530 && m.y <= 580.27)  //退出游戏
		{
			//先释放资源
			closegraph();
			exit(0);
		}
	}
}

A:;
}

//人和人进行游戏对战
void begingame()
{
//加载背景音乐
mciSendString(L"open BGM1.mp3 alias bg", NULL, 0, NULL);
mciSendString(L"play bg repeat", NULL, 0, NULL);
C://C标签背景音乐 显示背景音乐开关
IMAGE BGM;
loadimage(&BGM, L"780.jpg", 500, 750);//装载音乐播放时的背景图片
putimage(0, 0, &BGM);

//棋盘加载
setlinecolor(BLACK);//设置画线颜色为黑色
setlinestyle(PS_SOLID);//设置画线样式为实线
setfillcolor(RGB(248, 203, 18));//设置填充颜色
fillrectangle(25, 325, 425, 725); //计算而来的   棋盘外围的矩形

for (int i = 1; i < 15; i++)
{
	for (int j = 1; j < 15; j++)
	{
		rectangle(25 + j * 25, 325 + i * 25, 50 + j * 25, 350 + i * 25);  //棋盘左上是50 350

	}
}
//黑子先手  游戏开始光标默认在正中间
//绘制下棋时的预览光标
xy.x = 225;
xy.y = 525;// 这个坐标是推出来的 就是最中心的坐标
setlinecolor(RED);
setlinestyle(PS_DOT);
rectangle(xy.x - 15, xy.y - 15, xy.x + 15, xy.y + 15);

post master[225];  //定义一个有225个元素的结构体数组来代表光标的所有分布的可能性 
//填充电脑位置     //从棋盘左上是50 350开始
int index = 0; //定义结构体数组的下标
for (int i = 1; i <= 15; i++)
{
	for (int j = 1; j <= 15; j++)//25 + j * 25, 325 + i * 25,  //棋盘左上是50 350
	{
		master[index].x = 25 + j * 25;
		master[index].y = 325 + i * 25;
		index++;
	}
}
//清除上一下鼠标缓存
FlushMouseMsgBuffer();
MOUSEMSG m;		// 定义鼠标消息
while (true)
{
	//按下esc返回游戏界面
	if (_kbhit())//键盘敲击事件
	{
		char key;
		key = _getch();//函数自动读取某个字符
		switch (key)
		{
		case 27://27 为esc的ASCII码
		{
			//重置color
			color = 0;
			//音乐暂停
			mciSendString(L"close bg", NULL, 0, NULL);   //把pause改成close可以消除按下esc会页面在点击开始游戏直接出来棋子的bug 
			main();
		}
		}
	}
	//清除上一下鼠标缓存
	FlushMouseMsgBuffer();  //让光标更加灵活

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

	//是否暂停音乐
	if (bgm % 2 == 0)//偶数表示关
	{
		settextcolor(RGB(0, 0, 0));
		settextstyle(20, 0, L"楷体");
		outtextxy(25, 730, L"背景音乐:OFF");
		mciSendString(L"pause bg", NULL, 0, NULL);
	}
	else//否则奇数表示开
	{
		settextcolor(RGB(0, 0, 0));
		settextstyle(20, 0, L"楷体");
		outtextxy(25, 730, L"背景音乐:O N");
		mciSendString(L"resume bg", NULL, 0, NULL);
	}

	//显示提示黑子先手或者显示提示当前将要下的棋子颜色
	if (color == 0)
	{
		settextcolor(RGB(0, 0, 0));
		settextstyle(20, 0, L"楷体");
		outtextxy(30, 300, L"黑子先手!");
	}
	else if (color % 2 != 0)
	{
		settextcolor(RGB(0, 0, 0));
		settextstyle(20, 0, L"楷体");
		outtextxy(30, 300, L"轮到棋子:");//在指定位置20 300处输出字符串
		//设置提示落子颜色
		setfillcolor(WHITE);//填充色
		setlinecolor(WHITE);//画线色
		fillcircle(130, 310, 10);//有边框的填充圆
	}
	else
	{
		settextcolor(RGB(0, 0, 0));
		settextstyle(20, 0, L"楷体");
		outtextxy(30, 300, L"轮到棋子:");
		//设置提示落子颜色
		setfillcolor(BLACK);//填充色
		setlinecolor(BLACK);//画线色
		fillcircle(130, 310, 10);//有边框的填充圆
	}

	switch (m.uMsg)
	{
	case WM_MOUSEMOVE://鼠标移动
		for (int i = 0; i < 225; i++)
		{
			if ((m.x >= master[i].x - 10 && m.x <= master[i].x + 10) && (m.y >= master[i].y - 10 && m.y <= master[i].y + 10))
				//鼠标的移动显示控制   用一个小画线框表示当前鼠标所在区域,即将落下棋子的位置
			{
				setlinecolor(RGB(248, 203, 18));
				rectangle(xy.x - 15, xy.y - 15, xy.x + 15, xy.y + 15);
				xy.x = master[i].x;
				xy.y = master[i].y;
				setlinecolor(RED);
				setlinestyle(PS_DOT);
				rectangle(xy.x - 15, xy.y - 15, xy.x + 15, xy.y + 15);
			}
		}
		break;
	case WM_MBUTTONDOWN://鼠标中键按下
		if (m.mkShift)
		{
			bgm++;        // 如果按下中键同时按下shift就决定音乐是否暂停(先按住shift在按住鼠标中键)
			Sleep(100);
			break;
		}
		if (m.mkCtrl)
		{
			//如果按下中键同时按下ctrl就重新开始游戏
			color = 0;  //重置
			IMAGE backgrand;
			loadimage(&backgrand, L"back.jpg", 500, 750);
			putimage(0, 0, &backgrand);  //重置画面
			goto C;//跳回C标签重新开始游戏
		}
		exit(0);   //设置强制退出游戏功能

	case WM_LBUTTONUP://鼠标左键弹起
		//不可以重复下棋  通过getpixel这个函数来实现  检索指定坐标点的颜色值,如果检索到白和黑那么该指定坐标点无法再下棋
		if (getpixel(xy.x - 3, xy.y - 3) == RGB(0, 0, 0) || getpixel(xy.x - 3, xy.y - 3) == RGB(255, 255, 255))
		{
			break;
		}
		if (color % 2 == 0)
		{
			array[color] = xy;//把下的棋的顺序保存在array数组里面
			setfillcolor(BLACK);
			setlinecolor(BLACK);
			fillcircle(xy.x, xy.y, 10);
			PlaySound(L"104.wav", NULL, SND_FILENAME | SND_ASYNC);//每落下一颗棋子播放此音乐(棋子落下音效)
			COLORREF hei = getpixel(xy.x - 3, xy.y - 3);
			//胜负判断
			int a = panduan(hei, xy.x, xy.y);
			if (a == 1)
			{
				settextcolor(RGB(0, 0, 0));
				settextstyle(30, 0, L"楷体");
				setbkmode(TRANSPARENT);
				outtextxy(105, 200, L"恭喜黑棋获胜!");
				outtextxy(65, 170, L"(请按任意键继续游戏)");
				char str[30];
				sprintf_s(str, "大战了%d回合!", color / 2 + 1);
				outtextxy(105, 230, _T("str"));
				PlaySound(L"ying.wav", NULL, SND_FILENAME | SND_ASYNC);

				//显示棋子顺序
				//arrayqizhi();

				//重置color
				color = 0;
				system("pause");
				goto C;
			}
			//加入平局的判断
			if (a == 0 && color == 224)   //因为color最大值是224
			{
				settextcolor(RGB(0, 0, 0));
				settextstyle(30, 0, L"宋体");
				setbkmode(TRANSPARENT);
				outtextxy(250, 200, L"平局!");
				outtextxy(65, 170, L"(请按任意键继续游戏)");
				PlaySound(L"ying.wav", NULL, SND_FILENAME | SND_ASYNC);
				//arrayqizhi();//显示棋子顺序
				//重置color
				color = 0;
				system("pause");
				goto C;
			}
		}
		else
		{
			//把下的棋的顺序保存在array数组里面
			array[color] = xy;
			setfillcolor(WHITE);
			setlinecolor(WHITE);
			fillcircle(xy.x, xy.y, 10);
			PlaySound(L"104.wav", NULL, SND_FILENAME | SND_ASYNC);

			COLORREF bai = getpixel(xy.x - 3, xy.y - 3);
			//胜负判断
			int b = panduan(bai, xy.x, xy.y);
			if (b == 1)
			{
				settextcolor(RGB(0, 0, 0));
				settextstyle(30, 0, L"楷体");
				setbkmode(TRANSPARENT);
				outtextxy(105, 200, L"恭喜白棋获胜!");
				outtextxy(65, 170, L"(请按任意键继续游戏)");
				char str[30];
				sprintf_s(str, "大战了%d回合!", color / 2 + 1);//将数据格式化输出到字符串     将格式化字符串存到缓冲区,如果格式化字符串过大,则sprintf_s会返回一个空string和设置无效参数句柄为激活。
				outtextxy(105, 230, _T("str"));
				PlaySound(L"ying.wav", NULL, SND_FILENAME | SND_ASYNC);

				显示棋子顺序
				//arrayqizhi();

				//重置color
				color = 0;
				system("pause");
				goto C;
			}
			//加入平局的判断
			if (b == 0 && color == 224)
			{
				settextcolor(RGB(0, 0, 0));
				settextstyle(30, 0,L"宋体");
				setbkmode(TRANSPARENT);
				outtextxy(105, 200, L"平局!");
				outtextxy(65, 170, L"(请按任意键继续游戏)");
				PlaySound(L"ying.wav", NULL, SND_FILENAME | SND_ASYNC);

				显示棋子顺序
				//arrayqizhi();

				//重置color
				color = 0;
				system("pause");
				goto C;
			}
		}

		//把当前下的棋保存在huixy中
		huixy.x = xy.x;
		huixy.y = xy.y;
		color++;
		Sleep(100);
		break;

		//设置悔棋功能
	case WM_RBUTTONDOWN://鼠标右键按下 
		//保证是悔的上一颗的棋
		if (huixy.x == xy.x && huixy.y == xy.y && getpixel(xy.x - 3, xy.y - 3) != RGB(248, 203, 18))
		{
			setfillcolor(RGB(248, 203, 18));
			setlinecolor(RGB(248, 203, 18));
			fillcircle(xy.x, xy.y, 10);
			setlinecolor(BLACK);
			for (int i = 1; i < 15; i++)
			{
				for (int j = 1; j < 15; j++)
				{
					rectangle(25 + j * 25, 325 + i * 25, 50 + j * 25, 350 + i * 25);
				}
			}
			color--;
			break;
		}
	}
	//来一个重新检查  主要是让白棋不存在中心有黑线的情况
	for (int i = 0; i < 255; i++)
	{
		if (getpixel(master[i].x - 3, master[i].y - 3) == RGB(0, 0, 0))
		{
			setfillcolor(RGB(0, 0, 0));
			setlinecolor(RGB(0, 0, 0));
			fillcircle(master[i].x, master[i].y, 10);
		}
		if (getpixel(master[i].x - 3, master[i].y - 3) == RGB(255, 255, 255))
		{
			setfillcolor(RGB(255, 255, 255));
			setlinecolor(RGB(255, 255, 255));
			fillcircle(master[i].x, master[i].y, 10);
		}
	}
}

}

//进行人机游戏对战
void renjibegingame()
{
//加载背景音乐
mciSendString(L"open BGM.mp3 alias bg", NULL, 0, NULL);
mciSendString(L"play bg repeat", NULL, 0, NULL);
C:
//显示背景音乐开关
IMAGE BGM;
loadimage(&BGM,L"780.jpg", 500, 750);
putimage(0, 0, &BGM);

// 棋盘加载 和上面棋盘加载一个道理
setlinecolor(BLACK);
setlinestyle(PS_SOLID);
setfillcolor(RGB(248, 203, 18));
fillrectangle(30, 325, 425, 725); //计算而来
for (int i = 1; i < 15; i++)
{
	for (int j = 1; j < 15; j++)
	{
		rectangle(25 + j * 25, 325 + i * 25, 50 + j * 25, 350 + i * 25);  //棋盘左上是50 350

	}
}

//黑子先手  游戏开始光标默认在正中间
//绘制光标
xy.x = 225;
xy.y = 525;     // 这个坐标是推出来的 就是最中心的坐标
setlinecolor(RED);
setlinestyle(PS_DOT);
rectangle(xy.x - 15, xy.y - 15, xy.x + 15, xy.y + 15);

//初始化人机阿尔法猫
//加载每个点并且把分数搞成0 
alph alphcat[225];
//填充电脑位置     棋盘左上是50 350
int inde = 0; //定义结构体数组的下标
for (int i = 1; i <= 15; i++)
{
	for (int j = 1; j <= 15; j++)
	{
		//25 + j * 25, 325 + i * 25,  //棋盘左上是50 350
		alphcat[inde].x = 25 + j * 25;
		alphcat[inde].y = 325 + i * 25;
		alphcat[inde].score = 0;
		inde++;
	}
}

//定义一个有225个元素的结构体数组来代表光标的所有分布的可能性 
post master[225];
//填充电脑位置     棋盘左上是50 350
int index = 0; //定义结构体数组的下标
for (int i = 1; i <= 15; i++)
{
	for (int j = 1; j <= 15; j++)
	{
		//25 + j * 25, 325 + i * 25,  //棋盘左上是50 350
		master[index].x = 25 + j * 25;
		master[index].y = 325 + i * 25;
		index++;
	}
}

//清除上一下鼠标缓存
FlushMouseMsgBuffer();
MOUSEMSG m;		// 定义鼠标消息
while (true)
{
	//按下esc返回游戏界面
	if (_kbhit())
	{
		char key;
		key = _getch();
		switch (key)
		{
		case 27:
		{
			//重置color
			color = 0;
			//音乐暂停
			mciSendString(L"close bg", NULL, 0, NULL);   //把pause改成close就可以消除按下esc会页面在点击开始游戏直接出来棋子的bug 
			main();
		}
		}
	}
	//清除上一下鼠标缓存
	FlushMouseMsgBuffer();  //让光标更加灵活

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

	//是否暂停音乐
	if (bgm % 2 == 0)
	{
		settextcolor(RGB(0, 0, 0));
		settextstyle(20, 0, L"楷体");
		outtextxy(25, 730, L"背景音乐:OFF");
		mciSendString(L"pause bg", NULL, 0, NULL);
	}
	else
	{
		settextcolor(RGB(0, 0, 0));
		settextstyle(20, 0, L"楷体");
		outtextxy(25, 730, L"背景音乐:O N");
		mciSendString(L"resume bg", NULL, 0, NULL);
	}

	//显示提示黑子先手或者显示提示当前将要下的棋子颜色
	if (color == 0)
	{
		settextcolor(RGB(0, 0, 0));
		settextstyle(20, 0, L"楷体");
		outtextxy(30, 300, L"黑子先手!");
	}
	else if (color % 2 != 0)
	{
		settextcolor(RGB(0, 0, 0));
		settextstyle(20, 0, L"楷体");
		outtextxy(30, 300, L"轮到棋子:");
		//提示落子颜色
		setfillcolor(WHITE);
		setlinecolor(WHITE);
		fillcircle(130, 310, 10);
	}
	else
	{
		settextcolor(RGB(0, 0, 0));
		settextstyle(20, 0, L"楷体");
		outtextxy(30, 300, L"轮到棋子:");
		//提示落子颜色
		setfillcolor(BLACK);
		setlinecolor(BLACK);
		fillcircle(130, 310, 10);
	}
	switch (m.uMsg)
	{
	case WM_MOUSEMOVE:
		for (int i = 0; i < 225; i++)
		{
			if ((m.x >= master[i].x - 10 && m.x <= master[i].x + 10) && (m.y >= master[i].y - 10 && m.y <= master[i].y + 10))
			{
				setlinecolor(RGB(248, 203, 18));
				rectangle(xy.x - 15, xy.y - 15, xy.x + 15, xy.y + 15);
				xy.x = master[i].x;
				xy.y = master[i].y;
				setlinecolor(RED);
				setlinestyle(PS_DOT);
				rectangle(xy.x - 15, xy.y - 15, xy.x + 15, xy.y + 15);
			}
		}
		break;
	case WM_MBUTTONDOWN:
		if (m.mkShift)
		{
			bgm++;        // 如果按下中键同时按下shift就决定音乐是否暂停(先按住shift在按住鼠标中键)
			Sleep(100);
			break;
		}
		if (m.mkCtrl)
		{
			//如果按下中键同时按下ctrl就重新开始游戏
			color = 0;  //重置颜色
			IMAGE backgrand;
			loadimage(&backgrand, L"back.jpg", 500, 750);
			putimage(0, 0, &backgrand);           //重置画面
			goto C;
		}
		exit(0);   //设置强制退出游戏功能
	case WM_LBUTTONUP:
	{
		//不可以重复下棋  通过getpixel这个函数来实现
		if (getpixel(xy.x - 3, xy.y - 3) == RGB(0, 0, 0) || getpixel(xy.x - 3, xy.y - 3) == RGB(255, 255, 255))
		{
			break;
		}
		//把下的棋的顺序保存在array数组里面
		array[color] = xy;

		setfillcolor(BLACK);
		setlinecolor(BLACK);
		fillcircle(xy.x, xy.y, 10);
		PlaySound(L"104.wav", NULL, SND_FILENAME | SND_ASYNC);
		COLORREF hei = getpixel(xy.x - 3, xy.y - 3);
		//胜负判断
		int a = panduan(hei, xy.x, xy.y);
		if (a == 1)
		{
			settextcolor(RGB(0, 0, 0));
			settextstyle(30, 0, L"楷体");
			setbkmode(TRANSPARENT);
			outtextxy(105, 200, L"阿尔法猫:你厉害!");
			outtextxy(65, 170, L"(请按任意键继续游戏)");
			char str[30];
			sprintf_s(str, "大战了%d回合!", color / 2 + 1);
			outtextxy(105, 230, _T("str"));
			PlaySound(L"ying.wav", NULL, SND_FILENAME | SND_ASYNC);

			显示棋子顺序
			//rrarrayqizhi();
			//rjarrayqizhi();

			//重置color
			color = 0;
			system("pause");
			goto C;
		}
		//加入平局的判断
		if (a == 0 && color == 224)   //因为color最大值是224
		{
			settextcolor(RGB(0, 0, 0));
			settextstyle(30, 0, L"宋体");
			outtextxy(80, 200, L"我和你五五开!");
			outtextxy(65, 170, L"(请按任意键继续游戏)");
			PlaySound(L"ying.wav", NULL, SND_FILENAME | SND_ASYNC);

			显示棋子顺序
			//rrarrayqizhi();
			//rjarrayqizhi();

			//重置color
			color = 0;
			system("pause");
			goto C;
		}

		//把当前下的棋保存在huixy中
		huixy.x = xy.x;
		huixy.y = xy.y;
		color++;
		Sleep(100);
	}
	case 1:
	{
		for (int i = 0; i < 225; i++)
		{
			if (RGB(0, 0, 0) != getpixel(alphcat[i].x - 3, alphcat[i].y - 3) && RGB(255, 255, 255) != getpixel(alphcat[i].x - 3, alphcat[i].y - 3)/*当前落棋点没有落棋 (这个点的颜色是背景色)*/)
			{
				alphcat[i].score = scorepanduan(alphcat[i].x, alphcat[i].y);
			}
		}
		//再来选出一个得分最大的,如果得分一样就随机从最大的一个选一个  
		alph alphmax;
		alphmax.score = alphcat[0].score;
		for (int i = 1; i < 225; i++)
		{
			if (alphcat[i].score >= alphmax.score)
			{
				alphmax = alphcat[i];
			}
		}

		// 把下的棋的顺序保存在array数组里面
		rjarray[color] = alphmax;

		//根据这个点画白棋
		setfillcolor(WHITE);
		setlinecolor(WHITE);
		fillcircle(alphmax.x, alphmax.y, 10);
		PlaySound(L"104.wav", NULL, SND_FILENAME | SND_ASYNC);
		for (int i = 0; i < 225; i++)
		{
			alphcat[i].score = 0;
		}
		COLORREF bai = getpixel(alphmax.x - 3, alphmax.y - 3);
		//胜负判断
		int b = panduan(bai, alphmax.x, alphmax.y);
		if (b == 1)
		{
			settextcolor(RGB(0, 0, 0));
			settextstyle(30, 0, L"楷体");
			setbkmode(TRANSPARENT);
			outtextxy(100, 225, L"阿尔法猫:我赢了!");
			outtextxy(65, 195, L"(请按任意键继续游戏)");
			char str[30];
			sprintf_s(str, "大战了%d回合!", color / 2 + 1);
			outtextxy(105, 255, _T("str"));
			PlaySound(L"ying.wav", NULL, SND_FILENAME | SND_ASYNC);

			显示棋子顺序
			//rrarrayqizhi();
			//rjarrayqizhi();

			//重置color
			color = 0;
			system("pause");
			goto C;
		}
		//加入平局的判断
		if (b == 0 && color == 224)   //因为color最大值是224
		{
			settextcolor(RGB(0, 0, 0));
			settextstyle(30, 0, L"宋体");
			setbkmode(TRANSPARENT);
			outtextxy(250, 200, L"我和你五五开!");
			outtextxy(65, 170, L"(请按任意键继续游戏)");
			PlaySound(L"ying.wav", NULL, SND_FILENAME | SND_ASYNC);

			//显示棋子顺序
			rrarrayqizhi();
			rjarrayqizhi();

			//重置color
			color = 0;
			system("pause");
			goto C;
		}
		//把当前下的棋保存在rjhuixy中
		rjhuixy.x = alphmax.x;
		rjhuixy.y = alphmax.y;
		color++;
		Sleep(100);
		break;
	}
	case WM_RBUTTONDOWN:   //设置悔棋功能
		//保证是悔的上一颗的棋
		if (huixy.x == xy.x && huixy.y == xy.y && getpixel(xy.x - 3, xy.y - 3) != RGB(248, 203, 18))
		{
			//悔自己的黑棋
			setfillcolor(RGB(248, 203, 18));
			setlinecolor(RGB(248, 203, 18));
			fillcircle(xy.x, xy.y, 10);
			//机器也要悔一步棋
			setfillcolor(RGB(248, 203, 18));
			setlinecolor(RGB(248, 203, 18));
			fillcircle(rjhuixy.x, rjhuixy.y, 10);

			//重新画棋盘
			setlinecolor(BLACK);
			for (int i = 1; i < 15; i++)
			{
				for (int j = 1; j < 15; j++)
				{
					rectangle(25 + j * 25, 325 + i * 25, 50 + j * 25, 350 + i * 25);
				}
			}
			color -= 2;
			break;
		}
	}
	//来一个重新检查  主要是让白棋不存在中心有黑线的情况
	for (int i = 0; i < 255; i++)
	{
		if (getpixel(master[i].x - 3, master[i].y - 3) == RGB(0, 0, 0))
		{
			setfillcolor(RGB(0, 0, 0));
			setlinecolor(RGB(0, 0, 0));
			fillcircle(master[i].x, master[i].y, 10);
		}
		if (getpixel(master[i].x - 3, master[i].y - 3) == RGB(255, 255, 255))
		{
			setfillcolor(RGB(255, 255, 255));
			setlinecolor(RGB(255, 255, 255));
			fillcircle(master[i].x, master[i].y, 10);
		}
	}
}

}

//游戏结束释放资源
void gameover()
{
//游戏结束释放资源
_getch();
closegraph();//关闭图形模式,释放由图形系统分配的所有内存
}

//游戏胜负的判定 返回1表示胜负已定 返回0表示胜负未分
int panduan(COLORREF cl, int x, int y)
{
int a, b;
//定义上下总个数
int i = 0;
a = x;
b = y;
//先检查上面的
while (cl == getpixel(a - 3, b - 3 - 25))
{
i++;
b -= 25;
}
//还原落子位置
a = x;
b = y;
//再检查下面的
while (cl == getpixel(a - 3, b - 3 + 25))
{
i++;
b += 25;
}
//还原落子位置
a = x;
b = y;
if (i >= 4)
{
return 1;
}

//定义左右总个数
int j = 0;
a = x;
b = y;
//先检查左面的
while (cl == getpixel(a - 3 - 25, b - 3))
{
	j++;
	a -= 25;
}
//还原落子位置
a = x;
b = y;
//再检查下面的
while (cl == getpixel(a - 3 + 25, b - 3))
{
	j++;
	a += 25;
}
//还原落子位置
a = x;
b = y;
if (j >= 4)
{
	return 1;
}

//定义斜线总个数
int k = 0;
a = x;
b = y;
//先检查上面的
while (cl == getpixel(a - 3 - 25, b - 3 - 25))
{
	k++;
	a -= 25;
	b -= 25;
}
//还原落子位置
a = x;
b = y;
//再检查下面的
while (cl == getpixel(a - 3 + 25, b - 3 + 25))
{
	k++;
	a += 25;
	b += 25;
}
//还原落子位置
a = x;
b = y;
if (k >= 4)
{
	return 1;
}

//定义斜线总个数
int l = 0;
a = x;
b = y;
//先检查上面的
while (cl == getpixel(a - 3 + 25, b - 3 - 25))
{
	l++;
	a += 25;
	b -= 25;
}
//还原落子位置
a = x;
b = y;
//再检查下面的
while (cl == getpixel(a - 3 - 25, b - 3 + 25))
{
	l++;
	a -= 25;
	b += 25;
}
//还原落子位置
a = x;
b = y;
if (l >= 4)
{
	return 1;
}
return 0;

}
//
人和人对战模式下游戏结束显示电脑的下棋顺序
//void arrayqizhi()
//{
// //主要实现的功能是在黑色的棋上显示白色顺序 在白色棋子上显示黑色的顺序 偶数为黑棋
// for (int i = 0; i <= color; i++)
// {
// if (i % 2 == 0)//轮到黑棋时打印白色顺序
// {
// setbkcolor(RGB(0, 0, 0));
// char arr[10];
// sprintf_s(arr, “%-2d”, i + 1);//将顺序打印到arr数组中去
// settextcolor(RGB(255, 255, 255));
// settextstyle(15, 0, L"宋体");
// outtextxy(array[i].x - 7, array[i].y - 7, _T(“arr”));//在指定位置输出字符串
// }
// else//轮到白棋时候的情况
// {
// setbkcolor(RGB(255, 255, 255));
// char arr[10];
// sprintf_s(arr, “%-2d”, i + 1);
// settextcolor(RGB(0, 0, 0));
// settextstyle(15, 0, L"宋体");
// outtextxy(array[i].x - 7, array[i].y - 7, _T(“arr”));
// }
// }
// //setbkcolor(RGB(249, 237, 225));//恢复了背景颜色
//}
//
人机对战模式下游戏结束显示人机的下棋顺序
//void rjarrayqizhi()
//{
// // 在白色棋子上显示黑色的顺序
// for (int i = 0; i <= color; i++)
// {
// if (i % 2 != 0)
// {
// setbkcolor(RGB(255, 255, 255));
// char arr[10];
// sprintf_s(arr, “%-2d”, i + 1);
// settextcolor(RGB(0, 0, 0));
// settextstyle(15, 0, L"宋体");
// outtextxy(rjarray[i].x - 7, rjarray[i].y - 7, arr);
// }
// }
// setbkcolor(RGB(249, 237, 225));//恢复了背景颜色
//}
//
人机模式游戏结束显示玩家的下棋顺序
//void rrarrayqizhi()
//{
// // 在黑色棋子上显示白色的顺序
// for (int i = 0; i <= color; i++)
// {
// if (i % 2 == 0)
// {
// setbkcolor(RGB(0, 0, 0));
// char arr[10];
// sprintf_s(arr, “%-2d”, i + 1);
// settextcolor(RGB(255, 255, 255));
// settextstyle(15, 0, L"宋体");
// outtextxy(array[i].x - 7, array[i].y - 7, arr);
// }
// }
// setbkcolor(RGB(249, 237, 225)); //恢复了背景颜色
//}

//创建一个人机判断 死几活几的通解 参数分别是 颜色, x坐标, y坐标, 死活判断(1代表死,2代表活), 死几或者活几 返回1代表成立,返回0代表不成立
int shpanduan(COLORREF cl, int x, int y, int q, int p)
{
//用一个K来体现某一个方向的下一个是背景而不是有另外颜色的(活) K = 1 表示下一个为背景色
int K = 0;
int a, b;
//定义上下总个数
int i = 0;
a = x;
b = y;
//先检查上面的
while (cl == getpixel(a - 3, b - 3 - 25))
{
i++;
b -= 25;
}
//检查是否下一个是背景色
if (getpixel(a - 3, b - 3 - 25) == RGB(248, 203, 18) && b - 25 > 350)
{
K++;
}
//还原落子位置
a = x;
b = y;
//再检查下面的
while (cl == getpixel(a - 3, b - 3 + 25))
{
i++;
b += 25;
}
//检查是否下一个是背景色
if (getpixel(a - 3, b - 3 + 25) == RGB(248, 203, 18) && b + 35 < 700)
{
K++;
}
//还原落子位置
a = x;
b = y;
if (i == p - 1 && K == q)
{
return 1;
}

//重置K
K = 0;
//定义左右总个数
int j = 0;
a = x;
b = y;
//先检查左面的
while (cl == getpixel(a - 3 - 25, b - 3))
{
	j++;
	a -= 25;
}
//检查是否下一个是背景色 
if (getpixel(a - 3 - 25, b - 3) == RGB(248, 203, 18) && a - 35 > 50)
{
	K++;
}
//还原落子位置
a = x;
b = y;
//再检查下面的
while (cl == getpixel(a - 3 + 25, b - 3))
{
	j++;
	a += 25;
}
//检查是否下一个是背景色 
if (getpixel(a - 3 + 25, b - 3) == RGB(248, 203, 18) && a + 35 < 700)
{
	K++;
}
//还原落子位置
a = x;
b = y;
if (j == p - 1 && K == q)
{
	return 1;     
}

//重置K
K = 0;
//定义斜线总个数
int k = 0;
a = x;
b = y;
//先检查上面的
while (cl == getpixel(a - 3 - 25, b - 3 - 25))
{
	k++;
	a -= 25;
	b -= 25;
}
//检查是否下一个是背景色
if (getpixel(a - 3 - 25, b - 3 - 25) == RGB(248, 203, 18) && a - 25 > 50 && b - 25 > 350)
{
	K++;
}
//还原落子位置
a = x;
b = y;
//再检查下面的
while (cl == getpixel(a - 3 + 25, b - 3 + 25))
{
	k++;
	a += 25;
	b += 25;
}
//检查是否下一个是背景色
if (getpixel(a - 3 + 25, b - 3 + 25) == RGB(248, 203, 18) && a + 25 < 400 && b + 25 < 700)
{
	K++;
}
//还原落子位置
a = x;
b = y;
if (k == p - 1 && K == q)
{
	return 1;    //
}

//重置K
K = 0;
//定义'/'总个数
int l = 0;
a = x;
b = y;
//先检查上面的
while (cl == getpixel(a - 3 + 25, b - 3 - 25))
{
	l++;
	a += 25;
	b -= 25;
}
//检查是否下一个是背景色
if (getpixel(a - 3 + 25, b - 3 - 25) == RGB(248, 203, 18) && a + 25 < 400 && b - 25 > 350)
{
	K++;
}
//还原落子位置
a = x;
b = y;
//再检查下面的
while (cl == getpixel(a - 3 - 25, b - 3 + 25))
{
	l++;
	a -= 25;
	b += 25;
}
//检查是否下一个是背景色
if (getpixel(a - 3 - 25, b - 3 + 25) == RGB(248, 203, 18) && a - 25 > 50 && b + 25 < 700)
{
	K++;
}
//还原落子位置
a = x;
b = y;
if (l == p - 1 && K == q)
{
	return 1;    /
}
return 0;

}

//人机每一步分析可用棋子上的分数值,返回分数最高的就是落子点
int scorepanduan(int x, int y)
{
/* 主要思想
电脑白子 玩家黑子
白子连成五子 +10000 阻碍黑子连成五子 +1000
白子连成活四 +200 阻碍黑子连成活四 +100
白子连成死四 +50 阻碍黑子连成死四 +20
白子连成活三 +30 阻碍黑子连成活三 +10
白子连成死三 +8 阻碍黑子连成死三 +5
白子连成活二 +2 阻碍黑子连成活二 +1
白子连成死二 +2 阻碍黑子连成死二 +1
白子连成活一 +1 阻碍黑子连成活一 +0
白子连成死一 +1 阻碍黑子连成死一 +0
*/
int a = x;
int b = y;
int score = 0;//定义得分

//白子连成五子	+10000
if (panduan(RGB(255, 255, 255), a, b))    //这个函数只是l的值与k的值不一样 所以可以加两个变量在函数里面 
{
	score += 10000;
}
//阻碍黑子连成五子	+1000
if (panduan(RGB(0, 0, 0), a, b))
{
	score += 1000;
}
//白子连成活四	+200      
if (shpanduan(RGB(255, 255, 255), a, b, 2, 4))
{
	score += 200;
}
//阻碍黑子连成活四	+100
if (shpanduan(RGB(0, 0, 0), a, b, 2, 4))
{
	score += 100;
}
//白子连成死四	+50	
if (shpanduan(RGB(255, 255, 255), a, b, 1, 4))
{
	score += 50;
}
//阻碍黑子连成死四	+20
if (shpanduan(RGB(0, 0, 0), a, b, 1, 4))
{
	score += 20;
}
//白子连成活三	+30	
if (shpanduan(RGB(255, 255, 255), a, b, 2, 3))
{
	score += 30;
}
//阻碍黑子连成活三	+10
if (shpanduan(RGB(0, 0, 0), a, b, 2, 3))
{
	score += 10;
}
//白子连成死三	+8	
if (shpanduan(RGB(255, 255, 255), a, b, 1, 3))
{
	score += 8;
}
//阻碍黑子连成死三	+5
if (shpanduan(RGB(0, 0, 0), a, b, 1, 3))
{
	score += 5;
}
//白子连成活二	+2	
if (shpanduan(RGB(255, 255, 255), a, b, 2, 2))
{
	score += 2;
}
//阻碍黑子连成活二	+1
if (shpanduan(RGB(0, 0, 0), a, b, 2, 2))
{
	score += 1;
}
//白子连成死二	+2	
if (shpanduan(RGB(255, 255, 255), a, b, 1, 2))
{
	score += 2;
}
//阻碍黑子连成死二	+1
if (shpanduan(RGB(0, 0, 0), a, b, 1, 2))
{
	score += 1;
}
//白子连成活一	+1	
if (shpanduan(RGB(255, 255, 255), a, b, 2, 1))
{
	score += 1;
}
/* //阻碍黑子连成活一	+0
	if()
	{
		score += 0;
	}*/
	//白子连成死一	+1	
if (shpanduan(RGB(255, 255, 255), a, b, 1, 1))
{
	score += 1;
}
return score;

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值