【c语言】扫雷-详解

 本文会用到随机数的知识,参考博主先前的文章
 [猜数字游戏](http://t.csdnimg.cn/2EOXg)
 本文采用结构化文件实现游戏 分别包括
 test.c //⽂件中写游戏的测试逻辑 
 game.c //⽂件中写游戏中函数的实现等
 game.h //⽂件中写游戏需要的数据类型和函数声明等

前言

游戏介绍

《扫雷》是一款大众类的益智小游戏,于1992年发行。游戏目标是在最短的时间内根据点击格子出现的数字找出所有非雷格子,同时避免踩雷,踩到一个雷即全盘皆输
在这里插入图片描述

实现思路

1.创建棋盘

创建两个棋盘,一个棋盘大小为11×11进行我们程序的实现,另一个棋盘大小为9×9展示给用户。
创建11*11棋盘大小的原因

如果想要知道边线位置上周围雷的个数,例如下图中7*8的位置周围雷的个数   
arr【7】【8】,我们就需要查找以这个位置为中心的正方形的位置中雷的个
数,在  9*9的棋盘上实现非常的麻烦,所以我们索性定义11*11的棋盘,
在多出来的位置上 信息置为'0'即非雷,这样我们统计某个位置的雷的个个数
时,只需    要进行简单的加法运算

在这里插入图片描述

2.进行埋雷

雷的位置在内部棋盘上用‘1’表示 , 没有雷则是‘0’
运用随机数的知识在1111的棋盘的99位置上进行埋雷

3.开始排雷

玩家输入要排查的位置,进行判断该位置是否有雷,有雷则爆炸退出游戏,没有雷则继续进行,并告知玩家该位置周围雷的个数。
在这里插入图片描述

具体步骤

头文件

头文件中出现内容都会在后续讲解

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<time.h>
#include<stdlib.h>

#define ROW 9 //代表行数
#define COL 9 //代表列数
#define ROWS COL+2
#define COLS ROW+2
#define EASYCOUNT 10  //定义雷的个数
//初始化棋盘
void InitBoard(char board[ROWS][COLS], int rows, int cols, char temp);
//展示棋盘
void DisplayBoard(char board[ROWS][COLS], int row, int col);
//埋雷操作
void SetMine(char mine[ROWS][COLS], int row, int col);
//排查雷
void FindMine(char mine[ROWS][COLS], char  show[ROWS][COLS], int row, int col);
//判断x,y坐标位置九宫格内雷的个数
int GetMineCount(char mine[ROWS][COLS], int x, int y);

1.test.c主体(游戏框架)

int main()
{
    
    
	srand((unsigned int)time(NULL));

	int input = 0;
	menu();
	printf("请输入你的选择->");
	scanf("%d", &input);
	switch (input)
	{
    
    
	case 1:
		game();
		break;
	case 0:
		printf("退出扫雷\n");
		break;

	default:
		printf("输入错误,请重新输入->");

	}
	return 0;
}

2.打印菜单

 打印菜单页面,让玩家进入游戏知道如何开始及退出。
void menu()
{
    
    
	printf("*********************\n");
	printf("*** 1. play     *****\n");
	printf("*** 0. exit     *****\n");
	printf("*********************\n");
	printf("*********************\n");
}

在这里插入图片描述

3.定义游戏函数

我们需要在这个函数内完成几个需求
1.创建棋盘
2.初始化棋盘
3.埋雷
4.排查雷
5.给出反馈

为使整体代码简洁明了,我们将这几个过程分别自定义为函数
写在头文件中

void game()
{
    
    
	char mine[ROWS][COLS] = {
    
     0 };
	char show[ROWS][COLS] = {
    
     0 };
	//初始化棋盘
	InitBoard(mine, ROWS, COLS, '0');
	InitBoard(show, ROWS, COLS, '*');


	//展示棋盘
	DisplayBoard(show, ROW, COL);
	//埋雷
	SetMine(mine, ROW, COL);

	//找雷
	FindMine(mine, show, ROW, COL);
	DisplayBoard(show, ROW, COL);
	return;

}

1)创建棋盘

这里我们预先在头文件定义ROWS COLS ,这样的目的
方便我们在后续要生成大小不同的棋盘时,方便更改

#define ROW 9
#define COL 9
#define ROWS COL+2
#define COLS ROW+2
	char mine[ROWS][COLS] = {
    
     0 };
	char show[ROWS][COLS] = {
    
     0 };

2)初始化棋盘

void InitBoard(char board[ROWS][COLS], int rows, int cols, char temp);

因为我们自己程序运行的界面和展示给用户的界面内容并不相同,所以在定义函数时,多声明一个变量,来应对不同的情况
我们程序内部有雷则是‘1’,没有雷则是‘0’
而展示给用户所看到的当然不能是‘0’和‘1’,否则用户相当于在睁眼猜数字。

void InitBoard(char board[ROWS][COLS], int rows, int cols, char temp)
{
    
    
	int i = 0, j = 0;
	for (i = 0; i < rows; i++)
	{
    
    
		for (j = 0; j < cols; j++)
		{
    
    
			board[i][j] = temp;

		}
	}
}

3)展示初始化后的棋盘

void DisplayBoard(char board[ROWS][COLS], int row, int col);

在这里插入图片描述

void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
    
    
	int i = 0;
	int j = 0;
	printf("----------扫雷------------\n");
	
	for (i = 0; i <= row; i++)
		printf("%d ", i);
	//为棋盘生成列标号 方便后续玩家进行操作
	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");
}

