利用EasyX图形库实现五子棋程序(C语言课程设计)C语言入门 言简意赅

废话不多说,直接按实验报告格式来。

一、 实验目的

(1)实现利用计算机评判两个人五子棋比赛游戏。
(2)用C语言提供的图形库函数实现绘制五子棋棋盘。
(3)实现五子棋规则评判算法。

二、 实验内容

五子棋对战游戏设计

三、 分析与设计

(1)编写函数void GameInit(),它的功能是:initgraph(500,440)函数用来创建一个500*440的窗口,loadimage(NULL,L"Background1.jpg")函数用来添加文件名为Background1的背景图片, setlinecolor(BLACK)函数设置棋盘线条颜色为黑色,setlinestyle(PS_SOLID,2)作用为设置线条的粗细,line()函数用来画出棋盘,settextcolor(BLACK)函数设置提示字体为黑色,setbkmode(0)函数将字体背景设置成全透明,outtextxy()函数用来显示所要在游戏界面显示的字体。

(2)编写函数int playChess(void),它的功能是:

	① 变量Mouse利用GetMouseMsg()函数来获取鼠标点击信息,变量Key利用GetAsyncKeyState(VK_ESCAPE)函数来判断Esc按键是否按下。
	② 若Key小于0,代表Esc按键按下,弹出消息提示窗口,可选择是否退出。
	③ Mouse.x和Mouse.y为鼠标左键点击处的x轴和y轴的坐标点,将所有棋盘交点进行遍历,若鼠标点击在某一点半径为11的圆内,那么将该点坐标x,y记下,并将其二维数组号a,b进行储存。
	④ 用Mouse.uMsg判断鼠标左键是否按下,若二维数组board判断不为0,代表该处已下棋子,弹出提示窗口,点击确定键可以继续游戏。
	⑤ 利用flag变量对当前下的棋子色号进行判断,flag对2取余为0则下黑棋,否则下白棋,并将二维数组board进行赋值,1为黑棋,2为白棋。当flag大于等于400时,弹出窗口,提示平局。
	⑥ 利用JudgeWin()函数进行判断黑棋或白棋胜利,当有玩家胜利时,JudgeWin()函数的返回值为1,在此时flag对21取余为2是黑棋胜利,否则白棋胜利,并提示是否重新开始游戏。

(3)编写函数int JudgeWin(int a,int b),它的功能是:t的值为2 - flag % 2用来判断当前下棋者的棋子颜色,
① 以x轴ContLimit(a - 4) - ContLimit(a + 4),开始检测连续点,若连续点>=5,则判定该玩家胜利。
② 以y轴a不变,ContLimit(b - 4) - ContLimit(b + 4),开始检测连续点,若连续点>=5,则判定该玩家胜利。
③ 以y = x轴,(a - 4) - (a + 4),(b - 4) - (b + 4),开始检测连续点,若连续点>=5,则判定该玩家胜利。
④ 以y = -x轴,(a - 4) - (a + 4),(b + 4) - (b - 4),开始检测连续点,若连续点>=5,则判定该玩家胜利。

(4)函数int ContLimit(int n),它的功能是用来限制a或b的值在0 – 20之间,不超出二维数组board的存储范围。

四、 代码设计


void GameInit()
{
    
    
	//利用图形库创建一个窗口
	initgraph(500,440);

	//添加背景图片,引号前加L是因为要将格式改成多字节字符集
	loadimage(NULL,L"Background1.jpg"); 


	setlinecolor(BLACK);     //将棋盘线条颜色改为黑色
	setlinestyle(PS_SOLID,2);//将线条加粗


	//绘制棋盘
	line(21,21,21+399,21);                 //横轴
	for(int i=1;i<=20;i++)
	{
    
    
	  line(i*21,21,i*21,399+21);           //纵轴
	  line(21,21+i*21,21+399,21+i*21);     //横轴
	}

	settextcolor(BLACK);   //将背景字体设置为黑色
	setbkmode(0);          //将背景字体设置透明
    
	/*显示下棋方*/
	outtextxy(435,50,L"玩家1:");    //图形库文字函数(x,y,"显示字符")
	outtextxy(465,70,L"黑棋");
	outtextxy(435,120,L"玩家2:");
	outtextxy(465,140,L"白棋");

	outtextxy(435,220,L"Esc:");     //
	outtextxy(435,240,L"退出游戏"); //
}


