【C语言 |扫雷游戏】C语言实现的的扫雷游戏!!!!

目录

 一、问题描述

二、基本思路

三、步骤

1.菜单界面

 2.创建棋盘

 3.初始化棋盘

4.打印棋盘

5.布置雷 

6.排查雷

 8.主要逻辑实现

四、代码实现


 一、问题描述

用C语言实现扫雷

在线扫雷游戏:http://www.minesweeper.cn/

二、基本思路

实现代码的逻辑

使⽤控制台实现经典的扫雷游戏
游戏可以通过菜单实现继续玩或者退出游戏
扫雷的棋盘是9*9的格⼦
默认随机布置10个雷
可以排查雷
如果位置不是雷,就显⽰周围有⼏个雷
如果位置是雷,就炸死游戏结束
把除10个雷之外的所有雷都找出来,排雷成功,游戏结束
扫雷的过程中,布置的雷和排查出的雷的信息都需要存储,所以我们需要⼀定的数据结构来存储些
信息。
因为我们需要在9*9的棋盘上布置雷的信息和排查雷,我们⾸先想到的就是创建⼀个9*9的数组来存放 信息。
那如果这个位置布置雷,我们就存放1,没有布置雷就存放0.
专⻔给⼀个棋盘(对应⼀个数组mine)存放布置好的雷的信息,再 给另外⼀个棋盘(对应另外⼀个数组show)存放排查出的雷的信息。这样就互不⼲扰了,把雷布置到 mine数组,在mine数组中排查雷,排查出的数据存放在show数组,并且打印show数组的信息给后期 排查参考。

三、步骤

1.菜单界面

首先玩家进入程序,不管三七二十一先打印出来菜单(可以用do  while语句实现)

输入对应的数字选择对应的游戏

void menu(void)
{
	printf("\n**********游戏机***********\n");
	printf("*********玩过都说好*******\n\n");
	printf("**********************\n");
	printf("******1.扫雷**********\n");
	printf("******2.刮刮乐**********\n");
	printf("******3.地铁跑酷**********\n");
	printf("******4.王者荣耀**********\n");
	printf("******5.老爹的早餐店**********\n");
	printf("******0.exit******************\n");
	printf("******************************\n");
	printf("*****************************\n\n");
}

 2.创建棋盘

试想一下扫雷游戏,当点了一个位置以后,如果不是雷 这一片都会展开并在点的这里统计周围雷的个数

基于这一点 假如说创建一个9*9大小的棋盘来存雷 那排查雷就要12*12大小

因为 行跟列都会改变,我们使用宏定义去定义大小跟雷

#define ROW 9
#define COL 9

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

#define MINE 10

在扫雷中 刚开始的时候我们看棋盘是什么都看不见的,在玩的过程中会一点点显露出来并且记录周围的雷个数,所以这意味着需要两个数字来实现这个功能

    char mine数组           用来存放布置好的雷
    char show 数组         用来存放排查出的雷的信息

	char mine[ROWS][COLS];     
	char show[ROWS][COLS];    

 3.初始化棋盘

将棋盘全部初始化为传入的set这个字符 

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

 当然也可以用这个库函数来实现

memset()这个库函数实现--------包含头文件  #include<string,h>

复制字符 set(一个无符号字符)到参数 board所指向的字符串的前 n 个字符

                                               //这个set作用是需要初始化什么就传什么字符
void Board_Init(char board[ROWS][COLS],int rows,int cols,char set)
{
             //(rows*cols*sizeof(board[0][0]))  行*列*单个元素大小 就是整个数组大小
	memset(&board[0][0],set,rows*cols*sizeof(board[0][0]));
}

 因为  mine 用来存放布置好的雷, show 用来存放排查出的雷的信息,所以

将mine初始化设为0,雷后面设为1

将show刚开始设为* ,进入游戏什么都看不见

	Board_Init(mine, ROWS, COLS, '0');
	Board_Init(show, ROWS, COLS, '*');

4.打印棋盘

为了方便玩家好找坐标去排查,不用一个个去数,我们可以将行跟列分别打印在第一行

void DisPlayBorad(char arr[ROWS][COLS], int row, int col)
{
	int i, j = 0;                         // 打印出棋盘
	printf("\n--------------------------------\n");
	for (i = 0; i <= col; i++)
	{
		printf("%d", i);        // 打印显示行
	}
	printf("\n");
	for (i = 1; i <= row; i++)
	{
		printf("%d", i);              //打印显示列
		for (j = 1; j <= col; j++)
		{
			printf("%c", arr[i][j]);
		}
		printf("\n");
	}
}

