C语言扫雷

目录

一:扫雷的基本规则和逻辑

1:游戏概述:

2:游戏规则:

   ​编辑

3:实现思路

二:代码的实现

1:文件结构设计和头文件

2:菜单以及主函数

 3:初始化棋盘

3:打印棋盘

4:布置雷

5:排查雷

三:扫雷总代码


一:扫雷的基本规则和逻辑

1:游戏概述:

扫雷是一款经典的小游戏,想必在做的各位应该都玩过这一款游戏,玩法是让和我们在一个9×9的格子里面排查出隐藏在里面的10个地雷,如果在排查的过程中不小心踩到地雷游戏就会失败,所以要求我们精准的把所有地雷都找出来

2:游戏规则:

  • 盘面上有许多方格,方格中随机分布着一些雷。
  • 你的目标是避开雷,打开其他所有格子。
  • 一个非雷格中的数字表示其相邻8格中的雷数,你可以利用这个信息推导出安全格和雷的位置。
  • 你可以用右键在你认为是雷的地方插旗(称为标雷)。
  • 你可以用左键打开安全的地方,左键打开雷将被判定为失败。
  • 扫雷游戏胜利的条件是揭示所有不包含地雷的格子。
  • 利用安全格子提供的信息,我们可以推断一个格子附近的格子有没有雷。
  • 安全格子的类型:数字表示它周围八个格子中地雷的数量;空白表示附近都没有地雷。
  • 扫雷技巧:刚开始需要碰运气,只要点开一个区域,就可以正式开始了。根据现有情况,判断出一定有雷的位置。利用右键和左键的组合可以快速揭示周围的方块。

   

    

3:实现思路

1)先创建一个游戏的开始界面

2)首先创建一个mine数组存放布置好的雷的信息,并将其中的数组全部初始化为字符' 0 '还得创建一个show数组用来存放排查出的雷的信息,将里面初始化成 ' * '

3)然后对棋盘进行初始化和打印

4)将雷放入到创建的mine数组中去,雷为‘1’

5)最后寻找雷,知道排查出所有雷为止或被雷炸死

二:代码的实现

1:文件结构设计和头文件

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

2:菜单以及主函数

菜单:游戏菜单如下,1为开始游戏,0为退出游戏

void menu()
{
	printf("********************\n");
	printf("****   1. palay ****\n");
	printf("****   0. exit  ****\n");
	printf("********************\n");

}

主函数:

int main()
{
	int input = 0;
	srand((unsigned int)time(NULL));
	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:初始化棋盘

首先我们来初始化棋盘,在初始化之前我们先来定义ROW和COL的大小

有的人会问这里的ROW+2和COL+2是什么意思呢?我们在初始化棋盘的时候虽然我们实际初始化的9*9的棋盘大小,但是我们在周围还应该布置一圈,所以大小在9*9的基础上+2,这多出来的一圈是为了防止越界访问

这里用mine数组来存放布置好的雷的信息,用show数组来存放排查出的雷的信息,并将mine初始化为'*',show初始化为'*'

char mine[ROWS][COLS] = { 0 };//存放布置好的雷的信息
char show[ROWS][COLS] = { 0 };//存放排查出的雷的信息

//初始化棋盘
InitBoard(mine, ROWS, COLS,'0');
InitBoard(show, ROWS, COLS,'*');

//game.h文件
//棋盘的初始化
void InitBoard(char board[ROWS][COLS], int rows, int cols,int set);
//game.c文件
//初始化棋盘
void InitBoard(char board[ROWS][COLS], int rows, int cols, int set)
{
	int i = 0;
	for (i = 0; i < rows;i++)
	{
		int j = 0;
		for (j = 0; j < cols;j++)
		{
			board[i][j] = set;
		}
	}
}

          

3:打印棋盘

 以上是初始化棋盘的代码,在初始化好棋盘后我们可以给初始化的棋盘加上行号和列号,也就是打印棋盘

//打印棋盘
DisplayBoard(mine, ROW, COL);
//game.h文件
//打印棋盘
void DisplayBoard(char board[ROWS][COLS], int row, int col);

//game.c文件
//打印棋盘
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
	int i = 0;
	printf("------ 扫雷 ------\n");
	//打印列号
	for (i = 0; i <= row; i++)
	{
		printf("%d ", i);
	}
	printf("\n");
	for(i = 1;i <= row;i++)
	{
		int j = 0;
		//打印行号
		printf("%d ", i);
		for (j = 1; j <= col; j++)
		{
			printf("%c ", board[i][j]);
		}
		printf("\n");
	}
}

