五子棋项目总结

 在做这个项目之前就曾经用C++写过五子棋,不过当时只实现了一个简单的人人对战模式,现在又写了5天,虽然已经实现了更多的功能,但仍然有些许BUG,人机还有些智障,但我会继续改进,完善项目

#include<easyx.h>
#include<graphics.h>
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
//注意 项目->属性->配置属性->高级->字符集 要选择使用多字节字符集

int igwide = 641, igwigh = 640;//主界面窗口长宽
int buttw = 215, buttg = 130, butth = 80;//按钮距主界面左间距,上间距,按钮高
int qpw = 898, qph = 894;//棋盘宽和高


//函数声明部分
void playDouble();
void creat_first();
void playAI();
void Drawchess(int, int);

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

struct member {//储存玩家信息的结构体
	int step;//战胜AI所用的步数
	char name[100];//玩家名称
	char qizi[100];//战胜AI所用棋子颜色
}num[101];
int coutall;//当前保存在num数组中的信息个数
int openphbfile(member* a) {//打开排行榜文件读取信息到member数组中,a指向数组第一个元素,返回读取玩家信息的个数
	FILE* bs;
	if ((bs = fopen("member.dat", "rb")) == NULL) {//使用fopen会有报错C4996,在项目->属性->配置属性->c/c++ ->预处理器中添加定义:_CRT_SECURE_NO_WARNINGS即可解决
		bs=fopen("member.dat", "wb");//新建文件
		return 0;
	}
	int count = 1;
	while (true) {
		if (fread(&a[count], sizeof(member), 1, bs) != 1) {//从文件读数据读入num数组,读完结束
			break;
		}
		count++;
	}
	for (int i = 1; i <= count - 1; i++) {//给读到的结构体数组排序
		for (int p = i + 1; p <= count - 1; p++) {
			if (num[i].step > num[p].step) {
				member ui = num[i];
				num[i] = num[p];
				num[p] = ui;
			}
		}
	}
	return count - 1;
}
void downphbfile(member* a, int all) {//保存玩家信息保存到排行榜文件,a指向结构体数组第一个元素,all表示玩家总数
	FILE* sb;//定义文件指针
	if ((sb = fopen("member.dat", "wb")) == NULL) {
		printf("File not open!");//提示打开文件失败
		return;
	}
	for (int i = 1; i <= all; i++) {
		if (fwrite(&a[i], sizeof(member), 1, sb) != 1) {//一个个写入数据
			printf("File write error");//提示写入文件失败
			return;
		}
	}
	fclose(sb);//关闭文件
}

struct xy {//记录棋子信息
	int x, y;//棋子在Chess数组中的信息
}chessxy[225];
int step;//表示棋盘上棋子总数,数组模拟栈,方便悔棋

int AS;//当前下棋方,-1表示黑方,1表示白方

int Chess[16][16];//记录棋盘标记,0表示为空,-1表示黑棋,1表示白棋

int Chessscore[16][16];//人机对战时计算各点得分

int fx[8] = { 0,1,1,1,0,-1,-1,-1 };
int fy[8] = { 1,1,0,-1,-1,-1,0,1 };//方向数组

