扫雷游戏(C语言)

扫雷:

游戏简述:

1、在一个棋盘中的任意位置,随机埋上一个雷,这个雷的数量是固定的,

2、然后让用户去选择位置排雷,

        若选择的该位置没有雷,则在该位置显示周边一圈位置中雷的个数,
        若选择的位置有雷,则就被炸死了,游戏结束

        若选择的位置没有雷,并且将所有没有雷的位置都找出来,则玩家排雷成功,游戏结束

逐步实现:

1、打印菜单

我们首先要有一个菜单供用户选择,是否开始游戏 

选择 1 开始游戏,选择 0 结束游戏

实现:我们首先创建一个整型变量,让用户给变量输入值,

           若 输入1 则游戏开始,

           若  输入0  则退出游戏,

           若 输入其它数字 则提醒用户 并让用户重新输入

为了实现功能在这里我们采用 do  while();  循环,让用户至少进行一次选择

再用 switch case 语句 判断所输入的数字是否合法

若合法则进入游戏,若不合法则重新让用户输入(选择)

代码如下:

#include 
void Mune(void)
{
	printf("*****************************\n");
	printf("*********  1、play  *********\n");
	printf("*********  0、exit  *********\n");
	printf("*****************************\n");
}

void Text(void)
{
	int input = 0;//封装用户的输入
	//运用do while 至少执行一次
	do {
        //游戏菜单
	    Mune();
		printf("请选择->:");
		scanf("%d", &input);
		//用switch语句判断
		switch (input)
		{
		case 1:
			//进入游戏
			Games();
			break;
		case 0:
			printf("退出成功\n");
			break;
		default:
			printf("输入无效,请重新选择\n");
			break;
		}
	} while (input);//当变量的值为0时结束循环
}

int main()
{
	//扫雷游戏
	//游戏测试
	Text();
	return 0;
}

2、创建棋盘

1、创建棋盘1

假设我们创建一个 9 行 9 列 的棋盘

因为后期在玩家排雷的过程中,要在玩家选择的位置显示周边雷的个数,为了更方便的显示该位置周边一圈雷的个数  所以我们在创建棋盘的时候在本来用到的棋盘上的行和列分别加上2进行创建棋盘

也就是创建一个 11 行 11 列的棋盘

2、创建棋盘2

为了给原来的棋盘加密,我们再创建一个跟原来棋盘一样大的新棋盘,供用户扫雷

代码如下:

#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
//进入游戏
void Games(void)
{
	//创建棋盘1
	char encychessboard[ROWS][COLS] = { 0 };
	//创建棋盘2
	char chessboard[ROWS][COLS] = { 0 };
}

3、初始化棋盘

我们自行规定:’0‘ 表示没有雷 ’1‘ 表示雷 

将 encychessboard(棋盘1)全部初始化为 ’0‘

我们让用户看到的是棋盘2

要将棋盘2 进行加密所以将棋盘2全部初始化为 ’*‘

代码如下:

//初始化棋盘
//传行、传列、传要初始化成啥字符
void intit_board(char board[ROWS][COLS], int rows, int cols, char c)
{
	int i = 0;
	for (i = 0; i < rows; i++)
	{
		int j = 0;
		for (j = 0; j < cols; j++)
		{
			board[i][j] = c;
		}
	}
}

//进入游戏
void Games(void)
{
	//创建棋盘1
	char encychessboard[ROWS][COLS] = { 0 };
	//创建棋盘2
	char chessboard[ROWS][COLS] = { 0 };

	//初始化棋盘1
	init_board(encychessboard, ROWS, COLS, '0');
	//初始化棋盘2
	init_board(chessboard, ROWS, COLS, '*');
}

4、打印棋盘

我们在打印棋盘的时候只打印我们所用到的棋盘大小,也就是原先的假设的 9 行 9 列

只让用户在原先的行和列中操作,打印的时候我们只让用户看到棋盘2,因为棋盘2全是’*‘