弹出游戏菜单后,我们选择1.play开始游戏,然后打印出隐藏好雷的棋盘,用户通过输入坐标来排查棋盘中布置好的雷 

4:布置雷

我们完成了棋盘的初始化和打印,接下来我们将10个雷随机的布置到棋盘当中去,在布置的时候我们需要在game.h文件中定义一个变量EASY_COUNT,这里的变量同前面的的ROWS和COLS是一样的道理,如果需要增加布置的雷只需修改声明的变量10即可

接下来我们可以正式开始布置雷了

//布置雷
void SetMaine(char board[ROWS][COLS], int row, int col);

 1):我们先定义一个count表示布置的雷的个数,但是为了后续的修改我们可以将int count = 10;改为int count = EASY_COUNT; 

2):这里我们需要用到rand函数,rand函数会返回⼀个伪随机数,这个随机数的范围是在0~RAND_MAX之间,这个RAND_MAX的大小是依赖编译器上实现的,但是大部分编译器上是32767

其中while循环中的rand() % 9;  rand() % 9;可以让我们将x和y的范围控制在0~9;我们如果在后面分别加上+1可以使x,y的范围控制在1~9,正好是我们棋盘的大小9*9的范围

3):再将9改为row和col变量,这可以方便我们后续对棋盘的修改,我们在初始化棋盘时将存放布置雷的棋盘初始化为'0';如果为'0',我们就可以将雷'1'布置到其中然后count--

//布置雷
void SetMaine(char board[ROWS][COLS], int row, int col)
{
	int count = 10;
	while (count)
	{
		int x = rand() % 9 + 1;
		int y = rand() % 9 + 1;

		if (board[x][y] == '0')
		{
			board[x][y] = '1';
			count--;
		}
	}
}

 以下是优化后的代码

//布置雷
void SetMaine(char board[ROWS][COLS], int row, int col)
{
	int count = EASY_COUNT;
	while (count)
	{
		int x = rand() % row + 1;
		int y = rand() % col + 1;

		if (board[x][y] == '0')
		{
			board[x][y] = '1';
			count--;
		}
	}
}

5:排查雷

布置好雷以后我们开始排查雷,这一步是非常重要的一部也是较为复杂的一部

//排查雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);

1):在排查雷的时候,我们先要弄清楚在排查雷的过程中,在存放排查出的雷的棋盘中,如果排查的坐标位置不是雷,我们需要以九宫格为中心雷的个数给打印到棋盘中去,其实这也是比较好实现和了解的

2):因为字符'0'的ASCLL值为--48,字符'1'的ASCLL值为--49,字符'2'的ASCLL值为--50,由此我饿们可以总结出字符'2' - '0' = 2(数字2), '1' - '0' = 1(数字1),'6' - '0' = 6(数字6),我饿们可以通过此来就算雷的个数

3):通过下面的图片中的数据来就算九宫格中四周的雷,横为y,竖为x,然后分别他们挨个加起来,最后总的减去8*'0'就可以求出雷的个数了

x-1,y-1x-1,yx-1,y+1
x,y-1x,yx,y+1
x-1,y-1x+1,yx+1,y+1
GetMineCount(char mine[ROWS][COLS],int x,int y)
{
	return mine[x - 1][y] +
		mine[x - 1][y - 1] +
		mine[x][y - 1] +
		mine[x + 1][y - 1] +
		mine[x + 1][y] +
		mine[x + 1][y + 1] +
		mine[x][y + 1] +
		mine[x - 1][y + 1] - 8 * '0';
}

 4):首先我们定义一个下x,y变量来表示数组[row][col],在创建一个变量win不是雷的个数,接下来进入循win<row*col-EASY_COUNT,我们输入需要排查的雷的坐标,用scanf函数来输入,进入第一个if语句如果x,y在1~9中执行循环反之则退出循环,进入第二个if语句,如果输入的[x][y]坐标位置有雷,则输出被炸死了,然后将存放排查出的雷的信息打印给用户,然后break退出循环