单独打印出来0123456789  换行以后在每一次 i++ 之后进入 j 之前打印出来 i 

放在前面给玩家当个指导

5.布置雷 

我们可以先宏定义一个雷的个数

雷个数越多我们的难度越大,可以通过控制雷的个数控制难度,使用宏方便修改

#define MINE 10

这个函数作用是将雷随机的放入数组中

为了保证每一次的值真正随机,在主函数里面给她一个时间戳种子
并且包含两个头文件

#include<stdlib.h>
#include<time.h>
 
srand((unsigned int)time(NULL))

 每布置一个雷减一个次数并且把那个位置设为1

当次数为0(count==0)的时候,就不往进放了

里面的if语句作用是为了在没有雷的地方进行布置

而rand()函数生成的随机数范围在0 ~ 32767之间

所以我们要给她% 行/列 数,生成的num就是0大于等于0,小于自己的数

因为为了方便统计我们的数组是12*12 但实际是9*9

所以最外面的一圈不能被放置雷的,所以就有了

int x = rand() % row + 1;
int y = rand() % col + 1;

void SetMine(char mine[ROWS][COLS], int row, int col)
{
	//布置10个雷
//⽣成随机的坐标,布置雷

	int count = MINE;
	while (count)
	{
		int x = rand() % row + 1;
		int y = rand() % col + 1;
		if (mine[x][y] == '0')
		{
			mine[x][y] = '1';
			count--;
		}
	}
}

6.排查雷

这个代码实现对棋盘雷的排查,玩家输入坐标

是雷了被炸死

不是雷这个位置统计周围的雷个数

只有被炸死或者排除完雷才能跳出,不然一直在这个函数中循环

顺便给大家补充个知识点

int类型变成char类型

只需要1 + ‘0’ = ‘1’

同理

char类型变为int类型

只需要‘1’-‘0’=1

void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
	int x, y = 0;

    //x y坐标

	int win = 0;

    //win是剩余没有排查没有雷的的位置

	while (win < ((row * col) - MINE)) //当剩余的地方小于没有雷的位置时,说明还可以排继续循环
	{
		printf("Enter the coordinates for troubleshooting(选择你要排查的坐标)->");
		scanf("%d%d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			if (mine[x][y] == '1')
			{
				printf("The game is over, you're dead(游戏结束你死了)!!!!!!!");
				printf("打印出来了你看吧");
				DisPlayBorad(mine, ROW, COL);

                            //位置是1为雷 被炸死游戏结束
				break;
			}
			else
			{
				int n = GetMineCount(mine, x, y);
				show[x][y] = n + '0';
				DisPlayBorad(show, ROW, COL);
				win++;
			}
		}
		else
		{
			printf("Re-enter(请重新输入)\n");
		}
	}
	if (win == ((row * col) - MINE))
	{

//当剩余的地方等于没有雷的位置时,说明排完了,游戏结束赢了

		printf("Complete the game(赢咯)\n");
		DisPlayBorad(mine, ROW, COL);
	}
}

正因为这个函数返回值为整形int,但是传给show数组里面类型是char类型

正如上面说的int类型变成char类型,只需要用这个数加上一个字符0

所以就有了上述代码中的这个操作

int n = GetMineCount(mine, x, y);
 show[x][y] = n + '0';

 这个函数功能是当这个位置不是雷 统计一下周围有几个雷并以整形返回

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

}

 8.主要逻辑实现

这个函数主要实现整体逻辑

void game(void)
{
	char mine[ROWS][COLS];     //存放布置好的雷
	char show[ROWS][COLS];     //存放排查出的雷的信息


	//初始化棋盘
//1. mine数组最开始是全'0'
//2. show数组最开始是全'*'

	Board_Init(mine, ROWS, COLS, '0');
	Board_Init(show, ROWS, COLS, '*');

	//打印棋盘
	DisPlayBorad(show, ROW, COL);

	//1. 布置雷

	SetMine(mine, ROW, COL);

	//2. 排查雷

	FindMine(mine, show, ROW, COL);


	printf("\n歇一下  20秒后进入菜单");
	Sleep(20000);
	system("cls");              //睡眠10s 自动清屏


}

四、代码实现

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include <stdlib.h>
#include<time.h>
#include <windows.h>
#define ROW 9
#define COL 9

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

#define MINE 10

void menu(void)
{
	printf("\n**********游戏机***********\n");
	printf("*********玩过都说好*******\n\n");
	printf("**********************\n");
	printf("******1.扫雷**********\n");
	printf("******2.刮刮乐**********\n");
	printf("******3.地铁跑酷**********\n");
	printf("******4.王者荣耀**********\n");
	printf("******5.老爹的早餐店**********\n");
	printf("******0.exit******************\n");
	printf("******************************\n");
	printf("*****************************\n\n");
}

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