让用户按照棋盘2 进行操作!

在打印的同时将棋盘的行和列的序号也打印出来 以供用户按坐标选择

代码入下:

//打印棋盘
//我们只打印最初设置的棋盘大小
void print_board(char board[ROWS][COLS], int row, int col)
{
	printf("-------------棋盘------------\n");
	int i = 0;
	int j = 0;
	//打印列号
	printf(" ");
	for (j = 1; j <= col; j++)
	{
		printf("  %d", j);
	}
	printf("\n");
	for (i = 1; i <= row; i++)
	{
		//打印行号
		printf("%d ", i);
		for (j = 1; j <= col; j++)
		{
			printf(" %c ", board[i][j]);
		}
		printf("\n");
	}
	printf("-------------棋盘------------\n");
}
//进入游戏
void Games(void)
{
	//创建棋盘1
	char encychessboard[ROWS][COLS] = { 0 };
	//创建棋盘2
	char chessboard[ROWS][COLS] = { 0 };

	//初始化棋盘1
	init_board(encychessboard, ROWS, COLS, '0');
	//初始化棋盘2
	init_board(chessboard, ROWS, COLS, '*');

	//打印棋盘2
	print_board(chessboard, ROW, COL);
}

5、进行埋雷

我们规定 ‘0’ 不是雷,‘1’是雷

首先给定一个固定的雷数,让系统随机埋雷

埋雷是埋在棋盘1中的,也就是将一个随机位置中的内容 ’0‘ 改成 ’1‘

让系统产生两个随机数,两个不超出棋盘的随机坐标并对其进行判断

判断该坐标里面是否有雷,若是有则重新随机生成坐标

只有在没有雷的情况下进行埋雷

也就是判断该位置是否为‘0’ 若是则将其改为‘1’,若该位置是‘1’ 则重新生成坐标继续判断

显然在这里我们一直在做重复操作,所以用while循环来解决该问题

代码如下:

#define NUMBER 20//埋雷的个数

void mine_laying(char board[ROWS][COLS],int row,int col)
{
	int cun = NUMBER;
	while (cun)
	{
		//生成两个随机坐标
		int x = rand() % row + 1;
		int y = rand() % col + 1;
		//判断该位置是否有雷
		//没有雷则放置雷
		if (board[x][y] == '0')
		{
			board[x][y] = '1';
			cun--;
		}
	}
}

//进入游戏
void Games(void)
{
	//创建棋盘1
	char encychessboard[ROWS][COLS] = { 0 };
	//创建棋盘2
	char chessboard[ROWS][COLS] = { 0 };

	//初始化棋盘1
	init_board(encychessboard, ROWS, COLS, '0');
	//初始化棋盘2
	init_board(chessboard, ROWS, COLS, '*');

	//打印棋盘
	print_board(chessboard, ROW, COL);

	//埋雷
	mine_laying(encychessboard, ROW, COL);
	//print_board(encychessboard, ROW, COL);//测试是否埋雷成功
}

6、进行排雷

玩家开始输入坐标,进行排雷,

若该位置有雷,则提示玩家被炸死,并结束游戏

若该位置无雷,则在该位置显示周边一圈雷的个数,且让玩家继续排雷,直到将所有无雷的位置都找出来,则提示玩家胜利,结束游戏

以上操作都是重复的所以我们运用循环

在排雷的时候是在棋盘1中进行判断该位置是否等于‘1’,若是’1‘则是有雷,

若是’0‘则没有雷,没有雷的时候,我们计算出棋盘1中该位置周边的雷的数量,因为我们让玩家看到的是棋盘2 所以将雷的数量存放在棋盘2的该坐标位置

代码如下:

//统计周边雷的个数
int Statistics(char board[ROWS][COLS], int x, int y)
{
	//让周边的字符减去'0' 得到与该字符相同的整型值
	//因为没有雷的时候是‘0’ 有雷是‘1’
	//所以将他们转化成与其相同的整型数再求和就是周边雷的总数
	return board[x - 1][y] - '0' + board[x - 1][y - 1] - '0' + board[x][y - 1] - '0' +
		board[x + 1][y - 1] - '0' + board[x + 1][y] - '0' + board[x + 1][y + 1] - '0' +
		board[x][y + 1] - '0' + board[x - 1][y + 1] - '0';
}

//排雷
mine_clearance(char encychessboard[ROWS][COLS],char chessboard[ROWS][COLS],int row,int col)
{
	int cun = row * col - NUMBER;//没有雷的位置的数量
	int a = 0;
	int x = 0;//封装横坐标
	int y = 0;//封装竖坐标
	while (1)
	{
		printf("请输入要排除的坐标->");
		scanf("%d %d", &x, &y);
		//判断输入的坐标是否合法
		if ((x >= 1 && x <= row) && (y >= 1 && y <= col))
		{

			if (encychessboard[x][y] == '1')
			{
				printf("\n");
				printf("该位置有雷,你被炸死了!\n");
				break;
			}
			if (encychessboard[x][y] == '0')
			{
				//若是没有雷 将该坐标周边雷的个数保存在棋盘2上的该位置
				chessboard[x][y] = Statistics(encychessboard, x, y) + '0';
				//再打印一下棋盘2
				print_board(chessboard, ROW, COL);
				a++;
				if (a == cun)
				{
					printf("恭喜你排雷成功取得胜利\n");
					break;
				}
			}
		}
		else
		{
			printf("\n");
			printf("该坐标不合法 请重新选择:\n");
			printf("\n");
		}
	}
}

//进入游戏
void Games(void)
{
	//创建棋盘1
	char encychessboard[ROWS][COLS] = { 0 };
	//创建棋盘2
	char chessboard[ROWS][COLS] = { 0 };

	//初始化棋盘1
	init_board(encychessboard, ROWS, COLS, '0');
	//初始化棋盘2
	init_board(chessboard, ROWS, COLS, '*');

	//打印棋盘
	print_board(chessboard, ROW, COL);

	//埋雷
	mine_laying(encychessboard, ROW, COL);
	//print_board(encychessboard, ROW, COL);//测试是否埋雷成功

	//排雷
	mine_clearance(encychessboard, chessboard, ROW, COL);
	//排雷结束之后打印棋盘1让玩家看到雷的位置
	print_board(encychessboard, ROW, COL);
}

总代码:

#include 
#include 
#include 

#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
#define NUMBER 20//埋雷的个数

//打印棋盘
//我们只打印最初设置的棋盘大小
void print_board(char board[ROWS][COLS], int row, int col)
{
	printf("\n-------------棋盘------------\n");
	int i = 0;
	int j = 0;
	//打印列号
	printf(" ");
	for (j = 1; j <= col; j++)
	{
		printf("  %d", j);
	}
	printf("\n");
	for (i = 1; i <= row; i++)
	{
		//打印行号
		printf("%d ", i);
		for (j = 1; j <= col; j++)
		{
			printf(" %c ", board[i][j]);
		}
		printf("\n");
	}
	printf("-------------棋盘------------\n\n");
}

//统计周边雷的个数
int Statistics(char board[ROWS][COLS], int x, int y)
{
	//让周边的字符减去'0' 得到与该字符相同的整型值
	//因为没有雷的时候是‘0’ 有雷是‘1’
	//所以将他们转化成与其相同的整型数再求和就是周边雷的总数
	return board[x - 1][y] - '0' + board[x - 1][y - 1] - '0' + board[x][y - 1] - '0' +
		board[x + 1][y - 1] - '0' + board[x + 1][y] - '0' + board[x + 1][y + 1] - '0' +
		board[x][y + 1] - '0' + board[x - 1][y + 1] - '0';
}