void creatchess(int mande, int AIas) {//创建棋盘,mande表示当前模式,mande为1表示当前是人机局,AIas人机执棋色
	initgraph(qpw, qph);
	IMAGE qp_img;//定义一个图片名
	loadimage(&qp_img, "res/qp.jpg", 898, 894);//加载图片,并与qp_img绑定
	putimage(0, 0, &qp_img);//插入图片
	setbkmode(TRANSPARENT);//设置字体背景模式
	settextstyle(20, 0, "楷体");//设置字体
	settextcolor(RGB(705, 79, 79));//设置字体颜色
	outtextxy(10, 10, "提示:按下鼠标左键落子,按下鼠标右键悔棋,按下鼠标中键返回主菜单");

	settextcolor(RGB(0, 275, 70));//设置字体颜色
	if (mande == 1) {//是人机局则提示人机局
		outtextxy(630, 865, "当前为人机对战,");
		settextcolor(RGB(0, 675, 70));//设置字体颜色
		if (AIas == 1) {//人机执白棋
			outtextxy(780, 865, "人机执白棋");
		}
		else {//人机执黑棋
			outtextxy(780, 865, "人机执黑棋");
		}
	}
	else {
		outtextxy(750, 865, "当前为人人对战");
	}
	settextcolor(RGB(0, 575, 70));//设置字体颜色
	if (AS == 1) {//显示当前执子方
		outtextxy(10, 865, "执棋方:白方");
	}
	else {
		outtextxy(10, 865, "执棋方:黑方");
	}
}
void findpos(double sx, double sy, int* tx, int* ty) {//sx,sy为鼠标方位,tx,ty为在Chess数组中的方位
	double m = (sx - 38) / 58.6, n = (sy - 38) / 58.6;
	int ad = (int)(m + 0.5), ah = (int)(n + 0.5);
	*tx = ad + 1, * ty = ah + 1;
}

void init() {
	step = 0;
	memset(Chess, 0, sizeof(Chess));//棋盘清0
	AS = -1;//默认黑棋先下
}

void mango(int mande, int AIas) {//玩家走棋,mande表示是否是人机模式,AIas表示人机执棋
	MOUSEMSG on;//定义鼠标信息状态on 
	while (1) {//用户输入
		on = GetMouseMsg();//输入鼠标信息
		int a, b;
		findpos(on.x, on.y, &a, &b);
		if (on.uMsg == WM_MBUTTONDOWN) {
			closegraph();//关闭棋盘
			creat_first();
		}
		if (on.uMsg == WM_LBUTTONDOWN) {//鼠标按下左键
			if (Chess[a][b] != 0) {//坐标有子
				mciSendString("play res/wuxiao.mp3", 0, 0, 0);
				continue;
			}
			else {
				Chess[a][b] = AS;//下子
				mciSendString("play res/select.wav", 0, 0, 0);
				step++;
				AS = -AS;//换执棋方
				Drawchess(mande, AIas);//重新绘制
				chessxy[step].x = a, chessxy[step].y = b;//记录棋子信息
				break;
			}
		}
		if (on.uMsg == WM_RBUTTONDOWN && step > 0) {//鼠标按下右键悔棋
			mciSendString("play res/select.wav", 0, 0, 0);
			Chess[chessxy[step].x][chessxy[step].y] = 0;//出栈
			step--;
			AS = -AS;
			Drawchess(mande, AIas);//悔棋后绘制棋子
		}
	}
}