5):如果进入else语句,说明输入的坐标位置没有雷,并统计mine数组的x,y坐标周围的8个坐标中有几个雷,这里调用我们上面封装的函数GetMineCount,计算出周围的雷的数量,然后打印棋盘用DisplayBoard函数,win++,进入下一个else语句时,如果输入的坐标超出棋盘则打印输入的是无效坐标,请重新输入,最后如果将所有的雷都找了出来,游戏也就结束了

//排查雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
	int x = 0;
	int y = 0;
	int win = 0;
	while (win<row*col-EASY_COUNT)
	{
		printf("请输入要排查的坐标");
		scanf("%d %d", &x, &y);
		if (x>=1 && x<=row && y>=1 && y<=col)
		{
			if (mine[x][y] == '1')
			{
				printf("抱歉,你被炸死了\n");
				DisplayBoard(mine, ROW, COL);
				break;
			}
			else
			{
				//统计mine数组的x,y坐标周围的8个坐标中有几个雷
				int count = GetMineCount(mine, x, y);
				show[x][y] = count + '0';
				DisplayBoard(show, ROW, COL);
				win++;
			}
		}
		else
		{
			printf("输入的是无效坐标,请重新输入\n");
		}
	}
	if (win == row * col - EASY_COUNT)
	{
		printf("恭喜你排雷成功\n");
		DisplayBoard(mine, ROW, COL);

	}
}

三:扫雷总代码

1:test.c

#include "game.h"

void menu()
{
	printf("********************\n");
	printf("****   1. palay ****\n");
	printf("****   0. exit  ****\n");
	printf("********************\n");

}
//完成扫雷的全部过程
void game()
{
	char mine[ROWS][COLS] = { 0 };//存放布置好的雷的信息
	char show[ROWS][COLS] = { 0 };//存放排查出的雷的信息

	//初始化棋盘
	InitBoard(mine, ROWS, COLS,'0');
	InitBoard(show, ROWS, COLS,'*');

	//打印棋盘
	//DisplayBoard(mine, ROW, COL);

	//布置雷
	SetMaine(mine, ROW, COL);
	DisplayBoard(show, ROW, COL);
	//DisplayBoard(mine, ROW, COL);


	//排查雷
	FindMine(mine,show, ROW, COL);
}

int main()
{
	int input = 0;
	srand((unsigned int)time(NULL));
	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;
}

2.game.h

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>

#define EASY_COUNT 10

#define ROW 9
#define COL 9

#define ROWS ROW+2
#define COLS COL+2

//棋盘的初始化
void InitBoard(char board[ROWS][COLS], int rows, int cols,int set);

//打印棋盘
void DisplayBoard(char board[ROWS][COLS], int row, int col);

//布置雷
void SetMaine(char board[ROWS][COLS], int row, int col);

//排查雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);

3:game.c

#include "game.h"

//初始化棋盘
void InitBoard(char board[ROWS][COLS], int rows, int cols, int set)
{
	int i = 0;
	for (i = 0; i < rows;i++)
	{
		int j = 0;
		for (j = 0; j < cols;j++)
		{
			board[i][j] = set;
		}
	}
}

//打印棋盘
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
	int i = 0;
	printf("------ 扫雷 ------\n");
	//打印列号
	for (i = 0; i <= row; i++)
	{
		printf("%d ", i);
	}
	printf("\n");
	for(i = 1;i <= row;i++)
	{
		int j = 0;
		//打印行号
		printf("%d ", i);
		for (j = 1; j <= col; j++)
		{
			printf("%c ", board[i][j]);
		}
		printf("\n");
	}
}

//布置雷
void SetMaine(char board[ROWS][COLS], int row, int col)
{
	int count = EASY_COUNT;
	while (count)
	{
		int x = rand() % row + 1;
		int y = rand() % col + 1;

		if (board[x][y] == '0')
		{
			board[x][y] = '1';
			count--;
		}
	}
}

