c语言写扫雷新手详解

c语言写扫雷新手详解

一、用到的知识点

1、分支语句

其中主要应用了if else语句

2、循环语句

循环需要do while 语句和for()语句还有while语句

3、二维数组

二维数组在定义的时候,行可以为不写为空,但是列必须要写,例如arr[][5]={0}

4、最好分块,使代码的功能更加独立,思维逻辑更加清楚,此程序我写了:test.c用来存放我的主函数,game.h用来定义和声明函数,还有放置头文件,然后定义了game.c来实现函数

二、思绪和代码

1、想要做出这个游戏,最起码有一个菜单让人选择是否开始游戏,因此我们需要先写出一个菜单程序,最简单的菜单数据如下:

//头文件放入game.h里面
#include<stdio.h>
//主体部分放入test.c
void menu()
{
    
    
	printf("*********************************\n");
	printf("*******     1.  play     ********\n");
	printf("*******     0.  exit     ********\n");
	printf("*********************************\n");
}

2、当我们有菜单了,我们现在就可以开始选择是否进行游戏了,也就可以开始书写我们的主函数了,写的时候需要考虑到玩家可能想玩不止一次,因此我们需要用到循环,因为最起码要玩一次,所以这里建议使用do while语句,并且要考虑到玩家可能选择错误,没有选择到play和exit,这里建议将switch语句嵌套进do while语句里面,下面实现代码:

//放入test.c里面
int main()
{
    
    
	srand((unsigned int)time(NULL));
	int input = 0;
	do
	{
    
    
		menu();
		printf("请做出你的选择:");
		scanf("%d", &input);
		switch (input)
		{
    
    
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏!\n");
			break;
		default:
			printf("输入错误,请重新输入!\n");
			break;
		}
	} while (input);
	return 0;
}

3、当我们的菜单框架做出来以后,现在开始填充游戏内容,用函数game(),这里面写选择进入游戏后的操作,运用函数进行分块,可以使你的代码更有逻辑,建议运用,下面将详细解说如何思考和书写这个game()函数:

//放入test.c里面
void game()
{
    
    
//这里进行函数的填充
}

(1)我们想要实现一个比较简单的9*9的扫雷,最起码我们需要棋盘,可以进行放雷和扫雷,因为需要两个功能,这里我们尽量让他们的功能独立起来,因此定义两个二维数组,并且我们需要考虑到,如果扫雷的时候,我们需要排查最边上的格子,如果直接进行排查,将会发生越界,因为你只定义了9*9,其实排查边上的格子的时候你已经扫描到了11*11大小的格子,因此定义的时候,我们最好定义一个11*11的棋盘,但是我们只打印9*9的出来,这样就可以防止他越界,示例代码如下:

//这样将其全部定义出来,如果以后想要修改大小的话,可以直接在此处修改
//放入game.h里面
#define ROW 11
#define COL 11
#define ROWS ROW-2
#define COLS COL-2
//填充game()函数
放入test.c里面
void game()
{
    
    
	char mine[ROW][COL] = {
    
     0 };//定义放置雷的二维数组
	char show[ROW][COL] = {
    
     0 };//定义进行扫雷的二维数组
}

(2)现在两个二维数组已经构造好了,我们需要对其进行初始化,使得我们可以更好地打印扫雷的棋盘,这里在初始化放雷棋盘的时候,将其初始化为字符’0’,这里需要注意,此处是个伏笔,为了方便后面的排雷程序,初始化代码如下:

//继续对game()函数进行填充
//放入test.c里面
void game()
{
    
    
	char mine[ROW][COL] = {
    
     0 };//定义放置雷的二维数组
	char show[ROW][COL] = {
    
     0 };//定义进行扫雷的二维数组
	Init(mine, ROW, COL, '0');//初始化雷数组,令其全部为字符‘0’,令其为‘0’,方便一会统计雷数
	Init(show, ROW, COL, '*');//初始化扫雷数组,令其全部为字符‘*’
}
//放入game.h里面
void Init(char arr[ROW][COL], int row, int col, char set);
//放入game.c里面去实现
//对雷数组还有扫雷数组进行初始化
void Init(char arr[ROW][COL],int row,int col,char set)
{
    
    
	int i = 0;
	int j = 0;
	for (i = 0; i < row; i++)
	{
    
    
		for (j = 0; j < col; j++)
		{
    
    
			arr[i][j] = set;
		}
	}
}

(3)现在我们需要将我们设计好的棋盘打印出来,注意,我们设计了11*11的,但是我们只打印9*9的,在打印的时候,我们还可以顺便检查一下,我们的放雷数组是否初始化成功,代码如下:

//放入test.c里面
void game()
{
    
    
	char mine[ROW][COL] = {
    
     0 };//定义放置雷的二维数组
	char show[ROW][COL] = {
    
     0 };//定义进行扫雷的二维数组
	Init(mine, ROW, COL, '0');//初始化雷数组,令其全部为字符‘0’,令其为‘0’,方便一会统计雷数
	//Display(mine, ROWS, COLS);//打印雷的初始化看看
	Init(show, ROW, COL, '*');//初始化扫雷数组,令其全部为字符‘*’
	Display(show, ROWS, COLS);//打印一下初始化的扫雷数组
}
//放入game.h里面
void Display(char arr[ROW][COL], int row, int col);
//放入game.c里面去实现
//打印出扫雷盘
void Display(char arr[ROW][COL], int rows, int cols)
{
    
    
	int i = 0;
	int j = 0;
	int count = 1;
	int tmp = 0;
	for (tmp = 0; tmp <= rows; tmp++)
		printf("%d ", tmp);
	printf("\n");
	for (i = 1,count=1; i <= rows; i++,count++)
	{
    
    
		printf("%d ", count);
		for (j = 1; j <= cols; j++)
		{
    
    
			printf("%c ", arr[i][j]);
		}
		printf("\n");
	}
}

(4)现在棋盘打印好了,我们需要开始给里面放置雷,为了不把代码写死,一会雷的数量,我们会通过#define来实现,在放置雷的时候我们还要考虑到此处是否已经有雷,还有雷的位置需要有随机性,这里用到了rand(),srand(),time(),因此一会需要书写头文件,代码如下:

//放入test.c里面,继续对game()进行填充
void game()
{
    
    
	char mine[ROW][COL] = {
    
     0 };//定义放置雷的二维数组
	char show[ROW][COL] = {
    
     0 };//定义进行扫雷的二维数组
	Init(mine, ROW, COL, '0');//初始化雷数组,令其全部为字符‘0’,令其为‘0’,方便一会统计雷数
	//Display(mine, ROWS, COLS);//打印雷的初始化看看
	Init(show, ROW, COL, '*');//初始化扫雷数组,令其全部为字符‘*’
	Display(show, ROWS, COLS);//打印一下初始化的扫雷数组
	assign(mine, ROWS, COLS);//布置雷
	//Display(mine, ROWS, COLS);//可以打印雷检测一下是否正确
}
//放入game.h里面
#include<stdlib.h>
#include<time.h>
void assign(char mine[ROW][COL], int rows, int cols);
#define easy 10
//放入game.c里面去实现
//开始给mine布置雷
void assign(char mine[ROW][COL], int rows, int cols)
{
    
    
	int count = 0;
//	int x = rand() % rows + 1;//不能放到外面,导致雷的位置无法更新
//	int y = rand() % cols + 1;
	while ( count < easy)
	{
    
    
		int x = rand() % rows + 1;
		int y = rand() % cols + 1;
		if (mine[x][y] == '0')
		{
    
    
			mine[x][y] = '1';//将雷定义为字符1,为了方便一会扫雷
		}
		else
			continue;
		count++;
	}
}