void AIscore(int AIas) {
	memset(Chessscore, 0, sizeof(Chessscore));//先清空得分
	for (int i = 1; i <= 15; i++) {//正方计算每个点得分
		for (int p = 1; p <= 15; p++) {
			if (Chess[i][p] == 0) {//是个空白点
				int mynum = 0, emptynum = 0;//分别为己方棋子数,空白数
				for (int ir = 0; ir < 4; ir++) {//4个方向,包括每个方向的正反方向
					for (int ip = 1; ip <= 4; ip++) {//正方向
						int tx = ip * fx[ir] + i, ty = ip * fy[ir] + p;
						if (tx > 0 && ty > 0 && ty < 16 && tx < 16 && Chess[tx][ty] != -AIas) {//不越界,不被占
							if (Chess[tx][ty] == AIas) {//连子
								mynum++;
							}
							else if (Chess[tx][ty] == 0) {//空白子
								emptynum++;
								break;
							}
						}
						else {
							break;
						}
					}
					for (int ip = 1; ip <= 4; ip++) {//正方向
						int tx = -ip * fx[ir] + i, ty = -ip * fy[ir] + p;
						if (tx > 0 && ty > 0 && ty < 16 && tx < 16 && Chess[tx][ty] != -AIas) {//不越界,不被占
							if (Chess[tx][ty] == AIas) {//连子
								mynum++;
							}
							else if (Chess[tx][ty] == 0) {//空白子
								emptynum++;
								break;
							}
						}
						else {
							break;
						}
					}
					if (mynum == 4) {//活5
						Chessscore[i][p] += 30000;
					}
					else {
						if (mynum == 3) {
							if (emptynum == 2) {//活4
								Chessscore[i][p] += 1000;
							}
							if (emptynum == 1) {//冲4
								Chessscore[i][p] += 100;
							}
						}
						if (mynum == 2) {
							if (emptynum == 2) {//活3
								Chessscore[i][p] += 100;
							}
							if (emptynum == 1) {//死3
								Chessscore[i][p] += 50;
							}
						}
						if (mynum == 1 && emptynum == 2) {//连2
							Chessscore[i][p] += 20;
						}
					}
				}
			}
		}
	}
	AIas = -AIas;
	for (int i = 1; i <= 15; i++) {//以敌方计算每个点得分
		for (int p = 1; p <= 15; p++) {
			if (Chess[i][p] == 0) {//是个空白点
				int mynum = 0, emptynum = 0;//分别为己方棋子数,空白数
				for (int ir = 0; ir < 4; ir++) {//4个方向,包括每个方向的正反方向
					for (int ip = 1; ip <= 4; ip++) {//正方向
						int tx = ip * fx[ir] + i, ty = ip * fy[ir] + p;
						if (tx > 0 && ty > 0 && ty < 16 && tx < 16 && Chess[tx][ty] != -AIas) {//不越界,不被占
							if (Chess[tx][ty] == AIas) {//连子
								mynum++;
							}
							else if (Chess[tx][ty] == 0) {//空白子
								emptynum++;
								break;
							}
						}
						else {
							break;
						}
					}
					for (int ip = 1; ip <= 4; ip++) {//正方向
						int tx = -ip * fx[ir] + i, ty = -ip * fy[ir] + p;
						if (tx > 0 && ty > 0 && ty < 16 && tx < 16 && Chess[tx][ty] != -AIas) {//不越界,不被占
							if (Chess[tx][ty] == AIas) {//连子
								mynum++;
							}
							else if (Chess[tx][ty] == 0) {//空白子
								emptynum++;
								break;
							}
						}
						else {
							break;
						}
					}
					if (mynum == 4) {//活4
						Chessscore[i][p] += 20000;
					}
					else {
						if (mynum == 3) {
							if (emptynum == 2) {//活4
								Chessscore[i][p] += 20000;
							}
							if (emptynum == 1) {//冲4
								Chessscore[i][p] += 100;
							}
						}
						if (mynum == 2) {
							if (emptynum == 2) {//活3
								Chessscore[i][p] += 100;
							}
							if (emptynum == 1) {//死3
								Chessscore[i][p] += 50;
							}
						}
						if (mynum == 1 && emptynum == 2) {//连2
							Chessscore[i][p] += 20;
						}
					}
				}
			}
		}
	}
}
void AIgo(int as, int* x, int* y) {//人机走棋,as表示人机执子颜色,返回AI选择的落子坐标
	AIscore(as);
	int max = 0, mx, my;
	if (step == 0) {//先手第一次落子
		srand((unsigned)time(NULL));//将时间设置为随机数种子
		int a = rand() % 10 + 2, b = rand() % 10 + 2;
		*x = a, * y = b;
		return;
	}
	int maxnum = 1;//若有相同权值,记录具有相同最大权值的数量
	xy temp[235];
	for (int i = 1; i <= 15; i++) {
		for (int p = 1; p <= 15; p++) {
			if (max < Chessscore[i][p]) {
				maxnum = 1;
				max = Chessscore[i][p];
				temp[maxnum].x = i;
				temp[maxnum].y = p;
				mx = i, my = p;
			}
			if (max == Chessscore[i][p]) {
				maxnum++;
				temp[maxnum].x = i;
				temp[maxnum].y = p;
			}
		}
	}
	if (maxnum > 1) {
		srand((unsigned)time(NULL));//将时间设置为随机数种子
		int swlect = rand() % maxnum;
		while (swlect == 0) {
			int y = rand();
			swlect = (y * rand() + 1) % maxnum;
		}
		mx = temp[swlect].x, my = temp[swlect].y;
	}
	*x = mx, * y = my;
}