int playChess(void)      //鼠标下棋函数
{
    
    
	//鼠标右键点击
	MOUSEMSG Mouse;  //鼠标结构体变量


	/*a,b为二维数组号,x,y为当前鼠标点击的坐标*/
	int a = 0;
	int b = 0;
	int x = 0;
	int y = 0;
	HWND hwnd;       //窗口句柄
    hwnd = GetHWnd();//窗口置前
	int ret = 0;     //判断游戏是否结束标志
	int KeyRet = 0;  //键盘判断是否退出游戏
	int Key = 0;     //用作键盘热键判断的变量

	while(1)
	{
    
    
	   Mouse = GetMouseMsg();  //获取一个鼠标消息

	   Key = GetAsyncKeyState(VK_ESCAPE);//获取Esc键状态,若按下返回-127或-128


	   if(Key<0)               //判断获取键盘的信息,若键盘按下Esc,Key值小于0,则退出游戏
	   {
    
    
		    KeyRet = MessageBox(hwnd,L"是否想退出游戏?",L"提示",MB_YESNO|MB_ICONINFORMATION);  //MB_YESNO显示选项,MB_ICONINFORMATION为提示字前方图标
			if(KeyRet==IDYES)   //判断是否想重新开始一局游戏
			{
    
    
				 exit(0);       //退出程序
			}
	   }

	   //下棋时鼠标点击横纵轴交点,用绝对值将点击的x,y坐标值取整,使鼠标点击规定的棋盘位置(向右向下偏移1格)
	   for(int i = 1;i<21; i++)
	   {
    
    
	   	  for(int j = 1;j<21; j++)
	   	  {
    
    
	   		 if(abs(Mouse.x-i*21)<11&&abs(Mouse.y-j*21)<11)  //将点击的范围内的值取整
	   		 {
    
     
	   			 a = i;    //行列号
	   		 	 b = j;
	   			 x = i*21; //坐标
	   			 y = j*21;
	   		 }
	   	  }
	   }

	 

		if(Mouse.uMsg == WM_LBUTTONDOWN) //判断当前鼠标左键是否按下
		{
    
    
			if(board[a][b]!=0)      //有棋子
			{
    
    
				MessageBox(hwnd,L"此处已有棋子,请重新选择下棋点",L"五子棋",MB_OK);  //MB_OK为确定键
			    //退出循环
				continue;
			}
			if(flag % 2==0)         //取余
			{
    
    
			   setfillcolor(BLACK); //棋子颜色设置黑色
			   solidcircle(x,y,10); //画黑色棋子
			   board[a][b] = 1;     //给数组赋值黑棋色号
			}
			else
			{
    
    
			   setfillcolor(WHITE); //棋子颜色设置白色
			   solidcircle(x,y,10); //画白色棋子
			   board[a][b] = 2;     //给数组赋值白棋色号
			}		    
			flag++;                 //下棋手判断

			if(flag>=400)           //当棋盘下满时,平局。(0 - 399)
			{
    
    
				MessageBox(hwnd,L"本局平局",L"游戏结束",MB_OK);  //MB_OK为确定键
			    if(ret==IDYES)   //判断是否想重新开始一局游戏
			   {
    
    
				   flag = 0;                      //用来记录轮到哪个人下棋
				   memset(board,0,sizeof(board)); //清空数组
				  break;
			   }
			   else              //不重新开始,退出程序
			   {
    
    
				  exit(0);       //退出程序
			   }
			}
		}

		if(JudgeWin(a,b))        //找到了五子连成一条线
		{
    
    
			if(flag % 2 ==1)
			{
    
    
				MessageBox(hwnd,L"玩家1(黑棋)胜利",L"游戏结束",MB_OK);  //MB_OK为确定键
			}
			else
			{
    
    
				MessageBox(hwnd,L"玩家2(白棋)胜利",L"游戏结束",MB_OK);  //MB_OK为确定键
			}

             ret = MessageBox(hwnd,L"是否想重新开始一局游戏?",L"提示",MB_YESNO|MB_ICONINFORMATION);  //MB_YESNO显示选项,MB_ICONINFORMATION为提示字前方图标
			 
			 if(ret==IDYES)   //判断是否想重新开始一局游戏
			 {
    
    
				  flag = 0;                      //用来记录轮到哪个人下棋
				  memset(board,0,sizeof(board)); //清空数组
				  break;
			 }
			 else            //不重新开始,退出程序
			 {
    
    
				  exit(0);   //退出程序
			 }
		}
	}

  return 0;
}