GetMineCount(char mine[ROWS][COLS],int x,int y)
{
	return mine[x - 1][y] +
		mine[x - 1][y - 1] +
		mine[x][y - 1] +
		mine[x + 1][y - 1] +
		mine[x + 1][y] +
		mine[x + 1][y + 1] +
		mine[x][y + 1] +
		mine[x - 1][y + 1] - 8 * '0';
}
//排查雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
	int x = 0;
	int y = 0;
	int win = 0;
	while (win<row*col-EASY_COUNT)
	{
		printf("请输入要排查的坐标");
		scanf("%d %d", &x, &y);
		if (x>=1 && x<=row && y>=1 && y<=col)
		{
			if (mine[x][y] == '1')
			{
				printf("抱歉,你被炸死了\n");
				DisplayBoard(mine, ROW, COL);
				break;
			}
			else
			{
				//统计mine数组的x,y坐标周围的8个坐标中有几个雷
				int count = GetMineCount(mine, x, y);
				show[x][y] = count + '0';
				DisplayBoard(show, ROW, COL);
				win++;
			}
		}
		else
		{
			printf("输入的是无效坐标,请重新输入\n");
		}
	}
	if (win == row * col - EASY_COUNT)
	{
		printf("恭喜你排雷成功\n");
		DisplayBoard(mine, ROW, COL);

	}
}

以上就是扫雷的全部代码了,创作不易,求求大家点个小赞赞,感谢各位老们的赏脸观看,随手点个赞,养成好习惯,如有问题,感谢反馈!

以下是一个简单的 C 语言扫雷游戏的示例代码: ```c #include <stdio.h> #include <stdlib.h> #include <time.h> #define ROW 10 // 行数 #define COL 10 // 列数 #define MINE_NUM 10 // 雷数 int board[ROW][COL]; // 扫雷棋盘 /** * 在棋盘上随机放置雷 */ void place_mines() { int count = 0; while (count < MINE_NUM) { int row = rand() % ROW; int col = rand() % COL; if (board[row][col] != -1) { board[row][col] = -1; count++; } } } /** * 输出棋盘 */ void print_board() { printf(" "); for (int j = 0; j < COL; j++) { printf(" %d", j); } printf("\n"); for (int i = 0; i < ROW; i++) { printf("%d ", i); for (int j = 0; j < COL; j++) { if (board[i][j] == -2) { printf("* "); } else if (board[i][j] >= 0) { printf("%d ", board[i][j]); } else { printf(". "); } } printf("\n"); } } /** * 计算某个格子周围的雷数 * @param row 行坐标 * @param col 列坐标 * @return 周围雷数 */ int count_mines(int row, int col) { int count = 0; for (int i = row - 1; i <= row + 1; i++) { for (int j = col - 1; j <= col + 1; j++) { if (i >= 0 && i < ROW && j >= 0 && j < COL && board[i][j] == -1) { count++; } } } return count; } /** * 打开某个格子 * @param row 行坐标 * @param col 列坐标 */ void open_cell(int row, int col) { if (board[row][col] == -1) { printf("Game Over!\n"); print_board(); exit(0); } else if (board[row][col] == -2) { board[row][col] = count_mines(row, col); if (board[row][col] == 0) { for (int i = row - 1; i <= row + 1; i++) { for (int j = col - 1; j <= col + 1; j++) { if (i >= 0 && i < ROW && j >= 0 && j < COL) { open_cell(i, j); } } } } } } int main() { srand(time(NULL)); // 初始化棋盘 for (int i = 0; i < ROW; i++) { for (int j = 0; j < COL; j++) { board[i][j] = -2; // -2 表示未打开的格子 } } // 随机放置雷 place_mines(); // 输出初始棋盘 print_board(); // 开始游戏 while (1) { int row, col; printf("Enter row and col: "); scanf("%d%d", &row, &col); if (row >= 0 && row < ROW && col >= 0 && col < COL) { open_cell(row, col); print_board(); } } return 0; } ``` 在这个示例代码中,我们使用一个二维数组 `board` 来表示扫雷棋盘,数组元素的含义如下: - `-1` 表示该格子是一颗雷; - `-2` 表示该格子还未被打开; - 非负整数表示该格子周围有多少颗雷。 游戏开始时,我们随机放置了 `MINE_NUM` 颗雷。然后,程序会要求用户输入一个格子的位置,如果该位置上是一颗雷,则游戏结束;否则,程序会计算该格子周围有多少颗雷,并在棋盘上显示出来。如果该格子周围没有雷,则程序会递归地打开周围的格子,直到不能再打开为止。游戏结束后,程序会输出完整的棋盘并退出。 当然,这只是一个简单的示例代码,实际的扫雷游戏还有很多需要完善的地方,例如计时、计分等等。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值