int tempscore[16][16];
int endscore[16][16];
void dfsgo(int num, int AIas, int* unmax) {//num表示从原先棋局开始走完了的步数
	if (num == 9) {//走完5步,开始计算当前棋局中的得分最大值
		AIscore(AIas);//开始记算
		int maxnum = 1;//若有相同权值,记录具有相同最大权值的数量
		xy temp[235];
		int max = 0, mx, my;
		for (int i = 1; i <= 15; i++) {
			for (int y = 1; y <= 15; y++) {
				if (Chessscore[i][y] > max) {
					max = Chessscore[i][y];
					mx = i, my = y;
				}
			}
		}
		*unmax = max;
	}
	for (int i = 1; i <= 15; i++) {
		for (int p = 1; p <= 15; p++) {
			if (tempscore[i][p] != 0 && Chess[i][p] == 0) {//找到一个得分不为0空白点
				for (int si = 1; si <= 15; si++) {//找到另外一个得分不为0的空白点点
					for (int sp = 1; sp <= 15; sp++) {
						if (tempscore[si][sp] != 0 && Chess[si][sp] == 0) {
							Chess[i][p] = AIas, Chess[i][p] = -AIas;//模拟AI下棋和玩家下棋
							if (num == 0) {//记录该种棋局走的第一步坐标以及走该种棋局可以得到的最大分值
								int oknum;
								dfsgo(num + 1, AIas, &oknum);
								if (endscore[i][p] < oknum) {
									endscore[i][p] = oknum;
								}
							}
							else {
								dfsgo(num + 1, AIas, unmax);
							}
							Chess[i][p] = 0, Chess[i][p] = 0;
						}
					}
				}
			}
		}
	}
}
void AIdfsgo(int AIas, int* x, int* y) {
	if (step == 0) {//先手第一次落子
		srand((unsigned)time(NULL));//将时间设置为随机数种子
		int a = rand() % 10 + 2, b = rand() % 10 + 2;
		*x = a, * y = b;
		return;
	}
	//从当前棋局开始,AI走完5步之后得到各种棋局,将各种棋局棋盘中分值最大点值作为该此棋局的分值
	//然后依据各种棋局的得分找出得分最大的棋局,返回这个棋局所下的点
	AIscore(AIas);//进行评分初始化
	for (int i = 1; i <= 15; i++) {//先把初始得分地图复制到tempscore中
		for (int y = 1; y <= 15; y++) {
			tempscore[i][y] = Chessscore[i][y];
		}
	}
	memset(endscore, 0, sizeof(endscore));
	dfsgo(0, AIas, NULL);
	int max = 0, mx = 0, my = 0;
	int maxnum = 1;//若有相同权值,记录具有相同最大权值的数量
	xy temp[7235];
	for (int i = 1; i <= 15; i++) {//找走各点5步之后所能得到的最大分数的点
		for (int y = 1; y <= 15; y++) {
			if (max < endscore[i][y]) {
				max = endscore[i][y];
				mx = i, my = y;
				maxnum = 1;
			}
			if (max == endscore[i][y]) {
				temp[maxnum].x = i;
				temp[maxnum].y = y;
				maxnum++;
			}
		}
	}
	if (maxnum > 1) {
		srand((unsigned)time(NULL));//将时间设置为随机数种子
		int swlect = rand() % maxnum;
		while (swlect == 0) {
			int y = rand();
			swlect = (y * rand() + 1) % maxnum;
		}
		mx = temp[swlect].x, my = temp[swlect].y;
	}	
	*x = mx, * y = my;
}