//判断输赢
int JudgeWin(int a,int b)
{
    
    
	/*
	   算法逻辑:以当前下棋点为原点,
	   1.以x轴(a - 4) - (a + 4),开始检测连续点,若连续点>=5,则判定win
	   2.以y轴a不变,(b - 4) - (b + 4),开始检测连续点,若连续点>=5,则判定win
	   3.以y = x轴,(a - 4) - (a + 4),(b - 4) - (b + 4),开始检测连续点,若连续点>=5,则判定win
	   4.以y = -x轴,(a - 4) - (a + 4),(b + 4) - (b - 4),开始检测连续点,若连续点>=5,则判定win
	
	*/
	int i = 0;
	int j = 0;
	int Cont_i = 0;          //连续棋子数

	int t = 2 - flag % 2;    //判定此次所下棋子色号
	//x轴判断
	for(i = ContLimit(a - 4);i <= ContLimit(a + 4);i++) //i值范围:(a - 4)至(a + 4)
	{
    
    
		j = b;
		if(board[i][j] != t) //若不是当前下的棋子色号
		{
    
    
			Cont_i = 0;      //连续棋子数清零
		}
		else if(board[i][j] == t) //若是当前下的棋子色号
		{
    
    
			Cont_i+=1;
		}
        
		if(Cont_i>=5)        //若连续棋子数大于等于5
		{
    
    
			return 1;        //返回1,判定胜利
		}
	}

	Cont_i = 0;              //x轴判定未胜利,连续棋子数清零,进行y轴判定

	//y轴判断
	for(j = ContLimit(b - 4);j <= ContLimit(b + 4);j++) //j值范围:(b - 4)至(b + 4)
	{
    
    
		i = a;

		if(board[i][j] != t) //若不是当前下的棋子色号
		{
    
    
			Cont_i = 0;      //连续棋子数清零
		}
		else if(board[i][j] == t) //若是当前下的棋子色号
		{
    
    
			Cont_i+=1;
		}
        
		if(Cont_i>=5)        //若连续棋子数大于等于5
		{
    
    
			return 1;        //返回1,判定胜利
		}
	}

	Cont_i = 0;              //x轴判定未胜利,连续棋子数清零,进行y轴判定

	//y = x判断
	for(i = ContLimit(a - 4),j = ContLimit(b - 4);i <= ContLimit(a + 4) && j <= (b + 4);i++,j++) //i值范围:(a - 4)至(a + 4),j值范围:(b - 4)至(b + 4)
	{
    
    
		//i = a;

		if(board[i][j] != t) //若不是当前下的棋子色号
		{
    
    
			Cont_i = 0;      //连续棋子数清零
		}
		else if(board[i][j] == t) //若是当前下的棋子色号
		{
    
    
			Cont_i+=1;
		}
        
		if(Cont_i>=5)        //若连续棋子数大于等于5
		{
    
    
			return 1;        //返回1,判定胜利
		}
	}

	Cont_i = 0;              //x轴判定未胜利,连续棋子数清零,进行y轴判定

	//y = -x判断
	for(i = ContLimit(a - 4),j = ContLimit(b + 4);i <= ContLimit(a + 4) && j >= ContLimit(b - 4);i++,j--) //i值范围:(a - 4)至(a + 4),j值范围:(b + 4)至(b - 4)
	{
    
    
		//i = a;

		if(board[i][j] != t) //若不是当前下的棋子色号
		{
    
    
			Cont_i = 0;      //连续棋子数清零
		}
		else if(board[i][j] == t) //若是当前下的棋子色号
		{
    
    
			Cont_i+=1;
		}
        
		if(Cont_i>=5)        //若连续棋子数大于等于5
		{
    
    
			return 1;        //返回1,判定胜利
		}
	}

	return 0;

}



int ContLimit(int n)       //用来限制二维数组a,b的值 其范围在1 - 20
{
    
    
	if(n>20)               //若输入数据大于20
	{
    
    
		return 20;         //返回20
	}
	else if(n<0)           //若输入数据小于0
	{
    
    
		return 0;          //返回0
	}
	else                   //若不满足以上条件,返回原值
	{
    
    
		return n;
	}

	return n;
}

五、运行结果

演示效果

这里只提供关键代码,图形库自行百度搭建,十分简单,如需源码,点击以下链接进行下载。

五子棋源码链接

希望各位读者细心阅读本文,理解之后,在进行代码的编写会非常轻松,自己编程的过程很痛苦,但是所收获的内容是十分丰富的,本人能力有限,若有错误,请评论区留言,及时改正。

猜你喜欢

转载自blog.csdn.net/weixin_44549777/article/details/122471399