4)埋雷

void SetMine(char mine[ROWS][COLS], int row, int col);

这里我们使用EASYCOUNT,在头文件中预先定义

#define EASYCOUNT 10  //定义雷的个数
void SetMine(char mine[ROWS][COLS], int row, int col)
{
    
    
   //定义雷的个数
	int count = EASYCOUNT;

	while (count)
	{
    
    
       //使用srand()函数来随机生成我要存放雷的位置
		int x = rand() % row + 1;
		int y = rand() % col + 1;
		//当我们行数和列数
		if (mine[x][y] == '0')
		//如果此位置没有雷时
		{
    
    
			mine[x][y] = '1';
			//此位置放上雷
			count--;
			//未放置雷的个数减一 直至所有雷都放置完毕
		}
	}
}

在埋完雷之后,我们展示一下我们系统所能看见的棋盘界面
当然这个界面不能为用户展示

DisplayBoard(mine, ROW, COL);

1代表雷 0代表没有雷
在这里插入图片描述

5)找雷

 用户输入一个坐标,我们要实现两件事
 该位置是否有雷   
        1.有雷-----爆炸,游戏结束
        2.没有雷----显示该位置九宫格内雷的个数
//查找雷
void FindMine(char mine[ROWS][COLS], char  show[ROWS][COLS], int row, int col);
//判断x,y坐标位置九宫格内雷的个数
int GetMineCount(char mine[ROWS][COLS], int x, int y);
void FindMine(char mine[ROWS][COLS], char  show[ROWS][COLS], int row, int col)
{
    
    
	int x, y;
	int win = 0;
	//这里定义一个变量win  当我们每排查一次,并且该位置没有雷,则win++
	while (win < row * col - EASYCOUNT)
	//row*col代表一个棋盘可以存在雷的数量
	//EASYCOUNT代表雷的个数
	//相减即是没有雷的个数
	//当我们排查的次数小于没有雷的个数
	//即没有把雷排查完,则循环一直进行,直至排查完所有的雷
	{
    
    
		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
			//如果此处没有雷,则该位置显示周围九宫格内雷的个数
			{
    
    
				int c = GetMineCount(mine, x, y);
				show[x][y] = c + '0';
				DisplayBoard(show, ROW, COL);
				win++;
			}
		}
		else
		{
    
    
			printf("非法输入,请重新输入->\n");
		}
	}
	
	if (win == row * col - EASYCOUNT)
	//已经把没有雷的位置全部找出了
	{
    
    
		printf("恭喜你,排雷成功\n");
		DisplayBoard(mine, ROW, COL);
	}

}

判断x,y坐标位置九宫格内雷的个数

int 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';
}

我们实操一下
1.查找的位置没有雷
输入位置坐标2 6
该位置没有雷,并且周围也没有雷,则我们继续
在这里插入图片描述
2.排查的位置是雷
在这里插入图片描述

完整代码

game.h

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<time.h>
#include<stdlib.h>

#define ROW 9
#define COL 9
#define ROWS COL+2
#define COLS ROW+2
#define EASYCOUNT 10  //定义雷的个数

void InitBoard(char board[ROWS][COLS], int rows, int cols, char temp);

void DisplayBoard(char board[ROWS][COLS], int row, int col);

void SetMine(char mine[ROWS][COLS], int row, int col);

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

int GetMineCount(char mine[ROWS][COLS], int x, int y);

game.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"

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

		}
	}
}

void SetMine(char mine[ROWS][COLS], int row, int col)
{
    
    
	int count = EASYCOUNT;

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

//展示棋盘
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
    
    
	int i = 0;
	int j = 0;
	printf("----------扫雷------------\n");
	for (i = 0; i <= row; i++)
		printf("%d ", i);
	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");
}

int 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, y;
	int win = 0;
	while (win < row * col - EASYCOUNT)
	{
    
    
		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
			{
    
    
				int c = GetMineCount(mine, x, y);
				show[x][y] = c + '0';
				DisplayBoard(show, ROW, COL);
				win++;
			}
		}
		else
		{
    
    
			printf("非法输入,请重新输入->\n");
		}
	}
	if (win == row * col - EASYCOUNT)
	{
    
    
		printf("恭喜你,排雷成功\n");
		DisplayBoard(mine, ROW, COL);
	}

}

test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void menu()
{
    
    
	printf("*********************\n");
	printf("*** 1. play     *****\n");
	printf("*** 0. exit     *****\n");
	printf("*********************\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(show, ROW, COL);
	//埋雷
	SetMine(mine, ROW, COL);
	DisplayBoard(mine, ROW, COL);
	//找雷
	FindMine(mine, show, ROW, COL);
	DisplayBoard(show, ROW, COL);
	return;

}
int main()
{
    
    
	srand((unsigned int)time(NULL));

	int input = 0;
	menu();
	printf("请输入你的选择->");
	scanf("%d", &input);
	switch (input)
	{
    
    
	case 1:
		game();
		break;
	case 0:
		printf("退出扫雷\n");
		break;

	default:
		printf("输入错误,请重新输入->");

	}
	return 0;
}

码字不易,期待你的点赞,关注和收藏。
有什么好的建议欢迎在评论区提出0.0

猜你喜欢

转载自blog.csdn.net/2202_75795446/article/details/133818489
今日推荐