(5)现在棋盘有了,雷也放置好了,可以开始进行扫雷了,扫雷的时候先要判断这个位置是否已经被扫过了,如果扫过,重新扫,如果没有扫过,我们需要开始判断,这个地方是不是雷,如果是雷的话,玩家炸死,游戏结束,如果不是雷的话,则需要判断,以这个位置为中心的九宫格里面有几个雷,并且将雷的数量显示出来,这里就用到刚才初始化雷盘’0’和定义雷为’1’伏笔的时候了,‘0’的ASCII数为48,‘1’的ASCII数为49,九宫格周围的八个字符加起来再减去’0’*8,则能得到这个九宫格有几个雷,得到的是整形数字,想要将其转化为字符的话,加上’0’,然后将其打印出来,这里用到了一些ASCII的一些知识,代码如下:

//放入test.c里面,继续对game()进行填充
void game()
{
    
    
	char mine[ROW][COL] = {
    
     0 };//定义放置雷的二维数组
	char show[ROW][COL] = {
    
     0 };//定义进行扫雷的二维数组
	Init(mine, ROW, COL, '0');//初始化雷数组,令其全部为字符‘0’,令其为‘0’,方便一会统计雷数
	//Display(mine, ROWS, COLS);//打印雷的初始化看看
	Init(show, ROW, COL, '*');//初始化扫雷数组,令其全部为字符‘*’
	Display(show, ROWS, COLS);//打印一下初始化的扫雷数组
	assign(mine, ROWS, COLS);//布置雷
	//Display(mine, ROWS, COLS);//打印雷检测一下是否正确
	check_mine(mine, show, ROWS, COLS);//开始扫雷
}
//放入game.h里面
void check_mine(char mine[ROW][COL], char[ROW][COL], int rows, int cols);
//放入game.c里面去实现
//开始扫雷
void check_mine(char mine[ROW][COL], char show[ROW][COL], int rows, int cols)
{
    
    
	int x = 0;
	int y = 0;
	int count = 0;
	while (1)
	{
    
    
		printf("请输入坐标扫雷:");
		scanf("%d%d", &x, &y);
		if (show[x][y] == '*')
		{
    
    
			if (mine[x][y] == '0')
			{
    
    
				int num = mine[x - 1][y - 1] + mine[x - 1][y] + mine[x - 1][y + 1] +
					      mine[x][y - 1] + mine[x][y + 1] + mine[x + 1][y - 1] + 
						  mine[x + 1][y]+ mine[x + 1][y + 1] - '0' * 8;
				show[x][y] = num + '0';
				Display(show, ROWS, COLS);
				count++;
			}
			else
			{
    
    
				printf("不好意思你被炸死了!\n");
				Display(mine, ROWS, COLS);
				break;
			}
		}
		else
			printf("此处已经排查过!请重新排查!\n");
		if (count == rows*cols - easy)
		{
    
    
			printf("恭喜你排雷成功!\n");
			Display(show, ROWS, COLS);
			break;
		}
	}
}

三、代码完整示例如下