void AIwingo(int AIas, int* x, int* y) {

}

int fs(int as, int x, int y) {//查找从此(x,y)坐标开始最大连子数
	for (int i = 0; i < 8; i++) {//查找8个方向
		int tx = x, ty = y;
		int po = 0;
		while (1) {//往一个方向延伸
			tx += fx[i], ty += fy[i];
			if (Chess[tx][ty] != as) {
				break;
			}
			po++;
			if (po == 4) {//有5个连在一起
				return po;
			}
		}
	}
	return 0;
}
int findwin(int as) {//查找五子连棋,有5子返回1
	for (int i = 1; i <= 15; i++) {
		for (int l = 1; l <= 15; l++) {
			if (Chess[l][i] == as && fs(as, l, i) == 4) {//是要查找的棋子,查找
				return 1;
			}
		}
	}
	return 0;
}

int check() {//检查胜负平局,分别返回-1表示黑子胜,1表示白子胜,0表示无胜负方或平局,6表示平局
	if (findwin(-1)) {//查看黑子是否胜利
		return -1;
	}
	if (findwin(1)) {//查看白子是否胜利
		return 1;
	}
	if (step == 225) {//棋盘全部下满表示平局
		return 6;
	}
	return 0;//以上情况都不是
}
void shenfu(int as, int mande, int AIas) {//提示胜负平局,as为-1表示黑子胜,为1表示白子胜,0表示平局,mande表示是否是人机局,AIas表示人机执棋色
	if (mande == 1) { //是人机局
		if (as == AIas) {//人机胜
			mciSendString("play res/shibai.mp3", 0, 0, 0);
			HWND tip = GetHWnd();
			int windo = MessageBox(tip, "您输给了了AI,是否继续下一局?", "胜负已分", MB_OKCANCEL);//弹出窗口,获取信息赋值给windo
			if (windo == IDOK) {
				init();//棋盘初始化
				playAI();
			}
			else {
				closegraph();//关闭棋盘
				creat_first();
			}
		}
		else {//玩家胜
			mciSendString("play res/shengfu.mp3", 0, 0, 0);
			mciSendString("play res/good.mp3", 0, 0, 0);
			HWND tip = GetHWnd();
			int windo = MessageBox(tip, "您战胜了AI,是否继续下一局?", "胜负已分", MB_OKCANCEL);//弹出窗口,获取信息赋值给windo
			if (windo == IDOK) {
				init();//棋盘初始化
				playAI();
			}
			else {
				closegraph();//关闭棋盘
				creat_first();
			}
		}
	}
	else {//不是人机局
		mciSendString("play res/shengfu.mp3", 0, 0, 0);
		mciSendString("play res/good.mp3", 0, 0, 0);
		if (as == 1) {
			HWND tip = GetHWnd();
			int windo = MessageBox(tip, "白棋胜利,是否继续下一局?", "胜负已分", MB_OKCANCEL);//弹出窗口,获取信息赋值给windo
			if (windo == IDOK) {
				init();//棋盘初始化
				playDouble();
			}
			else {
				closegraph();//关闭棋盘
				creat_first();
			}
		}
		else {
			HWND tip = GetHWnd();
			int windo = MessageBox(tip, "黑棋胜利,是否继续下一局?", "胜负已分", MB_OKCANCEL);//弹出窗口,获取信息赋值给windo
			if (windo == IDOK) {
				init();//棋盘初始化
				playDouble();
			}
			else {
				closegraph();//关闭棋盘
				creat_first();
			}
		}
	}
}
void Drawchess(int mande, int AIas) {//绘制棋子
	BeginBatchDraw();//双缓冲绘图,防止闪屏
	cleardevice();
	IMAGE qp_img;//定义一个图片名
	loadimage(&qp_img, "res/qp.jpg", 898, 894);//加载图片,并与qp_img绑定
	putimage(0, 0, &qp_img);//插入图片
	double xs = 58.6, pui = 38;//棋子相对方位,用来调整
	for (int l = 1; l <= 15; l++) {
		for (int i = 1; i <= 15; i++) {
			if (Chess[i][l] != 0) {//该坐标有棋子
				if (Chess[i][l] == -1) {//是黑子
					setfillcolor(BLACK);
					fillcircle(pui + (i - 1) * xs, pui + (l - 1) * xs, 21);
				}
				else {//白子
					setfillcolor(WHITE);
					fillcircle(pui + (i - 1) * xs, pui + (l - 1) * xs, 21);
				}
			}
		}
	}

	setbkmode(TRANSPARENT);//设置字体背景模式
	settextstyle(20, 0, "楷体");//设置字体
	settextcolor(RGB(705, 79, 79));//设置字体颜色
	outtextxy(10, 10, "提示:按下鼠标左键落子,按下鼠标右键悔棋,按下鼠标中键返回主菜单");
	settextcolor(RGB(0, 275, 70));//设置字体颜色
	if (mande == 1) {//是人机局则提示人机局
		outtextxy(630, 865, "当前为人机对战,");
		settextcolor(RGB(0, 675, 70));//设置字体颜色
		if (AIas == 1) {//人机执白棋
			outtextxy(780, 865, "人机执白棋");
		}
		else {//人机执黑棋
			outtextxy(780, 865, "人机执黑棋");
		}
	}
	else {
		outtextxy(750, 865, "当前为人人对战");
	}
	settextcolor(RGB(0, 575, 70));//设置字体颜色
	if (AS == 1) {//显示当前执子方
		outtextxy(10, 865, "执棋方:白方");
	}
	else {
		outtextxy(10, 865, "执棋方:黑方");
	}
	EndBatchDraw();
}
void playAI() {//人机模式
	char name[10];
	InputBox(name, 8, "请输入你想要的昵称", "用户注册");
	int AIas;//标记人机执棋色
	HWND tip = GetHWnd();
	int windo = MessageBox(tip, "您是否先手呢", "选择先后手", MB_OKCANCEL);//弹出窗口,获取信息赋值给windo,先手为黑棋
	if (windo == IDOK) {//玩家执黑棋,则人机执白棋
		AIas = 1;
	}
	else {
		AIas = -1;
	}
	creatchess(1, AIas);//创建棋盘
	mciSendString("play res/start.wav", 0, 0, 0);//播报开始语音

	init();//棋盘初始化

	while (1) {//游戏内循环
		int so = check();// 检查棋盘
		if (so == -1) {//黑子胜
			if (so == -AIas) {//玩家胜利
				coutall++;
				strcpy(num[coutall].name, name);
				if (AIas == 1) {//人机执白棋
					strcpy(num[coutall].qizi, "黑棋");//玩家用黑棋战胜
				}
				else {
					strcpy(num[coutall].qizi, "白棋");//玩家用白棋战胜
				}
				num[coutall].step = step;
				downphbfile(&num[1], coutall);//保存玩家信息
			}
			shenfu(-1, 1, AIas);//提示黑子胜利
			break;
		}
		if (so == 1) {//白子胜
			if (so == -AIas) {//玩家胜利
				coutall++;
				strcpy(num[coutall].name, name);
				if (AIas == 1) {//人机执白棋
					strcpy(num[coutall].qizi, "黑棋");//玩家用黑棋战胜
				}
				else {
					strcpy(num[coutall].qizi, "白棋");//玩家用白棋战胜
				}
				num[coutall].step = step;
				downphbfile(&num[1], coutall);
			}
			shenfu(1, 1, AIas);//提示白子胜利
			break;
		}
		if (AIas != AS) {//玩家下棋或悔棋
			mango(1, AIas);
		}
		else {//人机下棋
			int AX, AY;
			//AIgo(AIas, &AX, &AY);//得到人机要下子的坐标
			AIdfsgo(AIas, &AX, &AY);
			Chess[AX][AY] = AIas;//下子
			step++;
			AS = -AS;
			Drawchess(1, AIas);//重新绘制
			mciSendString("play res/select.wav", 0, 0, 0);
			chessxy[step].x = AX, chessxy[step].y = AY;
		}
	}
}
void playDouble() {//双人模式
	creatchess(0, 0);//创建棋盘
	mciSendString("play res/start.wav", 0, 0, 0);//播报开始语音

	init();//棋盘初始化

	while (1) {//游戏内循环
		int so = check();//检查棋盘
		if (so == -1) {//黑子胜
			shenfu(-1, 0, 0);//提示黑子胜利
			break;
		}
		if (so == 1) {//白子胜
			shenfu(1, 0, 0);//提示白子胜利
			break;
		}
		if (so == 6) {//平局
			shenfu(0, 0, 0);//提示平局
			break;
		}
		mango(0, 0);
	}
}

