水墨五子棋(暂时未完成)

完成进度:

C++课程设计

老师布置了C++的课程设计,说是随便写点啥,同学们都写了各种基于黑框框(控制台)的什么学生成绩管理系统,感觉没什么创意,我想写一个图形界面的,本程序采用了EasyX图形库和一些Winodows API,然后用它来完成我的五子棋,具体实现过程就不说了,底下会放出源码的。在这里更一下进度吧。。

编译环境:

Visual Studio 2017(在编译选项里选择多字符集支持,默认是Unicode的字符集)

EasyX图形库

原来准备写三个功能:

1.双人对战(已完成)

2.单人AI(有BUG)

3.联机对战(没写)

背景音乐:

主界面:万代.传承

游戏界面:绿野仙踪

游戏截图

主界面:

《水墨五子棋(暂时未完成)》

鼠标移到对应选项会变色:

《水墨五子棋(暂时未完成)》

双人模式界面:

《水墨五子棋(暂时未完成)》

双人模式胜利界面:

《水墨五子棋(暂时未完成)》

AI模式胜利界面:

《水墨五子棋(暂时未完成)》


附上主要的代码,完整的代码去文末GitHub里面找:

#include <graphics.h>
#include <conio.h>
#include <stdio.h>
#include <cstring>
#include <string>
#include <iostream>
#include <algorithm>
#include <time.h>
#include "chess.h"
#include "Pos.h"
#define mem(a,b) memset(a,b,sizeof(a))
#include <windows.h>
#include <mmsystem.h>
#pragma comment(lib,"winmm.lib")
using namespace std;
#define window_x 1013
#define window_y 800
#define inf 0x3f3f3f3f
#define chess_r 49
#define debug() puts("what the fuck!!!")
int MODE = 1;//模式,1代表双人,2代表单人,3代表联机
Pos map[20][20];//存储每一个棋子的坐标
int vis[20][20];//标记一个位置当前有没有落子
int color[20][20];//1代表黑棋,0代表白棋
IMAGE MAPIMAGE[30][30];//图片对象
IMAGE NowChessImage;//存储请谁落子的图
void monse()
{
	POINT point;
	char s[10];
	while (true)
	{
		GetCursorPos(&point);
		// 输出鼠标坐标
		sprintf(s, _T("%d    "), point.x);
		outtextxy(0, 0, s);

		sprintf(s, _T("%d    "), point.y);
		outtextxy(0, 20, s);

		// 适当延时
		Sleep(10);

	}
}
void chess::welcome()
{
	mciSendString("open welcome.mp3", NULL, 0, 0);
	mciSendString("play welcome.mp3 repeat", NULL, 0, 0);


	initgraph(1024, 632);//创建一个1024*632的画布
	loadimage(NULL, "welcome.jpg");//放置背景
	 /*mciSendString("open welcome.mp3", NULL, 0, 0);
	 mciSendString("play welcome.mp3", NULL, 0, 0);*/
	 //monse();
	setbkmode(TRANSPARENT);//透明字体
	HWND hwnd = GetHWnd();//获取当前窗口句柄
	SetWindowText(hwnd, "蒟蒻的五子棋 --- By:贺鹏程");//设置窗口标题
	settextcolor(RGB(77, 77, 77));
	LOGFONT f;//字体类对象
	gettextstyle(&f);//获取当前字体设置
	f.lfHeight = 70;
	strcpy_s(f.lfFaceName, "微软雅黑");
	f.lfQuality = ANTIALIASED_QUALITY;//字体抗锯齿
	settextstyle(&f);
	RECT r1 = { 500, 300, 800, 400 };
	RECT r2 = { 500, 405, 800, 505 };
	RECT r3 = { 500, 510, 800, 610 };
	/*setlinecolor(BLACK);
	rectangle(500, 300, 800, 400);*/
	drawtext("【双人模式】", &r1, DT_CENTER | DT_VCENTER | DT_SINGLELINE);//文字居中,文字垂直居中,使文字显示在一行
	drawtext("【单人A   I】", &r2, DT_CENTER | DT_VCENTER | DT_SINGLELINE);//文字居中,文字垂直居中,使文字显示在一行
	drawtext("【联机对战】", &r3, DT_CENTER | DT_VCENTER | DT_SINGLELINE);//文字居中,文字垂直居中,使文字显示在一行
																	//--------------------------------------------------------------------------------------------
	bool flag = true;
	MOUSEMSG m;//定义一个鼠标对象
	while (flag)
	{
		//这个函数用于开始批量绘图。执行后,任何绘图操作都将暂时不输出到屏幕上,直到执行 FlushBatchDraw 或 EndBatchDraw 才将之前的绘图输出。
		BeginBatchDraw();
		m = GetMouseMsg();//获取鼠标消息
		switch (m.uMsg)
		{
		case WM_LBUTTONDOWN://鼠标左键按下
			EndBatchDraw();
			if (m.x >= 500 && m.x <= 800 && m.y >= 300 && m.y <= 400)//判断在开始游戏的矩形区域内
			{

				flag = false;
				MODE = 1;
				closegraph();
			}
			else if (m.x >= 500 && m.x <= 800 && m.y >= 405 && m.y <= 505)//单人ai模式
			{

				flag = false;
				MODE = 2;
				closegraph();

			}
		case WM_MOUSEMOVE://监测鼠标移动
			EndBatchDraw();
			if (m.x >= 500 && m.x <= 800 && m.y >= 300 && m.y <= 400)//判断鼠标在开始游戏的矩形区域内
			{
				settextcolor(RGB(254, 67, 101));
				drawtext("【双人模式】", &r1, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
			}
			else if (m.x >= 500 && m.x <= 800 && m.y >= 405 && m.y <= 505)
			{
				settextcolor(RGB(254, 67, 101));
				drawtext("【单人A   I】", &r2, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
			}
			else if (m.x >= 500 && m.x <= 800 && m.y >= 510 && m.y <= 610)
			{
				settextcolor(RGB(254, 67, 101));
				drawtext("【联机对战】", &r3, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
			}
			else
			{
				settextcolor(RGB(77, 77, 77));
				drawtext("【双人模式】", &r1, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
				drawtext("【单人A   I】", &r2, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
				drawtext("【联机对战】", &r3, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
			}
			//break;
		}
	}

}
double chess::dis(int x1, int y1, int x2, int y2)//算出两点间的距离
{
	return sqrt((double)((x1 - x2)*(x1 - x2)) + (double)((y1 - y2)*(y1 - y2)));
}
bool chess::JudgeChess(int x, int y)
{
	//思路:以当前点为中心点,向四个方向展开搜索
	if (color[x][y] == 0)//判断白棋连珠
	{
		int num = 0;//记录棋子数量
  //横向x不变
		for (int i = y; i <= 15; i++)//向右
		{
			if (color[x][i] == 0)
			{
				num++;
			}
			else
				break;
		}
		for (int i = y - 1; i >= 0; i--)//向左
		{
			if (color[x][i] == 0)
			{
				num++;
			}
			else
				break;
		}
		if (num >= 5)
			return true;//横向连珠,返回结果
		num = 0;//归零
				//竖向y不变
		for (int i = x; i <= 15; i++)//向下
		{
			if (color[i][y] == 0)
			{
				num++;
			}
			else
				break;
		}
		for (int i = x - 1; i >= 0; i--)//向上
		{
			if (color[i][y] == 0)
			{
				num++;
			}
			else
				break;
		}
		if (num >= 5)
			return true;//竖向连珠,返回结果
		num = 0;//归零
				//由右下斜向左上'\'
		for (int i = x, j = y; (i >= 0 && i <= 15 && j >= 0 && j <= 15); i--, j--)//由当前点向左上
		{
			if (color[i][j] == 0)
			{
				num++;
			}
			else
				break;
		}
		for (int i = x + 1, j = y + 1; (i >= 0 && i <= 15 && j >= 0 && j <= 15); i++, j++)//由当前点向右下
		{
			if (color[i][j] == 0)
			{
				num++;
			}
			else
				break;
		}
		if (num >= 5)
			return true;// '\'连珠,返回结果
		num = 0;//归零
				//由左下斜向右上'/'
		for (int i = x, j = y; (i >= 0 && i <= 15 && j >= 0 && j <= 15); i--, j++)//由当前点斜向右上
		{
			if (color[i][j] == 0)
			{
				num++;
			}
			else
				break;
		}
		for (int i = x + 1, j = y - 1; (i >= 0 && i <= 15 && j >= 0 && j <= 15); i++, j--)//由当前点斜下左下
		{
			if (color[i][j] == 0)
			{
				num++;
			}
			else
				break;
		}
		if (num >= 5)
			return true;// '/'连珠,返回结果
		num = 0;//归零
		return false;//白棋不能连珠
	}
	else if (color[x][y] == 1)//黑棋连珠
	{
		int num = 0;//记录棋子数量
					//横向x不变
		for (int i = y; i <= 15; i++)//向右
		{
			if (color[x][i] == 1)
			{
				num++;
			}
			else
				break;
		}
		for (int i = y - 1; i >= 0; i--)//向左
		{
			if (color[x][i] == 1)
			{
				num++;
			}
			else
				break;
		}
		if (num >= 5)
			return true;//横向连珠,返回结果
		num = 0;//归零
				//竖向y不变
		for (int i = x; i <= 15; i++)//向下
		{
			if (color[i][y] == 1)
			{
				num++;
			}
			else
				break;
		}
		for (int i = x - 1; i >= 0; i--)//向上
		{
			if (color[i][y] == 1)
			{
				num++;
			}
			else
				break;
		}
		if (num >= 5)
			return true;//竖向连珠,返回结果
		num = 0;//归零
				//由右下斜向左上'\'
		for (int i = x, j = y; (i >= 0 && i <= 15 && j >= 0 && j <= 15); i--, j--)//由当前点向左上
		{
			if (color[i][j] == 1)
			{
				num++;
			}
			else
				break;
		}
		for (int i = x + 1, j = y + 1; (i >= 0 && i <= 15 && j >= 0 && j <= 15); i++, j++)//由当前点向右下
		{
			if (color[i][j] == 1)
			{
				num++;
			}
			else
				break;
		}
		if (num >= 5)
			return true;// '\'连珠,返回结果
		num = 0;//归零
				//由左下斜向右上'/'
		for (int i = x, j = y; (i >= 0 && i <= 15 && j >= 0 && j <= 15); i--, j++)//由当前点斜向右上
		{
			if (color[i][j] == 1)
			{
				num++;
			}
			else
				break;
		}
		for (int i = x + 1, j = y - 1; (i >= 0 && i <= 15 && j >= 0 && j <= 15); i++, j--)//由当前点斜下左下
		{
			if (color[i][j] == 1)
			{
				num++;
			}
			else
				break;
		}
		if (num >= 5)
			return true;// '/'连珠,返回结果
		num = 0;//归零
		return false;//黑棋不能连珠
	}
}
void chess::PlayGame1()
{
	/*---------------------------------处理背景音乐------------------------------------------------*/
	mciSendString("close welcome.mp3", NULL, 0, 0);
	mciSendString("open palying.mp3", NULL, 0, 0);
	mciSendString("play palying.mp3 repeat", NULL, 0, 0);
	/*---------------------------------画棋盘------------------------------------------------*/
	initgraph(window_x, window_y);
	loadimage(NULL, "4.jpg");
	HWND hwnd = GetHWnd();//获取当前窗口句柄
	SetWindowText(hwnd, "蒟蒻的五子棋 --- By:贺鹏程");//设置窗口标题
	setlinestyle(PS_SOLID, 2);
	setlinecolor(BLACK);
	for (int x = 30; x <= 765; x += 49)
	{
		line(30, x, 765, x);
	}
	for (int y = 30; y <= 765; y += 49)
	{
		line(y, 30, y, 765);
	}
	/*---------------------------------存储棋盘坐标------------------------------------------------*/

	//存储坐标
	for (int i = 0; i <= 15; i++)
	{
		for (int j = 0; j <= 15; j++)
		{
			map[i][j].x = 30 + 49 * j;
		}
	}
	for (int i = 0; i <= 15; i++)
	{
		for (int j = 0; j <= 15; j++)
		{
			map[j][i].y = 30 + 49 * j;
		}
	}

	//画黑点
	setlinecolor(BLACK);
	setfillcolor(BLACK);
	fillrectangle(map[3][3].x - 3, map[3][3].y - 3, map[3][3].x + 3, map[3][3].y + 3);
	fillrectangle(map[3][11].x - 3, map[3][11].y - 3, map[3][11].x + 3, map[3][11].y + 3);
	fillrectangle(map[7][7].x - 3, map[7][7].y - 3, map[7][7].x + 3, map[7][7].y + 3);
	fillrectangle(map[11][3].x - 3, map[11][3].y - 3, map[11][3].x + 3, map[11][3].y + 3);
	fillrectangle(map[11][11].x - 3, map[11][11].y - 3, map[11][11].x + 3, map[11][11].y + 3);
	//存储每一个位置的圆的图片
	/*for (int i = 0; i <= 15; i++)
	{
	for (int j = 0; j <= 15; j++)
	{
	getimage(&MAPIMAGE[i][j],)
	}
	}*/

	/*---------------------------------游戏开始------------------------------------------------*/
	mem(vis, 0);//清零标记数组
	mem(color, -1);//把颜色全部设置无
	bool flag = true;
	int opp = 0;//偶数是黑棋,奇数是白棋
	MOUSEMSG m;//定义一个鼠标对象


			   /*setlinestyle(PS_SOLID, 1);
			   setlinecolor(BLACK);*/
	getimage(&NowChessImage, 780, 40, 1000, 100);//获取原来的图像并存储
												 //rectangle(780,40, 1000, 100);
	settextcolor(RGB(77, 77, 77));
	RECT r1 = { 780,40, 1000, 100 };
	LOGFONT f;//字体类对象
	setbkmode(TRANSPARENT);//透明字体
	gettextstyle(&f);//获取当前字体设置
	f.lfHeight = 50;
	strcpy_s(f.lfFaceName, "微软雅黑");
	f.lfQuality = ANTIALIASED_QUALITY;//字体抗锯齿
	settextstyle(&f);
	drawtext("请黑方落子", &r1, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
	while (flag)
	{
		//这个函数用于开始批量绘图。执行后,任何绘图操作都将暂时不输出到屏幕上,直到执行 FlushBatchDraw 或 EndBatchDraw 才将之前的绘图输出。
		BeginBatchDraw();
		m = GetMouseMsg();//获取鼠标消息
		switch (m.uMsg)
		{
		case WM_LBUTTONDOWN://鼠标左键按下
			EndBatchDraw();
			Pos temp;
			temp.x = inf, temp.y = inf;
			double R = 10000000.0;
			for (int i = 0; i <= 15; i++)
			{
				for (int j = 0; j <= 15; j++)
				{
					if (dis(map[i][j].x, map[i][j].y, m.x, m.y)<R)
					{
						R = dis(map[i][j].x, map[i][j].y, m.x, m.y);
						temp.x = i;
						temp.y = j;
					}
				}
			}
			setlinecolor(BLACK);
			if (!vis[temp.x][temp.y])//只有没有被标记过才可以走
			{
				vis[temp.x][temp.y] = 1;
				if (opp & 1)//是奇数就画白棋
				{

					setfillcolor(WHITE);
					fillcircle(map[temp.x][temp.y].x, map[temp.x][temp.y].y, chess_r / 3);
					PlaySound(TEXT("chessmusic.wav"), 0, SND_FILENAME);//播放声音
					putimage(780, 40, &NowChessImage);
					drawtext("请黑方落子", &r1, DT_CENTER | DT_VCENTER | DT_SINGLELINE);

					color[temp.x][temp.y] = 0;
					if (JudgeChess(temp.x, temp.y) == true)//白棋可以连珠
					{
						flag = false;
						GameOver1(0);
					}

				}
				else//偶数就画黑棋
				{

					setfillcolor(BLACK);
					fillcircle(map[temp.x][temp.y].x, map[temp.x][temp.y].y, chess_r / 3);
					PlaySound(TEXT("chessmusic.wav"), 0, SND_FILENAME);

					putimage(780, 40, &NowChessImage);
					drawtext("请白方落子", &r1, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
					color[temp.x][temp.y] = 1;//标记颜色
					if (JudgeChess(temp.x, temp.y) == true)//黑棋可以连珠
					{
						flag = false;
						GameOver1(1);
					}
				}
				opp++;//改变状态
			}
			//case WM_MOUSEMOVE://监测鼠标移动
			//	EndBatchDraw();
		}
	}
}
void chess::GameOver1(int n)
{
	settextcolor(RGB(254, 67, 101));
	LOGFONT f;//字体类对象
	setbkmode(TRANSPARENT);//透明字体
	gettextstyle(&f);//获取当前字体设置
	f.lfHeight = 120;
	strcpy_s(f.lfFaceName, "黑体");
	f.lfQuality = ANTIALIASED_QUALITY;//字体抗锯齿
	settextstyle(&f);
	RECT r1 = { 0, 0, 800, 800 };
	RECT r2 = { 790, 710, 980, 760 };
	RECT r3 = { 780,40, 1000, 100 };
	setlinecolor(BLACK);
	if (n == 0)
	{
		drawtext("白 棋 获 胜", &r1, DT_CENTER | DT_VCENTER | DT_SINGLELINE);//文字居中,文字垂直居中,使文字显示在一行

	}
	else if (n == 1)
	{
		drawtext("黑 棋 获 胜", &r1, DT_CENTER | DT_VCENTER | DT_SINGLELINE);//文字居中,文字垂直居中,使文字显示在一行
	}
	gettextstyle(&f);//获取当前字体设置
	f.lfHeight = 50;
	strcpy_s(f.lfFaceName, "微软雅黑");
	f.lfQuality = ANTIALIASED_QUALITY;//字体抗锯齿
	settextstyle(&f);
	putimage(780, 40, &NowChessImage);
	drawtext("游戏结束", &r3, DT_CENTER | DT_VCENTER | DT_SINGLELINE);


	//设置矩形
	setlinestyle(PS_SOLID, 1);
	setlinecolor(BLACK);
	rectangle(790, 710, 980, 760);//画重新开始的矩形边框
	setbkmode(TRANSPARENT);//透明字体
	gettextstyle(&f);//获取当前字体设置
	f.lfHeight = 50;
	strcpy_s(f.lfFaceName, "微软雅黑");
	f.lfQuality = ANTIALIASED_QUALITY;//字体抗锯齿
	settextstyle(&f);
	settextcolor(RGB(77, 77, 77));
	drawtext("重新开始", &r2, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
	bool flag = true;
	MOUSEMSG m;//定义一个鼠标对象
	while (flag)
	{
		//这个函数用于开始批量绘图。执行后,任何绘图操作都将暂时不输出到屏幕上,直到执行 FlushBatchDraw 或 EndBatchDraw 才将之前的绘图输出。
		BeginBatchDraw();
		m = GetMouseMsg();//获取鼠标消息
		switch (m.uMsg)
		{
		case WM_LBUTTONDOWN://鼠标左键按下
			EndBatchDraw();
			if (m.x >= 790 && m.x <= 980 && m.y >= 710 && m.y <= 760)//判断在开始游戏的矩形区域内
			{
				flag = false;
				//***********************************************
				PlayGame1();//重新开始游戏
			}
			//break;
		case WM_MOUSEMOVE://监测鼠标移动
			EndBatchDraw();
			if (m.x >= 790 && m.x <= 980 && m.y >= 710 && m.y <= 760)//判断鼠标在开始游戏的矩形区域内
			{
				settextcolor(RGB(254, 67, 101));
				drawtext("重新开始", &r2, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
			}
			else
			{
				settextcolor(RGB(77, 77, 77));
				drawtext("重新开始", &r2, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
			}
			//break;
		}
	}


}
void chess::PlayGame2()
{
	/*---------------------------------处理背景音乐------------------------------------------------*/
	mciSendString("close welcome.mp3", NULL, 0, 0);
	mciSendString("open palying.mp3", NULL, 0, 0);
	mciSendString("play palying.mp3 repeat", NULL, 0, 0);
	/*---------------------------------画棋盘------------------------------------------------*/
	initgraph(window_x, window_y);
	loadimage(NULL, "4.jpg");
	HWND hwnd = GetHWnd();//获取当前窗口句柄
	SetWindowText(hwnd, "蒟蒻的五子棋 --- By:贺鹏程");//设置窗口标题
	setlinestyle(PS_SOLID, 2);
	setlinecolor(BLACK);
	for (int x = 30; x <= 765; x += 49)
	{
		line(30, x, 765, x);
	}
	for (int y = 30; y <= 765; y += 49)
	{
		line(y, 30, y, 765);
	}
	/*---------------------------------存储棋盘坐标------------------------------------------------*/

	//存储坐标
	for (int i = 0; i <= 15; i++)
	{
		for (int j = 0; j <= 15; j++)
		{
			map[i][j].x = 30 + 49 * j;
		}
	}
	for (int i = 0; i <= 15; i++)
	{
		for (int j = 0; j <= 15; j++)
		{
			map[j][i].y = 30 + 49 * j;
		}
	}

	//画黑点
	setlinecolor(BLACK);
	setfillcolor(BLACK);
	fillrectangle(map[3][3].x - 3, map[3][3].y - 3, map[3][3].x + 3, map[3][3].y + 3);
	fillrectangle(map[3][11].x - 3, map[3][11].y - 3, map[3][11].x + 3, map[3][11].y + 3);
	fillrectangle(map[7][7].x - 3, map[7][7].y - 3, map[7][7].x + 3, map[7][7].y + 3);
	fillrectangle(map[11][3].x - 3, map[11][3].y - 3, map[11][3].x + 3, map[11][3].y + 3);
	fillrectangle(map[11][11].x - 3, map[11][11].y - 3, map[11][11].x + 3, map[11][11].y + 3);
	//存储每一个位置的圆的图片

	/*---------------------------------游戏开始------------------------------------------------*/
	mem(vis, 0);//清零标记数组
	mem(color, -1);//把颜色全部设置无
	bool flag = true;
	int opp = 0;//偶数是黑棋,奇数是白棋
	MOUSEMSG m;//定义一个鼠标对象

	getimage(&NowChessImage, 780, 40, 1000, 100);//获取原来的图像并存储

	settextcolor(RGB(77, 77, 77));
	RECT r1 = { 780,40, 1000, 100 };
	LOGFONT f;//字体类对象
	setbkmode(TRANSPARENT);//透明字体
	gettextstyle(&f);//获取当前字体设置
	f.lfHeight = 50;
	strcpy_s(f.lfFaceName, "微软雅黑");
	settextstyle(&f);
	drawtext("请黑方落子", &r1, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
	while (flag)
	{
		//这个函数用于开始批量绘图。执行后,任何绘图操作都将暂时不输出到屏幕上,直到执行 FlushBatchDraw 或 EndBatchDraw 才将之前的绘图输出。
		BeginBatchDraw();
		m = GetMouseMsg();//获取鼠标消息
		switch (m.uMsg)
		{
		case WM_LBUTTONDOWN://鼠标左键按下
			EndBatchDraw();
			Pos temp;
			temp.x = inf, temp.y = inf;
			double R = 10000000.0;
			for (int i = 0; i <= 15; i++)
			{
				for (int j = 0; j <= 15; j++)
				{
					if (dis(map[i][j].x, map[i][j].y, m.x, m.y)<R)
					{
						R = dis(map[i][j].x, map[i][j].y, m.x, m.y);
						temp.x = i;
						temp.y = j;
					}
				}
			}
			setlinecolor(BLACK);
			int black_go = 0;
			if (!vis[temp.x][temp.y])//只有没有被标记过才可以走
			{
				vis[temp.x][temp.y] = 1;
				black_go = 1;

				//////////////////////画黑棋//////////////////////////
				setfillcolor(BLACK);
				fillcircle(map[temp.x][temp.y].x, map[temp.x][temp.y].y, chess_r / 3);
				PlaySound(TEXT("chessmusic.wav"), 0, SND_FILENAME);

				putimage(780, 40, &NowChessImage);
				drawtext("请白方落子", &r1, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
				color[temp.x][temp.y] = 1;//标记颜色
				if (JudgeChess(temp.x, temp.y) == true)//黑棋可以连珠
				{
					flag = false;
					GameOver2(1);
					break;
				}
			}
				///////////////////////////////画白棋//////////////////////////////////
			Pos PointWhite = GetAddress();
			if (!vis[PointWhite.x][PointWhite.y] && black_go == 1)
			{
				vis[PointWhite.x][PointWhite.y] = 1;
				setfillcolor(WHITE);
				//MessageBox(NULL, to_string(PointWhite.y).c_str(), "Title(标题)", MB_OK);
				fillcircle(map[PointWhite.x][PointWhite.y].x, map[PointWhite.x][PointWhite.y].y, chess_r / 3);
				PlaySound(TEXT("chessmusic.wav"), 0, SND_FILENAME);//播放声音
				putimage(780, 40, &NowChessImage);
				drawtext("请黑方落子", &r1, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
				color[PointWhite.x][PointWhite.y] = 0;
				if (JudgeChess(PointWhite.x, PointWhite.y) == true)//白棋可以连珠
				{
					flag = false;
					GameOver2(0);
					break;
				}
			}
		}
	}
}
void chess::GameOver2(int n)
{
	settextcolor(RGB(254, 67, 101));
	LOGFONT f;//字体类对象
	setbkmode(TRANSPARENT);//透明字体
	gettextstyle(&f);//获取当前字体设置
	f.lfHeight = 120;
	strcpy_s(f.lfFaceName, "黑体");
	f.lfQuality = ANTIALIASED_QUALITY;//字体抗锯齿
	settextstyle(&f);
	RECT r1 = { 0, 0, 800, 800 };
	RECT r2 = { 790, 710, 980, 760 };
	RECT r3 = { 780,40, 1000, 100 };
	setlinecolor(BLACK);
	if (n == 0)
	{
		drawtext("电 脑 获 胜", &r1, DT_CENTER | DT_VCENTER | DT_SINGLELINE);//文字居中,文字垂直居中,使文字显示在一行

	}
	else if (n == 1)
	{
		drawtext("玩 家 获 胜", &r1, DT_CENTER | DT_VCENTER | DT_SINGLELINE);//文字居中,文字垂直居中,使文字显示在一行
	}
	gettextstyle(&f);//获取当前字体设置
	f.lfHeight = 50;
	strcpy_s(f.lfFaceName, "微软雅黑");
	f.lfQuality = ANTIALIASED_QUALITY;//字体抗锯齿
	settextstyle(&f);
	putimage(780, 40, &NowChessImage);
	drawtext("游戏结束", &r3, DT_CENTER | DT_VCENTER | DT_SINGLELINE);


	//设置矩形
	setlinestyle(PS_SOLID, 1);
	setlinecolor(BLACK);
	rectangle(790, 710, 980, 760);//画重新开始的矩形边框
	setbkmode(TRANSPARENT);//透明字体
	gettextstyle(&f);//获取当前字体设置
	f.lfHeight = 50;
	strcpy_s(f.lfFaceName, "微软雅黑");
	f.lfQuality = ANTIALIASED_QUALITY;//字体抗锯齿
	settextstyle(&f);
	settextcolor(RGB(77, 77, 77));
	drawtext("重新开始", &r2, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
	bool flag = true;
	MOUSEMSG m;//定义一个鼠标对象
	while (flag)
	{
		//这个函数用于开始批量绘图。执行后,任何绘图操作都将暂时不输出到屏幕上,直到执行 FlushBatchDraw 或 EndBatchDraw 才将之前的绘图输出。
		BeginBatchDraw();
		m = GetMouseMsg();//获取鼠标消息
		switch (m.uMsg)
		{
		case WM_LBUTTONDOWN://鼠标左键按下
			EndBatchDraw();
			if (m.x >= 790 && m.x <= 980 && m.y >= 710 && m.y <= 760)//判断在开始游戏的矩形区域内
			{
				flag = false;
				//***********************************************
				PlayGame2();//重新开始游戏

			}
			//break;
		case WM_MOUSEMOVE://监测鼠标移动
			EndBatchDraw();
			if (m.x >= 790 && m.x <= 980 && m.y >= 710 && m.y <= 760)//判断鼠标在开始游戏的矩形区域内
			{
				settextcolor(RGB(254, 67, 101));
				drawtext("重新开始", &r2, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
			}
			else
			{
				settextcolor(RGB(77, 77, 77));
				drawtext("重新开始", &r2, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
			}
			//break;
		}
	}
}
Pos chess::GetAddress()//传进来当前落子的坐标
{
	Pos now;
	int choose_score = 1;//判分,如果需要防守此值为0,要进攻为1
//白棋防守,判断黑棋最多能连成几个棋子,然后进行封堵
	int flag = 1;//判断是否跳出循环
	for (int x = 0; x <= 15 && flag; x++)
	{
		for (int y = 0; y <= 15 && flag; y++)
		{
			if (color[x][y] == 1 && flag)//如果当前棋子的颜色为黑色
			{
				int num = 0;//记录连续黑色棋子数量
							//横向x不变
				for (int i = y; i <= 15; i++)//向右
				{
					if (color[x][i] == 1)
					{
						num++;
					}
					else
						break;
				}
				for (int i = y - 1; i >= 0; i--)//向左
				{
					if (color[x][i] == 1)
					{
						num++;
					}
					else
						break;
				}
				if (num >= 3)//如果横向已经连成三个
				{
					choose_score = 0;
					int flog = 1;//区分是否已找到
					for (int i = y; i <= 15 && flog; i++)//向右
					{
						if (color[x][i] == -1)
						{
							flog = 0;
							now.x = x;
							now.y = i;
						}
					}
					for (int i = y - 1; i >= 0 && flog; i--)//向左
					{
						if (color[x][i] == -1)
						{
							flog = 0;
							now.x = x;
							now.y = i;
						}

					}
					flag = 0;
					break;
				}
				num = 0;
				//竖向y不变
				for (int i = x; i <= 15; i++)//向下
				{
					if (color[i][y] == 1)
					{
						num++;
					}
					else
						break;
				}
				for (int i = x - 1; i >= 0; i--)//向上
				{
					if (color[i][y] == 1)
					{
						num++;
					}
					else
						break;
				}
				if (num >= 3)//如果竖向已经连成三个
				{
					choose_score = 0;
					int flog = 1;
					for (int i = x; i <= 15 && flog; i++)//向下
					{
						if (color[i][y] == -1)
						{
							flog = 0;
							now.x = i;
							now.y = y;
						}
					}
					for (int i = x - 1; i >= 0 && flog; i--)//向上
					{
						if (color[i][y] == 1)
						{
							flog = 0;
							now.x = i;
							now.y = y;
						}
					}
					flag = 0;
					break;
				}
				num = 0;
				//由右下斜向左上'\'
				for (int i = x, j = y; (i >= 0 && i <= 15 && j >= 0 && j <= 15); i--, j--)//由当前点向左上
				{
					if (color[i][j] == 1)
					{
						num++;
					}
					else
						break;
				}
				for (int i = x + 1, j = y + 1; (i >= 0 && i <= 15 && j >= 0 && j <= 15); i++, j++)//由当前点向右下
				{
					if (color[i][j] == 1)
					{
						num++;
					}
					else
						break;
				}
				if (num >= 3)//如果'\'已经连成三个
				{
					choose_score = 0;
					int flog = 1;
					for (int i = x, j = y; (i >= 0 && i <= 15 && j >= 0 && j <= 15) && flog; i--, j--)//由当前点向左上
					{
						if (color[i][j] == -1)
						{
							flog = 0;
							now.x = i;
							now.y = j;
						}
					}
					for (int i = x + 1, j = y + 1; (i >= 0 && i <= 15 && j >= 0 && j <= 15) && flog; i++, j++)//由当前点向右下
					{
						if (color[i][j] == -1)
						{
							flog = 0;
							now.x = i;
							now.y = j;
						}
					}
					flag = 0;
					break;
				}
				num = 0;
				//由左下斜向右上'/'
				for (int i = x, j = y; (i >= 0 && i <= 15 && j >= 0 && j <= 15); i--, j++)//由当前点斜向右上
				{
					if (color[i][j] == 1)
					{
						num++;
					}
					else
						break;
				}
				for (int i = x + 1, j = y - 1; (i >= 0 && i <= 15 && j >= 0 && j <= 15); i++, j--)//由当前点斜下左下
				{
					if (color[i][j] == 1)
					{
						num++;
					}
					else
						break;
				}
				if (num >= 3)//如果已经连成三个
				{
					choose_score = 0;
					int flog = 1;
					for (int i = x, j = y; (i >= 0 && i <= 15 && j >= 0 && j <= 15) && flog; i--, j++)//由当前点斜向右上
					{
						if (color[i][j] == -1)
						{
							flog = 0;
							now.x = i;
							now.y = j;
						}
					}
					for (int i = x + 1, j = y - 1; (i >= 0 && i <= 15 && j >= 0 && j <= 15) && flog; i++, j--)//由当前点斜下左下
					{
						if (color[i][j] == -1)
						{
							flog = 0;
							now.x = i;
							now.y = j;
						}
					}
					flag = 0;
					break;
				}
				num = 0;

			}
		}
	}
	//白棋进攻,找到对自己最有利的,判断当前白棋最多能连几个棋子
	int maxx = 0;
	if (choose_score)
	{
		for (int x = 0; x <= 15; x++)
		{
			for (int y = 0; y <= 15; y++)
			{
				if (color[x][y] == -1)//这一点可以落子
				{
					int num = 0;//记录棋子数量
					int max_num = 0;
					//横向x不变
					for (int i = y; i <= 15; i++)//向右
					{
						if (color[x][i] == 0)
						{
							num++;
						}
						else
							break;
					}
					for (int i = y - 1; i >= 0; i--)//向左
					{
						if (color[x][i] == 0)
						{
							num++;
						}
						else
							break;
					}
					max_num = max(max_num, num);
					num = 0;
					//竖向y不变
					for (int i = x; i <= 15; i++)//向下
					{
						if (color[i][y] == 0)
						{
							num++;
						}
						else
							break;
					}
					for (int i = x - 1; i >= 0; i--)//向上
					{
						if (color[i][y] == 0)
						{
							num++;
						}
						else
							break;
					}
					max_num = max(max_num, num);
					num = 0;
					//由右下斜向左上'\'
					for (int i = x, j = y; (i >= 0 && i <= 15 && j >= 0 && j <= 15); i--, j--)//由当前点向左上
					{
						if (color[i][j] == 0)
						{
							num++;
						}
						else
							break;
					}
					for (int i = x + 1, j = y + 1; (i >= 0 && i <= 15 && j >= 0 && j <= 15); i++, j++)//由当前点向右下
					{
						if (color[i][j] == 0)
						{
							num++;
						}
						else
							break;
					}
					max_num = max(max_num, num);
					num = 0;
					//由左下斜向右上'/'
					for (int i = x, j = y; (i >= 0 && i <= 15 && j >= 0 && j <= 15); i--, j++)//由当前点斜向右上
					{
						if (color[i][j] == 0)
						{
							num++;
						}
						else
							break;
					}
					for (int i = x + 1, j = y - 1; (i >= 0 && i <= 15 && j >= 0 && j <= 15); i++, j--)//由当前点斜下左下
					{
						if (color[i][j] == 0)
						{
							num++;
						}
						else
							break;
					}
					max_num = max(max_num, num);
					num = 0;

					if (maxx <= max_num)
					{
						maxx = max_num;
						now.x = x;
						now.y = y;
					}
				}
			}
		}
	}
	//MessageBox(NULL, to_string(now.x).c_str(), "Title(标题)", MB_OK);
	return now;
}
int main()
{
	chess fivech;
	fivech.welcome();//欢迎界面
	if (MODE == 1)//双人模式
	{
		fivech.PlayGame1();
	}
	else if (MODE == 2)//单人ai
	{
		fivech.PlayGame2();
	}
	getch();
	closegraph();
	return 0;
}

 

在这里附上编译好的下载地址:

云盘下载     密码:x1ao

项目源码在GitHub上:https://github.com/riba2534/Ink-FiveChess

欢迎fork…..(不过还是等写完吧,代码不忍直视~~~)

 

点赞
  1. riba2534说道:

    虽然没人看,自己沙发一下 :razz:

    1. thinkelreo说道:

      不不不,还是有人看的 :biggrin:

  2. ribald说道:

    还是很厉害的

  3. vonhyou说道:

    %%%很强大

发表评论

电子邮件地址不会被公开。 必填项已用*标注