void DisPlayBorad(char arr[ROWS][COLS], int row, int col)
{
	int i, j = 0;                         // 打印出棋盘
	printf("\n--------------------------------\n");
	for (i = 0; i <= col; i++)
	{
		printf("%d", i);        // 打印显示行
	}
	printf("\n");
	for (i = 1; i <= row; i++)
	{
		printf("%d", i);              //打印显示列
		for (j = 1; j <= col; j++)
		{
			printf("%c", arr[i][j]);
		}
		printf("\n");
	}
}

void SetMine(char mine[ROWS][COLS], int row, int col)
{
	//布置10个雷
//⽣成随机的坐标,布置雷

	int count = MINE;
	while (count)
	{
		int x = rand() % row + 1;
		int y = rand() % col + 1;
		if (mine[x][y] == '0')
		{
			mine[x][y] = '1';
			count--;
		}
	}
}

int GetMineCount(char mine[ROWS][COLS], int x, int y)
{
	return ((mine[x + 1][y] + mine[x][y + 1] + mine[x - 1][y] + mine[x][y - 1] + mine[x + 1][y + 1] + mine[x + 1][y - 1] + mine[x - 1][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, y = 0;
	int win = 0;
	while (win < ((row * col) - MINE))
	{
		printf("Enter the coordinates for troubleshooting(选择你要排查的坐标)->");
		scanf("%d%d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			if (mine[x][y] == '1')
			{
				printf("The game is over, you're dead(游戏结束你死了)!!!!!!!");
				printf("打印出来了你看吧");
				DisPlayBorad(mine, ROW, COL);
				break;
			}
			else
			{
				int n = GetMineCount(mine, x, y);
				show[x][y] = n + '0';
				DisPlayBorad(show, ROW, COL);
				win++;
			}
		}
		else
		{
			printf("Re-enter(请重新输入)\n");
		}
	}
	if (win == ((row * col) - MINE))
	{
		printf("Complete the game(赢咯)\n");
		DisPlayBorad(mine, ROW, COL);
	}
}


void game(void)
{
	char mine[ROWS][COLS];     //存放布置好的雷
	char show[ROWS][COLS];     //存放排查出的雷的信息


	//初始化棋盘
//1. mine数组最开始是全'0'
//2. show数组最开始是全'*'

	Board_Init(mine, ROWS, COLS, '0');
	Board_Init(show, ROWS, COLS, '*');

	//打印棋盘
	DisPlayBorad(show, ROW, COL);

	//1. 布置雷

	SetMine(mine, ROW, COL);

	//2. 排查雷

	FindMine(mine, show, ROW, COL);


	printf("\n歇一下  20秒后进入菜单");
	Sleep(20000);
	system("cls");              //睡眠10s 自动清屏

}

int main(void)
{
	srand((unsigned int)time(NULL));
	int input = 0;
	do
	{
		menu();   //进来先打印出来一个菜单
		printf("please input number(输入对应数字 选择游戏):>");
		scanf("%d", &input);
		Sleep(1000);
		switch (input)
		{
		case 1:                   //根据选择的数字进入对应的case
			system("cls");
			printf(">>>>>>>>>>>>>>>>>>>>>>> game start(游戏开始)!!!!!!!!!!!!!!\n");
			Sleep(1000);
			game();
			break;
		case 2:
			system("cls");
			printf("Lie to you(呆瓜 根本没有刮刮乐,只有一个扫雷哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈)\n");
			Sleep(1000);
			break;
		case 3:
			system("cls");
			printf("Lie to you(呆瓜 根本没有地铁跑酷,只有一个扫雷哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈)\n");
			Sleep(1000);
			break;
		case 4:
			system("cls");
			printf("Lie to you(呆瓜 根本没有王者荣耀,只有一个扫雷哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈)\n");
			Sleep(1000);
			break;
		case 5:
			system("cls");
			printf("Lie to you(呆瓜 根本没有老爹的早餐店,只有一个扫雷哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈哈)\n");
			Sleep(1000);
			break;
		case 0:
			system("cls");
			printf(">>>>>>>>>>>>>>>>>>>>>>> game over(游戏结束)!!!!!!!!!\n");
			Sleep(1000);
			break;
		default:
			system("cls");
			printf(">>>>>>>>>>>>>>>>>>>>>>> Re-enter(重新选择)_________________\n");
			Sleep(1000);
			break;
		}
	} while (input);

	return 0;
}

希望对你有帮助

  • 18
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值