控制版c语言扫雷喵 虽然写的可能不太好,但是是我理解的大白话的思路,可以借鉴一下

目录

1.制作一个简易的菜单

2.创建数组

3.对数组进行初始化

4.打印棋盘

5.布置雷

6.排查雷


1.第一步

在这个之前,要创建三个文件,test.c ,game.c , game.h

分开文件放可以更加整洁,更加利于理解,每个文件实现对应的功能

game.c 放游戏的逻辑实现, game.h 放函数声明和 头文件

2.第一行的#include "game.h" ,我把头文件放到game.h

3.menu();不需要传参数也不要返回值,所以void menu()

#include <stdio.h>

#include "game.h"

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


int main()
{
	int input = 0;
	do
	{
		menu();
		printf("请选择喵:");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏喵...");
			break;
		default:
			printf("输入错误,请重新输入:\n");
			break;
		}
	} while (input);
	
	return 0;
}

do—while循环,用input变量,来控制循环是否会继续,它可以在使用前就先运行代码一次,我们用这个特性就可以先打印一遍菜单。假如输入1就会进入循环,因为在循环中,不是0的数为真(非0为真),0则为假,为假就不会执行

switch判断语句,再让用户输入1或者0来判断,1开始游戏,0结束提出,假如输入了3, 8,9等等其他的数就会让用户再次输入(再次输入是因为input的值是1,会一直循环)

2.创建数组

这里的game();就有用了,void无返回值的类型,不需要return返回值

创建两个数组,注意观察创建的类型是char类型的,每个坐标只存放一个字符

mine,布置雷,雷是不可看见了。

show,用来排查的,用户可以看见的

ROWS和COLS,是我们定义的两个宏,叫做不带参数的宏,

#define 标识符 字符串,宏的基本格式

这个也是定义在game.h里面,我们要创建的是一个9*9的棋盘,要排查雷的数量是10个

在下面的数组创建中就可以直接用了,行和列都是11,初始化为全0
因为要做逻辑运算,假如要排查9行7列的数,就会发现溢出了,所以是要创建11*11

防止溢出。

game.h部分的

#include <stdio.h>

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

test.c 部分的 

void game()
{
	//创建数组喵,mine布置雷,show可视化,初始化为0
	char mine[ROWS][COLS] = {0};
	char show[COLS][COLS] = {0};

}

3.对数组进行初始化

初始化函数,布置雷的棋盘一个需要初始化为全为字符‘0’,show,未排查的雷要初始化为全‘ * ’。

mine初始化为全0,是因为后面每次布置一个雷就要是字符‘ 1 ’,代表一个雷

3.1.这边传的参数是数组,棋盘行,列,需要初始化的实参

game.h ,这里就偷个懒啦,先把要声明的头文件都放这里,这里不用看很仔细,到后面就知道了

每个函数在用前都要声明这个。变量的类型和参数,告诉程序。

这里也就解释了最开头的 #include "game.h"。这样就可以找到定义了

#include <stdio.h>

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

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

#define EASY_COUNT 10

//数组初始化
void InitBoard(char arr[ROWS][COLS],int rows,int cols, char set);

//打印数组
void DisplayBoard(char arr[ROWS][COLS], int row, int col);

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

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

 test.c

void game()
{
	//创建数组喵,mine布置雷,show可视化,初始化为0
	char mine[ROWS][COLS] = {0};
	char show[COLS][COLS] = {0};

	//对数组进行初始化
	InitBoard(mine, ROWS, COLS, '0');
	InitBoard(show, ROWS, COLS, '*');
}

game.h,部分的

3.2.形参,收到char数组,行和列,初始化的参数

初始化通过两个for循环遍历的每个地方。每遍历到一个位置就放入,set也就是传过来的字符

#include "game.h"

//初始化棋盘,函数的函数就是形参是变化的,但是实参不是变化的
void InitBoard(char arr[ROWS][COLS], int rows, int cols, char set)
{
	int i = 0;
	//要经过大脑思考不要盲目敲代码啊
	for (i = 0; i < rows; i++)
	{
		int j = 0;
		for (j = 0; j < cols; j++)
		{
			arr[i][j] = set;
		}
	}
}

4.打印棋盘

竟然初始化了数组中的数,接下来就要打印初始化好的数组,打印数组可以用同样的思路

有双层for循环遍历整个数组,来看看是否初始化成功

两个数组,mine和show,这里注释掉了,因为后面要布置雷的。如果要看有没有初始化成功也可以打印看看

test.c