//test.c里面
#include"game.h"
void menu()
{
    
    
	printf("*********************************\n");
	printf("*******     1.  play     ********\n");
	printf("*******     0.  exit     ********\n");
	printf("*********************************\n");
}
void game()
{
    
    
	char mine[ROW][COL] = {
    
     0 };//定义放置雷的二维数组
	char show[ROW][COL] = {
    
     0 };//定义进行扫雷的二维数组
	Init(mine, ROW, COL, '0');//初始化雷数组,令其全部为字符‘0’,令其为‘0’,方便一会统计雷数
	//Display(mine, ROWS, COLS);//打印雷的初始化看看
	Init(show, ROW, COL, '*');//初始化扫雷数组,令其全部为字符‘*’
	Display(show, ROWS, COLS);//打印一下初始化的扫雷数组
	assign(mine, ROWS, COLS);//布置雷
	//Display(mine, ROWS, COLS);//打印雷检测一下是否正确
	check_mine(mine, show, ROWS, COLS);//开始扫雷
}
int main()
{
    
    
	srand((unsigned int)time(NULL));
	int input = 0;
	do
	{
    
    
		menu();
		printf("请做出你的选择:");
		scanf("%d", &input);
		switch (input)
		{
    
    
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏!\n");
			break;
		default:
			printf("输入错误,请重新输入!\n");
			break;
		}
	} while (input);
	return 0;
}
//game.h里面
#include<stdio.h>
#define ROW 11
#define COL 11
#define ROWS ROW-2
#define COLS COL-2
void Init(char arr[ROW][COL], int row, int col, char set);
void Display(char arr[ROW][COL], int row, int col);
#include<stdlib.h>
#include<time.h>
void assign(char mine[ROW][COL], int rows, int cols);
#define easy 10
void check_mine(char mine[ROW][COL], char[ROW][COL], int rows, int cols);
//game.c里面
#include"game1.h"
//对雷数组还有扫雷数组进行初始化
void Init(char arr[ROW][COL],int row,int col,char set)
{
    
    
	int i = 0;
	int j = 0;
	for (i = 0; i < row; i++)
	{
    
    
		for (j = 0; j < col; j++)
		{
    
    
			arr[i][j] = set;
		}
	}
}
//打印出扫雷盘
void Display(char arr[ROW][COL], int rows, int cols)
{
    
    
	int i = 0;
	int j = 0;
	int count = 1;
	int tmp = 0;
	for (tmp = 0; tmp <= rows; tmp++)
		printf("%d ", tmp);
	printf("\n");
	for (i = 1,count=1; i <= rows; i++,count++)
	{
    
    
		printf("%d ", count);
		for (j = 1; j <= cols; j++)
		{
    
    
			printf("%c ", arr[i][j]);
		}
		printf("\n");
	}
}
//开始给mine布置雷
void assign(char mine[ROW][COL], int rows, int cols)
{
    
    
	int count = 0;
//	int x = rand() % rows + 1;//不能放到外面,导致雷的位置无法更新
//	int y = rand() % cols + 1;
	while ( count < easy)
	{
    
    
		int x = rand() % rows + 1;
		int y = rand() % cols + 1;
		if (mine[x][y] == '0')
		{
    
    
			mine[x][y] = '1';
		}
		else
			continue;
		count++;
	}
}
//开始扫雷
void check_mine(char mine[ROW][COL], char show[ROW][COL], int rows, int cols)
{
    
    
	int x = 0;
	int y = 0;
	int count = 0;
	while (1)
	{
    
    
		printf("请输入坐标扫雷:");
		scanf("%d%d", &x, &y);
		if (show[x][y] == '*')
		{
    
    
			if (mine[x][y] == '0')
			{
    
    
				int num = mine[x - 1][y - 1] + mine[x - 1][y] + mine[x - 1][y + 1] +
					      mine[x][y - 1] + mine[x][y + 1] + mine[x + 1][y - 1] + 
						  mine[x + 1][y]+ mine[x + 1][y + 1] - '0' * 8;
				show[x][y] = num + '0';
				Display(show, ROWS, COLS);
				count++;
			}
			else
			{
    
    
				printf("不好意思你被炸死了!\n");
				Display(mine, ROWS, COLS);
				break;
			}
		}
		else
			printf("此处已经排查过!请重新排查!\n");
		if (count == rows*cols - easy)
		{
    
    
			printf("恭喜你排雷成功!\n");
			Display(show, ROWS, COLS);
			break;
		}
	}
}

四、优化

代码写出来了,这是最简单的一个扫雷,还可以进行好多优化,例如插旗,拔旗,标记之类的,希望读者可以发散性的思考,改进,优化,相信你可以的!

猜你喜欢

转载自blog.csdn.net/yunhaogame/article/details/108633913