//排雷
mine_clearance(char encychessboard[ROWS][COLS],char chessboard[ROWS][COLS],int row,int col)
{
	int cun = row * col - NUMBER;//没有雷的位置的数量
	int a = 0;
	int x = 0;//封装横坐标
	int y = 0;//封装竖坐标
	while (1)
	{
		printf("请输入要排除的坐标->");
		scanf("%d %d", &x, &y);
		//判断输入的坐标是否合法
		if ((x >= 1 && x <= row) && (y >= 1 && y <= col))
		{

			if (encychessboard[x][y] == '1')
			{
				printf("\n");
				printf("该位置有雷,你被炸死了!\n");
				break;
			}
			if (encychessboard[x][y] == '0')
			{
				//若是没有雷 将该坐标周边雷的个数保存在棋盘2上的该位置
				chessboard[x][y] = Statistics(encychessboard, x, y) + '0';
				//再打印一下棋盘2
				print_board(chessboard, ROW, COL);
				a++;
				if (a == cun)
				{
					printf("恭喜你排雷成功取得胜利\n");
					break;
				}
			}
		}
		else
		{
			printf("\n");
			printf("该坐标不合法 请重新选择:\n");
			printf("\n");
		}
	}
}

void mine_laying(char board[ROWS][COLS],int row,int col)
{
	int cun = NUMBER;
	while (cun)
	{
		//生成两个随机坐标
		int x = rand() % row + 1;
		int y = rand() % col + 1;
		//判断该位置是否有雷
		//没有雷则放置雷
		if (board[x][y] == '0')
		{
			board[x][y] = '1';
			cun--;
		}
	}
}

//初始化棋盘
//传行、传列、传要初始化成啥字符
void init_board(char board[ROWS][COLS], int rows, int cols, char c)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < rows; i++)
	{
		for (j = 0; j < cols; j++)
		{
			board[i][j] = c;
		}
	}
}

//进入游戏
void Games(void)
{
	//创建棋盘1
	char encychessboard[ROWS][COLS] = { 0 };
	//创建棋盘2
	char chessboard[ROWS][COLS] = { 0 };

	//初始化棋盘1
	init_board(encychessboard, ROWS, COLS, '0');
	//初始化棋盘2
	init_board(chessboard, ROWS, COLS, '*');

	//打印棋盘
	print_board(chessboard, ROW, COL);

	//埋雷
	mine_laying(encychessboard, ROW, COL);
	//print_board(encychessboard, ROW, COL);//测试是否埋雷成功

	//排雷
	mine_clearance(encychessboard, chessboard, ROW, COL);
	//排雷结束之后打印棋盘1让玩家看到雷的位置
	print_board(encychessboard, ROW, COL);
}

void Mune(void)
{
	printf("*****************************\n");
	printf("*********  1、play  *********\n");
	printf("*********  0、exit  *********\n");
	printf("*****************************\n");
}

void Text(void)
{
	//用时间戳创建随机数,用后面布置雷做准备
	srand((unsigned int)time(NULL));
	//srand的参数是unsigned int  
	// time函数的参数是一个指针在这里我们不知道该传什么所以给其传空指针
	//time 函数的返回值是 time_t(time_t实则是一个与时间有关的长整型)
	//所以将其强制转换
	
	int input = 0;//封装用户的输入
	//运用do while 至少执行一次
	do {
		//游戏菜单
		Mune();
		printf("请选择->:");
		scanf("%d", &input);
		//用switch语句判断
		switch (input)
		{
		case 1:
			//进入游戏
			Games();
			break;
		case 0:
			printf("退出成功\n");
			break;
		default:
			printf("输入无效,请重新选择\n");
			break;
		}
	} while (input);//当变量的值为0时结束循环
}

int main()
{
	//扫雷游戏
	//游戏测试
	Text();
	return 0;
}

你可能感兴趣的:(游戏,c语言)