void go_ranklist() {
	coutall = openphbfile(num + 1);//打开玩家信息文件,方便排行榜操作
	initgraph(650, 938);
	IMAGE f_b_img;//定义一个图片名
	loadimage(&f_b_img, "res/phb.jpg", 650, 938);//加载图片,并与f_b_img绑定
	putimage(0, 0, &f_b_img);
	setbkmode(TRANSPARENT);//设置字体背景模式
	settextstyle(25, 0, "正体");//设置字体

	setlinestyle(PS_SOLID, 3);//设置选项边框为实线,宽度为1像素
	setfillcolor(RGB(287, 178, 6));
	setlinecolor(RED);//设置线条颜色
	fillrectangle(48, 196, 108, 226);// 边框
	settextcolor(YELLOW);//设置字体颜色
	outtextxy(53, 200, "战胜");
	setfillcolor(BLUE);
	setlinecolor(RED);//设置线条颜色
	fillrectangle(542, 196, 582, 226);// 边框
	settextcolor(YELLOW);//设置字体颜色
	outtextxy(549, 200, "AI");

	settextcolor(RGB(105, 79, 59));//设置字体颜色
	outtextxy(58, 256, "排名");
	settextcolor(RGB(105, 79, 59));//设置字体颜色
	outtextxy(196, 256, "玩家昵称");
	settextcolor(RGB(105, 79, 59));//设置字体颜色
	outtextxy(381, 256, "棋子");
	settextcolor(RGB(105, 79, 59));//设置字体颜色
	outtextxy(505, 256, "所用步数");
	setcolor(RGB(255, 0, 0));//设置线条颜色
	line(45, 285, 615, 285);
	for (int i = 1; i <= 10; i++) {//绘制10条线,已及排名
		if (i % 2 == 0) {
			setcolor(RGB(83, 60, 233));
			settextcolor(RGB(34, 216, 94));
		}
		else {
			setcolor(RGB(34, 216, 94));
			settextcolor(RGB(83, 60, 233));
		}
		line(48, 340 + (i - 1) * 60, 610, 340 + (i - 1) * 60);
		if (i <= coutall) {
			char bb[5];
			sprintf(bb, "%d", num[i].step);//将整形step转换成字符串
			outtextxy(217, 311 + (i - 1) * 60, num[i].name);
			outtextxy(382, 311 + (i - 1) * 60, num[i].qizi);
			outtextxy(520, 311 + (i - 1) * 60, bb);
		}
		else {
			outtextxy(217, 311 + (i - 1) * 60, "xxxx");
			outtextxy(382, 311 + (i - 1) * 60, "xxxx");
			outtextxy(520, 311 + (i - 1) * 60, "xxxx");
		}
		outtextxy(52, 311 + (i - 1) * 60, "第  名:");
		char bb[5];
		sprintf(bb, "%d", i);//将整形i转换成字符串
		if (i <= 3) {
			settextcolor(RED);//设置字体颜色
		}
		else {
			settextcolor(BLACK);//设置字体颜色
		}
		outtextxy(80, 311 + (i - 1) * 60, bb);
	}
	settextcolor(RED);//设置字体颜色绿色
	outtextxy(58, 891, "按鼠标右键返回主菜单");
	MOUSEMSG jk = GetMouseMsg();//定义鼠标信息状态jk
	while (1) {
		jk = GetMouseMsg();//获取鼠标信息
		if (jk.uMsg == WM_RBUTTONDOWN) {//鼠标按下左键
			closegraph();
			creat_first();
			break;
		}
	}
}