void game()
{
	//创建数组喵,mine布置雷,show可视化,初始化为0
	char mine[ROWS][COLS] = {0};
	char show[COLS][COLS] = {0};

	//对数组进行初始化
	InitBoard(mine, ROWS, COLS, '0');
	InitBoard(show, ROWS, COLS, '*');

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

game.c

4.1.注意这里前面的第一个for循环,是为美化一下棋盘用数字来标记列号的,这个是在数组打印前就输出的,然后用\n换行。

4.2.排查雷的部分是9*9,做逻辑运算的是11*11,所以传过来的值是ROW和COL。

下面的双层是用来打印数组的,下面有一个printf(“%d  ”,i);用来打印行号的,在每次数组的行开始打印前的。

数组的每个打印完要空格有间距视觉上会好一些printf(“%d  ”,arr[ i ][ j ]);。每行打印完也要换行

这个arr[ i ][ j ]是当遍历到当前位置时。

//打印棋盘,做逻辑运算的是创建的数组,显示需要排查的雷的是9*9的部分
void DisplayBoard(char arr[ROWS][COLS], int row, int col)
{
	int i = 0;
		for (i = 0; i <= col; i++)
		{
			printf("%d ",i);
		}
		printf("\n");
	for (i = 1; i <= row; i++)
	{
		printf("%d ", i);//打印行号
		int j = 0;
		for (j = 1; j <= col; j++)
		{
			printf("%c ", arr[i][j]);
		}
		printf("\n");
	}
}

最后的调试结果就是这样的喵

5.布置雷

test.c 

5.1布置雷,要布置完才知道,所以打印要放布置前才行。不然棋盘都打印完了,雷去哪里布置?

void game()
{
	//创建数组喵,mine布置雷,show可视化,初始化为0
	char mine[ROWS][COLS] = {0};
	char show[COLS][COLS] = {0};

	//对数组进行初始化
	InitBoard(mine, ROWS, COLS, '0');
	InitBoard(show, ROWS, COLS, '*');

	//布置雷
	SetMine(mine, ROW, COL);

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

game.c

5.2.布置雷是mine,9*9内

5.3.第一步首先,EASY-COUNT定义一个宏表示10个雷,放在3.2

5.4.先用一个while循环,每成功布置一次雷就count--,知道为0,循环结束,rand一个生成随机数的函数,一般这个函数是需要srand函数,用这个来获取种子,一般是要搭配使用。

在程序的最开头设置,time是获取一个时间戳,1970—现在的总共的秒数,但是返回的类型是time_s,所有用unsigned,强制转换成无符号整型。rand需要的值是个无符号整型

int main()
{
	//在程序的最开始位置设置种子
	srand((unsigned)time(NULL));
	int input = 0;

5.5.int x = rand() % row + 1,row是9,所以余数是0—8。+1,余数就会变为1—9,假设余数是8,它就要+1,变成9。通过rand产生的随机值就可以x 和 y的地址

5.6.然后if,判断这个地址里面是“0”,是就布置,并且count - -。

//布置雷,按照逻辑来讲,布置雷要在打印棋盘之前
void SetMine(char arr[ROWS][COLS], int row, int col)
{
	int count = EASY_COUNT;//创建一个变量,来计数,EASY_COUNT,表示要布置10个雷
	while (count)//不等于0,时会一直循环
	{
		int x = rand() % row + 1;//通过随机数,在棋盘上随机布置雷
		int y = rand() % col + 1;//row和col控制范围

		if (arr[x][y] == '0')//如果该坐标是'0',就布置雷
		{
			arr[x][y] = '1';
			count--;//每布置成功一次就-1
		}
	}
}

最后的效果实现,查看一下雷布置的结果,但是只是测试看一下 

6.排查雷

test.c

void game()
{
	//创建数组喵,mine布置雷,show可视化,初始化为0
	char mine[ROWS][COLS] = {0};
	char show[COLS][COLS] = {0};

	//对数组进行初始化
	InitBoard(mine, ROWS, COLS, '0');
	InitBoard(show, ROWS, COLS, '*');

	//布置雷
	SetMine(mine, ROW, COL);

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

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

game.c

首先要看排查雷的部分,

6.1.先定义两个变量,先判断坐标的有效性n m换成x和y的更好理解,假如不在9*9的棋盘内,输入错误

6.2.输入的坐标正确,但是被炸死了,就是mine[n][m] == '1',挑战失败,并且打印布置雷的棋盘,让你输的心服口服

6.3.没有被炸死,就要统计这个坐标的周围有几个雷,然后放到show这个棋盘中

GetMineCount(mine, n, m);通过这个函数来统计周围有几个雷

假设坐标是3 6

 6.4,每次遍历到该位置,就—‘0’,因为字符'1'的ASCLL码值是60,字符‘0’的ASCLL是59

它两相减的差值是1,有几个雷就会返回几。放到count计数,这个函数是int类型的需要返回值

6.5然后再将返回值用ct装起来,ct+‘0’,转换成对应字符,然后放到show这个棋盘中。

6.6,win++,每排查完一个雷就+1,用while来,win < row * col - EASY_COUNT,9*9的棋盘-雷的数量81-10=71,小于71会一直执行直到雷排查完

6.7.最后一步就是雷都都排查完了,win == row * col - EASY_COUNT,正好是一个雷都不剩了

恭喜你!,挑战成功

int GetMineCount(char mine[ROWS][COLS], int n,int m)
{
	int count = 0;
	for (int i = n - 1; i <= n + 1; i++)
	{
		for (int j = m - 1; j <= m + 1; j++)
		{
			 count = mine[i][j] - '0';
		}
	}
	return count;
}


//排查雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
	int n = 0;
	int m = 0;
	int win = 0;
	while (win < row * col - EASY_COUNT)
	{
		printf("请输入你要排查的坐标:");
		scanf("%d %d", &n, &m);
		if (n >= 1 && n <= 9 && m >= 1 && m <= 9)
		{
			//输入正确后
			if (mine[n][m] == '1')
			{
				printf("挑战失败\n");
				DisplayBoard(mine, ROW, COL);
				break;
			}
			else
			{
				int ct = GetMineCount(mine, n, m);
				show[n][m] = ct + '0';//转换成字符
				DisplayBoard(show, ROW, COL);
				win++;//每排查完一个就++
			}
		}
		else
		{
			printf("输入错误,请重新输入:");
		}
	}
	if (win == row * col - EASY_COUNT)
	{
		printf("挑战成功\n");
		DisplayBoard(mine, ROW, COL);
	}

 最终效果,多多实操、頑張る

后续的扩展功能,等我学习一下再来吧,喵喵

有些地方不好,会慢慢改进的--_--

  • 23
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值