• C语言新手写扫雷源代码


    今天发布源代码,由于写在一个文件里非常乱,所以分三个文件写

    绘图和鼠标函数graph.h

    /*绘图与鼠标相关函数*/
    
    #include<graphics.h>
    #include <easyx.h>
    
    void DrawEmpty(int, int, int, int);//初始化空格子界面的函数
    void DrawSmile(void);//画笑脸的函数
    void DrawRedFlag(int, int);//右键画红旗的函数
    int MouseX, MouseY;//鼠标的x,y坐标
    MOUSEMSG m;//鼠标结构变量,接受鼠标消息
    
    void DrawSmile(void)
    {
    	setfillstyle(BS_SOLID);
    	setfillcolor(YELLOW);
    	fillellipse(90, 5, 110, 25);//绘制椭圆(笑脸)函数,参数为椭圆外切矩形的左上右下角坐标
    	setfillstyle(BS_SOLID);
    	setfillcolor(BLACK);//画眼睛
    	fillellipse(93, 13, 97, 17);
    	fillellipse(103, 13, 107, 17);
    	bar(97, 20, 103, 21);//画嘴巴
    }
    
    void DrawRedFlag(int i, int j)
    {
    	setfillstyle(BS_SOLID);
    	setfillcolor(RED);
    	bar(8 + j * 20, 35 + i * 20, 8 + j * 20 + 5, 35 + i * 20 + 5);
    	setcolor(BLACK);
    	line(8 + j * 20, 35 + i * 20, 8 + j * 20, 35 + i * 20 + 10);
    }
    
    void DrawEmpty(int i, int j, int mode, int color) //画出16*16的小格
    {
    	setfillstyle(BS_SOLID);
    	setfillcolor(color);
    	if (mode == 0)
    	{
    		bar(10 + j * 20 - 8, 40 + i * 20 - 8, 10 + j * 20 + 8, 40 + i * 20 + 8);
    	}
    	else if (mode == 1)
    	{
    		bar(10 + j * 20 - 7, 40 + i * 20 - 7, 10 + j * 20 + 7, 40 + i * 20 + 7);
    	}
    }
    
    void MouseGetXY(void)//获得鼠标的位置
    {
    	m = GetMouseMsg();
    	MouseX = m.x;
    	MouseY = m.y;
    }

    辅助计算函数auxiliary.h

    /*辅助函数*/
    
    #include <conio.h>  //_kbhit()
    
    
    struct
    {
    	int num;//格子当前状态,1表示有雷,0表示无雷或已经显示数字
    	int roundnum;//统计格子周围的雷数
    	int flag;//右键按下显示红旗标志,0表示没有,1表示有
    }Mine[10][10];
    
    int mineNUM;//统计处理过的格子数
    TCHAR randmineNUM[100];//显示数字的字符串
    
    /*统计每个格子周围的雷数*/
    
    int MineStatistics(int i, int j)
    {
    	int nNUM = 0;
    	if (i == 0 && j == 0)//左上角格子的统计
    	{
    		if (Mine[0][1].num == 1)
    			nNUM++;
    		if (Mine[1][0].num == 1)
    			nNUM++;
    		if (Mine[1][1].num == 1)
    			nNUM++;
    	}
    	else
    	if (i == 0 && j == 9)//右上角格子的统计
    	{
    		if (Mine[0][8].num == 1)
    			nNUM++;
    		if (Mine[1][9].num == 1)
    			nNUM++;
    		if (Mine[1][8].num == 1)
    			nNUM++;
    	}
    	else
    	if (i == 9 && j == 0)//左下角格子的统计
    	{
    		if (Mine[8][0].num == 1)
    			nNUM++;
    		if (Mine[9][1].num == 1)
    			nNUM++;
    		if (Mine[8][1].num == 1)
    			nNUM++;
    	}
    	else
    	if (i == 9 && j == 9)//右下角格子的统计
    	{
    		if (Mine[9][8].num == 1)
    			nNUM++;
    		if (Mine[8][9].num == 1)
    			nNUM++;
    		if (Mine[8][8].num == 1)
    			nNUM++;
    	}
    	else if (j == 0)//左边第一列格子的统计
    	{
    		if (Mine[i][j + 1].num == 1)
    			nNUM++;
    		if (Mine[i + 1][j].num == 1)
    			nNUM++;
    		if (Mine[i - 1][j].num == 1)
    			nNUM++;
    		if (Mine[i - 1][j + 1].num == 1)
    			nNUM++;
    		if (Mine[i + 1][j + 1].num == 1)
    			nNUM++;
    	}
    	else if (j == 9)//右边第一列格子的统计
    	{
    		if (Mine[i][j - 1].num == 1)
    			nNUM++;
    		if (Mine[i + 1][j].num == 1)
    			nNUM++;
    		if (Mine[i - 1][j].num == 1)
    			nNUM++;
    		if (Mine[i - 1][j - 1].num == 1)
    			nNUM++;
    		if (Mine[i + 1][j - 1].num == 1)
    			nNUM++;
    	}
    	else if (i == 0)//第一行格子的统计
    	{
    		if (Mine[i + 1][j].num == 1)
    			nNUM++;
    		if (Mine[i][j - 1].num == 1)
    			nNUM++;
    		if (Mine[i][j + 1].num == 1)
    			nNUM++;
    		if (Mine[i + 1][j - 1].num == 1)
    			nNUM++;
    		if (Mine[i + 1][j + 1].num == 1)
    			nNUM++;
    	}
    	else if (i == 9)//最后一行格子的统计
    	{
    		if (Mine[i - 1][j].num == 1)
    			nNUM++;
    		if (Mine[i][j - 1].num == 1)
    			nNUM++;
    		if (Mine[i][j + 1].num == 1)
    			nNUM++;
    		if (Mine[i - 1][j - 1].num == 1)
    			nNUM++;
    		if (Mine[i - 1][j + 1].num == 1)
    			nNUM++;
    	}
    	else//普通格子的统计
    	{
    		if (Mine[i - 1][j].num == 1)
    			nNUM++;
    		if (Mine[i - 1][j + 1].num == 1)
    			nNUM++;
    		if (Mine[i][j + 1].num == 1)
    			nNUM++;
    		if (Mine[i + 1][j + 1].num == 1)
    			nNUM++;
    		if (Mine[i + 1][j].num == 1)
    			nNUM++;
    		if (Mine[i + 1][j - 1].num == 1)
    			nNUM++;
    		if (Mine[i][j - 1].num == 1)
    			nNUM++;
    		if (Mine[i - 1][j - 1].num == 1)
    			nNUM++;
    	}
    	return nNUM;//把格子周围一共有多少雷数的统计结果返回
    }
    
    
    void ShowWhite(int i, int j)//显示无雷区的空白部分
    {
    	if (Mine[i][j].flag == 1 || Mine[i][j].num == 0)//如果有红旗或该格处理过就不对该格进行任何判断
    		return;
    	mineNUM--;//显示过数字或者空格的格子就表示多处理了一个格子,当所有格子都处理过了表示胜利
    	if (Mine[i][j].roundnum == 0 && Mine[i][j].num != 1)//显示空格
    	{
    		DrawEmpty(i, j, 1, WHITE);
    		Mine[i][j].num = 0;
    	}
    	else
    	if (Mine[i][j].roundnum != 0)//输出雷数
    	{
    		DrawEmpty(i, j, 1, WHITE);
    		_stprintf_s(randmineNUM, _T("%d"), Mine[i][j].roundnum);
    		setcolor(RED);
    		outtextxy(6 + j * 20, 32 + i * 20, randmineNUM);
    		Mine[i][j].num = 0;//已经输出雷数的格子用0表示已经用过这个格子
    		return;
    	}
    
    	/*8个方向递归显示所有的空白格子*/
    	if (i != 0 && Mine[i - 1][j].num != 1)
    		ShowWhite(i - 1, j);
    	if (i != 0 && j != 9 && Mine[i - 1][j + 1].num != 1)
    		ShowWhite(i - 1, j + 1);
    	if (j != 9 && Mine[i][j + 1].num != 1)
    		ShowWhite(i, j + 1);
    	if (j != 9 && i != 9 && Mine[i + 1][j + 1].num != 1)
    		ShowWhite(i + 1, j + 1);
    	if (i != 9 && Mine[i + 1][j].num != 1)
    		ShowWhite(i + 1, j);
    	if (i != 9 && j != 0 && Mine[i + 1][j - 1].num != 1)
    		ShowWhite(i + 1, j - 1);
    	if (j != 0 && Mine[i][j - 1].num != 1)
    		ShowWhite(i, j - 1);
    	if (i != 0 && j != 0 && Mine[i - 1][j - 1].num != 1)
    		ShowWhite(i - 1, j - 1);
    }

    主函数main.cpp

    #include<stdio.h>
    #include"graph.h"
    #include"auxiliary.h"
    #include<stdlib.h> //rand(),srand()
    #include<time.h>   //srand((unsigned)time(NULL))
    
    void Game(void);//游戏主程序
    void GameBegin(void);//游戏开始
    void GamePlay(void);//游戏执行过程
    void GameOver(void);//游戏结束
    void GameWin(void);//游戏胜利
    
    int PLAY = 0;//是否第一次玩游戏的标志
    int FLAG = 1;//游戏失败后是否重新开始的标志
    int AGAIN = 0;//游戏中途重新开始的标志
    
    int main(void)
    {
    	initgraph(200, 230, SHOWCONSOLE);//初始化游戏界面和大小
    	Game();//运行游戏
    	closegraph();//关闭图形界面
    }
    
    
    
    void Game(void)
    {
    	while (1)
    	{
    		if (FLAG == 1)
    		{
    			GameBegin();//绘制出游戏界面并判断是否玩过和重新开始
    			GamePlay();//游戏过程的函数
    			if (AGAIN == 1)
    			{
    				AGAIN = 0;
    				continue;
    			}
    		}
    		FLAG = 0;
    		if (m.uMsg == WM_LBUTTONDOWN)//鼠标左键按下事件
    		{
    			MouseGetXY();
    			if (MouseX > 90 && MouseX<110 && MouseY>5 && MouseY < 25)
    			{
    				FLAG = 1;
    				continue;
    			}
    		}
    		if (_kbhit())//判断有按键退出
    		{
    			break;
    		}
    	}
    }
    
    void GameBegin(void)
    {
    	int i, j;
    	cleardevice();
    	PLAY = 1;
    	mineNUM = 0;
    	setfillstyle(BS_SOLID);//此处用法和TC不同
    	setfillcolor(WHITE);
    	bar(0, 0, 200, 230); //设置背景区域
    	for (i = 0; i < 10; i++) //绘制每个雷区(小格)
    	{
    		for (j = 0; j < 10; j++)
    		{
    			DrawEmpty(i, j, 0, LIGHTGRAY);
    		}
    	}
    	DrawSmile();//画出中间的笑脸
    	srand((unsigned)time(NULL));//根据时间给随机数不同的种子数
    	for (i = 0; i < 10; i++)
    	{
    		for (j = 0; j < 10; j++)
    		{
    			
    			Mine[i][j].num = rand() % 8;//随机数产生范围0-7
    			
    			if (Mine[i][j].num == 1)
    			{
    				mineNUM++;
    			}
    			else
    			{
    				Mine[i][j].num = 2;
    			}
    			printf("%3d", Mine[i][j].num);
    			Mine[i][j].flag = 0;
    		}
    		printf("
    ");
    		_stprintf_s(randmineNUM, _T("%d"), mineNUM);//将minrNUM转换成字符串类型
    		setbkcolor(WHITE);
    		setcolor(RED);
    		settextstyle(16, 0, _T("0"));
    		outtextxy(2, 2, randmineNUM);
    		
    	}  mineNUM = 100 - mineNUM;
    }
    
    void GamePlay(void)/*游戏过程*/
    {
    	int i, j, Num = 0;/*Num用来接收统计函数返回一个格子周围有多少地雷*/
    	for (i = 0; i < 10; i++)
    	for (j = 0; j<10; j++)
    		Mine[i][j].roundnum = MineStatistics(i, j);/*统计每个格子周围有多少地雷*/
    	while (!_kbhit())
    	{
    		m = GetMouseMsg();
    		switch (m.uMsg)
    		{
    		case WM_LBUTTONDOWN:
    		{
    							   MouseGetXY();
    							   if (MouseX>90 && MouseX<110 && MouseY>5 && MouseY<25)/*重新来*/
    							   {
    								   MessageBox(NULL, TEXT("重新开始成功"), TEXT("YES"), MB_OK);
    								   AGAIN = 1;
    								   return;
    							   }
    							   if (MouseX>0 && MouseX<200 && MouseY>30 && MouseY < 230)/*当前鼠标位置在格子范围内*/
    							   {
    								   j = (MouseX) / 20;/*x坐标*/
    								   i = (MouseY - 30) / 20;/*y坐标*/
    								   if (Mine[i][j].flag == 1)/*如果格子有红旗则左键无效*/
    									   continue;
    								   if (Mine[i][j].num != 0)/*如果格子没有处理过*/
    								   {
    									   if (Mine[i][j].num == 1)/*鼠标按下的格子是地雷*/
    									   {
    										   GameOver();/*游戏失败*/
    										   break;
    									   }
    									   else/*鼠标按下的格子不是地雷*/
    									   {
    										   Num = MineStatistics(i, j);
    										   if (Num == 0)/*周围没地雷就用递归算法来显示空白格子*/
    											   ShowWhite(i, j);
    										   else/*按下格子周围有地雷*/
    										   {
    											   _stprintf_s(randmineNUM, _T("%d"), Num);/*输出当前格子周围的雷数*/
    											   DrawEmpty(i, j, 1, WHITE);
    											   setcolor(RED);
    											   outtextxy(6 + j * 20, 32 + i * 20, randmineNUM);
    											   mineNUM--;
    										   }
    										   Mine[i][j].num = 0;/*点过的格子周围雷数的数字变为0表示这个格子已经用过*/
    										   if (mineNUM < 1)/*胜利了*/
    										   {
    											   GameWin();
    											   break;
    										   }
    									   }
    								   }
    							   }
    		}
    		case WM_RBUTTONDOWN:
    		{
    							   MouseGetXY();
    							   if (MouseX > 0 && MouseX<200 && MouseY>30 && MouseY < 230)/*当前鼠标位置在格子范围内*/
    							   {
    								   j = (MouseX) / 20;/*x坐标*/
    								   i = (MouseY - 30) / 20;/*y坐标*/
    								   //MessageBox(NULL, TEXT("右键测试"), TEXT("YES"), MB_OK);
    								   if (Mine[i][j].flag == 0 && Mine[i][j].num != 0)/*本来没红旗现在显示红旗*/
    								   {
    									   DrawRedFlag(i, j);
    									   Mine[i][j].flag = 1;
    								   }
    								   else
    								   if (Mine[i][j].flag == 1)/*有红旗标志再按右键就红旗消失*/
    								   {
    									   DrawEmpty(i, j, 0, LIGHTGRAY);
    									   Mine[i][j].flag = 0;
    								   }
    							   }
    		}
    		}
    	}
    }
    
    
    
    void GameOver(void)
    {
    	int i, j;
    	for (i = 0; i < 10; i++)
    	{
    		for (j = 0; j < 10; j++)
    		{
    			if (Mine[i][j].num == 1)//显示所有地雷
    			{
    				DrawEmpty(i, j, 0, WHITE);
    				setfillstyle(BS_SOLID);
    				setfillcolor(RED);
    				fillellipse(3 + j * 20, 33 + i * 20, 17 + j * 20, 47 + i * 20);	
    				setbkcolor(WHITE);
    				setcolor(RED);
    				settextstyle(16, 0, _T("宋体"));
    				outtextxy(2, 2, _T("输了请重来"));
    			}
    		}
    	}
    }
    
    void GameWin(void)
    {
    	setbkcolor(WHITE);
    	setcolor(RED);
    	settextstyle(16, 0, _T("宋体"));
    	outtextxy(2, 2, _T("你赢了"));
    }
    
    
    更多功能正在完善,To be continued!!
  • 相关阅读:
    「USACO 2020 US Open Platinum」Exercise
    Equilateral Triangles
    [USACO 2020 February Platinum]Help Yourself
    「ICPC World Finals 2019」美丽的桥梁
    「ICPC World Finals 2019 何以伊名始
    COCI20162017 Contest#6 F
    COCI2016/2017 Contest#3 F Meksikanac
    TopCoder SRM 570 Div1 CurvyonRails
    COCI2016-2017 Contest#2 F
    UOJ Round Good Bye JiHai D. 新年的追逐战
  • 原文地址:https://www.cnblogs.com/acgpiano/p/3987655.html
Copyright © 2020-2023  润新知