void creat_first() {//进入主界面
	coutall = openphbfile(num + 1);//打开玩家信息文件,方便排行榜操作
	initgraph(igwide, igwigh);//打开界面
	IMAGE f_b_img;//定义一个图片名
	loadimage(&f_b_img, "res/menue.jpg", 666, 664);//加载图片,并与f_b_img绑定
	putimage(0, 0, &f_b_img);//插入图片
	setlinestyle(PS_SOLID, 2);//设置选项边框为实线,宽度为1像素
	setfillcolor(RGB(187, 128, 96));
	setlinecolor(RED);//设置线条颜色
	fillrectangle(buttw, buttg, igwide - buttw, butth + buttg);
	buttg += 100;
	fillrectangle(buttw, buttg, igwide - buttw, butth + buttg);
	buttg += 110;
	fillrectangle(buttw, buttg, igwide - buttw, butth + buttg);
	buttg += 120;
	fillrectangle(buttw, buttg, igwide - buttw, butth + buttg);//设置三个主菜单选项边框
	buttg -= 330;
	setbkmode(TRANSPARENT);//设置字体背景模式
	settextstyle(50, 0, "正体");//设置字体
	settextcolor(RGB(105, 79, 59));//设置字体颜色
	outtextxy(248, 144, "排行榜");
	outtextxy(218, 240, "双人模式");
	outtextxy(218, 350, "单人模式");
	outtextxy(218, 475, "结束游戏");

	MOUSEMSG first;//定义鼠标信息状态first
	while (1) {
		first = GetMouseMsg();//输入鼠标信息
		if (first.uMsg == WM_LBUTTONDOWN) {//鼠标按下左键
			if (first.x > buttw && first.x <igwide - buttw && first.y > buttg && first.y < buttg + butth) {
				mciSendString("play res/select.wav", 0, 0, 0);
				go_ranklist();//查看排行榜
				break;
			}
			buttg += 100;
			if (first.x > buttw && first.x <igwide - buttw && first.y > buttg && first.y < buttg + butth) {
				mciSendString("play res/select.wav", 0, 0, 0);
				buttg -= 100;
				playDouble();//双人模式
				break;
			}
			buttg += 110;
			if (first.x > buttw && first.x <igwide - buttw && first.y > buttg && first.y < buttg + butth) {
				mciSendString("play res/select.wav", 0, 0, 0);
				buttg -= 210;
				playAI();//单人模式
				break;
			}
			buttg += 120;
			if (first.x > buttw && first.x <igwide - buttw && first.y > buttg && first.y < buttg + butth) {
				mciSendString("play res/select.wav", 0, 0, 0);
				buttg -= 330;
				closegraph();//结束游戏
				break;
			}
			buttg -= 330;
		}
	}
	system("pause");
}
int main() {
	mciSendString("open res/bg.mp3 alias f_b_m", 0, 0, 0);//加载音乐文件,并将其命名f_b_m
	mciSendString("play f_b_m repeat", 0, 0, 0);//重复播放音乐
	creat_first();
	closegraph();
	return 0;
}

五子棋项目C++整合资源下载:

链接:https://pan.baidu.com/s/1-0GZjZKqbuOr7c1c2nLmUQ?pwd=6766
提取码:6766

有很多不足,欢迎大佬指正

 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值