2024年C C++最新【C语言】扫雷—初学者也能写的小游戏,2024年最新C C++开发手册

img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

}


> 
> srand((unsigned int)time(NULL)); 对于这句话后面会讲到
> 
> 
> 


* ###### 上述代码分为 ——— 三部分

 1.打印菜单  
 2.接收字符  
 3.判断状态

 为了一打开程序就进入游戏状态  
 所以用了 **do{}while{}** 循环


1.打印菜单调用 emnu()函数



    void emnu()
    {
    	printf("\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\n");
    	printf("\*\*\*\*\*\*\* 1.play \*\*\*\*\*\*\*\n");
    	printf("\*\*\*\*\*\*\* 0.exly \*\*\*\*\*\*\*\n");
    	printf("\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\n");
    }

2.接收字符



    我们在循环外部定义 
        int input = 0;  接收指令的变量
    
        scanf("%d",&input);  接收键盘输入的函数
            注意:
                %d后面不要加空格 
                 & 符号不要忘记写

3.判断接收字符的状态



    switch(整形表达式) 
    {
        case 整形常量表达式:
            break; //跳出switch 去下面的while中判断是否继续循环
        case 0:
            break;
        default://相当于if语句中的else的作用
                //当上面的语句都不满足时 执行此语句
            break;
    }while(input); //input为0时结束游戏
    
输入1       继续游戏
输入0       结束游戏
输入错误    给出提示并从新输入

* ###### 当你想验证一下现在写的代码时


	+ 可以在game.h中引入头文件
	+ 并且在test.c中引入game.h头文件
	+ 这样所有头文件都放在game.h中就可以了game.h

 
#pragma once
#include <stdio.h>
 

在头文件中 第一行 写入#pragma once
在其他文件中不管包含几次<stdio.h>都只拷贝一次
是为了防止头文件重复 做无用功

 test.c

 
#include "game.h"


###### 经过上面的代码 可以在case 1: 中调用函数game()


#### ganme()分为——五部分


* 1.创建雷区
* 2.初始化
* 3.打印初始化
* 4.生成雷
* 5.排查雷


##### 1.创建雷区



> 
> test.c
> 
> 
> 



void game()
{
	char LQu[ROWS][COLS]; 存放雷的信息
	char PCha[ROWS][COLS]; 排查雷的信息
}

###### so easy 有没有 雷区创建好了


##### 2.初始化雷区



void game()
{
	//创建雷区
	char LQu[ROWS][COLS]; //存放雷的信息
	char PCha[ROWS][COLS];//排查雷的信息

	//初始化
	CShi(LQu, ROWS, COLS,'0');//雷区
	CShi(PCha,ROWS, COLS,'\*');//排查区

	//打印初始化
	//DY(LQu, ROW, COL);//雷区
	printf("共有%d个雷\n",LEI);

	DY(PCha, ROW, COL);//排查区

	//生成雷
	S\_L(LQu, ROW, COL,LEI);
	printf("\n");
	//DY(LQu, ROW, COL);//雷区

	//排查雷
	P\_C(LQu,PCha, ROW, COL);
	DY(PCha, ROW, COL);//排查区
}

###### 可以看到创建雷区 用到了两个数组 LQu PCha


###### 先看下game.h中的代码



> 
> game.h
> 
> 
> 



#pragma once

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


#define ROW 9
#define COL 9

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

#define LEI 10


//初始化
void CShi(char CShi[ROWS][COLS], int rows, int cols,char ret);//雷区

###### 上述数组用到了两个 常量ROWS、COLS 怎么来的?



这里用到5个变量,用#define定义
#define 定义全局变量

ROW 为用户可见区域 横坐标
COL 为用户可见区域 纵坐标 
ROWS  为底层排雷区域 横坐标
COLS  为底层排雷区域 纵坐标
LEI  为雷的个数

为什么分为 ROW 和 ROWS 呢
我们开头说到 比如是9\*9 的格子
在扫描雷的时候要扫描坐标在内的周围的9个格子
如下:
    \* \* \* 
    \* n \*
    \* \* \*
整体的布局:(ROW,COL)
0 1 2 3 4 5 6 7 8 9
1 \* \* \* \* \* \* \* \* \*
2 \* \* \* \* \* \* \* \* \*
3 \* \* \* \* \* \* \* \* \*
4 \* \* \* \* \* \* \* \* \*
5 \* \* \* \* \* \* \* \* \*
6 \* \* \* \* \* \* \* \* \*
7 \* \* \* \* \* \* \* \* \*
8 \* \* \* \* \* \* \* \* \*
9 \* \* \* \* \* \* \* \* \*

但是:
    左上(1,1),左下(1,9),右上(9,1),右下(9,9).....
    这几个坐标访问时就越界了
所以:
    我们在底层代码扫描时 把上下左右都加上一行
    这时访问数组时就不会出现越界了
    也就有了ROWS、COLS 这两个变量
        #define ROW 9
        #define COL 9

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

###### game.h 中下方还有一行代码——初始化 (下)



> 
> 左右滑动查看代码
> 
> 
> 



> 
> test.c
> 
> 
> 



char LQu[ROWS][COLS]; //存放雷的信息 定义数组
char PCha[ROWS][COLS];//排查雷的信息 定义数组


//需要初始化的代码:
CShi(LQu, ROWS, COLS,‘0’);//雷区
CShi(PCha,ROWS, COLS,‘*’);//排查区
这样设计用一个函数传参 就能给不同数组 初始化成不同的 字符



> 
> game.h
> 
> 
> 



//初始化
void CShi(char CShi[ROWS][COLS], int rows, int cols,char ret);//雷区


    函数返回类型 不需要返回值 所以为 void
    数组传参 接收一个数组 用char CShi[][]数组接收
    ROWS COLS 是整形 用int 类型变量接收
    后面的 '0' '\*' 用char 字符类型接收  

    
因为排查雷需要更大的数组 所以用到了 ROWS COLS
test.c      中定义函数
game.h      声明函数
game.c      实现代码


> 
> game.c
> 
> 
> 



#include "game.h"

//初始化雷区
void CShi (char CShi[ROWS][COLS], int rows, int cols,char ret)
{
	int i = 0;
	for (i = 0; i < rows; i++)
	{
		int j = 0;
		for (j = 0; j < cols; j++)
		{
			CShi[i][j] = ret;
		}
	}
}


用for循环将两个数组初始化成全0  全\*
CShi(LQu, ROWS, COLS,'0');
0 1 2 3 4 5 6 7 8 9 a b
1 0 0 0 0 0 0 0 0 0 0 0
2 0 0 0 0 0 0 0 0 0 0 0
3 0 0 0 0 0 0 0 0 0 0 0
4 0 0 0 0 0 0 0 0 0 0 0
5 0 0 0 0 0 0 0 0 0 0 0
6 0 0 0 0 0 0 0 0 0 0 0
7 0 0 0 0 0 0 0 0 0 0 0
8 0 0 0 0 0 0 0 0 0 0 0
9 0 0 0 0 0 0 0 0 0 0 0
a 0 0 0 0 0 0 0 0 0 0 0
b 0 0 0 0 0 0 0 0 0 0 0
这一层布置雷 扫雷

CShi(PCha,ROWS, COLS,'\*');
0 1 2 3 4 5 6 7 8 9 a b
1 \* \* \* \* \* \* \* \* \* \* \*
2 \* \* \* \* \* \* \* \* \* \* \*
3 \* \* \* \* \* \* \* \* \* \* \*
4 \* \* \* \* \* \* \* \* \* \* \*
5 \* \* \* \* \* \* \* \* \* \* \*
6 \* \* \* \* \* \* \* \* \* \* \*
7 \* \* \* \* \* \* \* \* \* \* \* 
8 \* \* \* \* \* \* \* \* \* \* \*
9 \* \* \* \* \* \* \* \* \* \* \*
a \* \* \* \* \* \* \* \* \* \* \*
b \* \* \* \* \* \* \* \* \* \* \*
这一层打印出来给用户看 当然不是打印11\*11  是打印9\*9 后面会说到
(16进制  a=10 b=11 c=12 d=13 e=14 f=15)

##### 3.打印初始化



> 
> test.c
> 
> 
> 



//打印初始化
DY(PCha, ROW, COL);//排查区
printf("共有%d个雷\n",LEI); //告诉用户有几个雷


> 
> game.h
> 
> 
> 



//打印初始化
void DY(char LQu[ROWS][COLS],int rows,int cols);//雷区


传参上面讲了 同理


###### 这里要强调的是传参的时候用的是ROW COL



因为打印出来的是要给用户观察的
ROW COL 定义的为9
所以要打印9\*9 的个格子 

聪明的你要问了:怎么才能在11\*11 的数组中打印9\*9 的格子呢?

你: 我才没问呢  我都知道!

你: 只要在数组下标为1 的地方打印到下标10就可以啦

你真是个机灵鬼!!!


> 
> game.c
> 
> 
> 



//打印
void DY(char LQu[ROWS][COLS], int row, int col)
{
	int i = 0;
	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 ", LQu[i][j]);
		}
		printf("\n");
	}
	printf("\n");
}


上述代码 第一个循环 是打印出了每行的编号 为了方便观察
下面的代码 也在每一行的首元素打印了编号
最后for循环打印的数组初始化的内容

打印结果如下:DY(PCha, ROW, COL);
        共有10个雷
        0 1 2 3 4 5 6 7 8 9
        1 \* \* \* \* \* \* \* \* \*
        2 \* \* \* \* \* \* \* \* \*
        3 \* \* \* \* \* \* \* \* \*
        4 \* \* \* \* \* \* \* \* \*
        5 \* \* \* \* \* \* \* \* \*
        6 \* \* \* \* \* \* \* \* \*
        7 \* \* \* \* \* \* \* \* \*
        8 \* \* \* \* \* \* \* \* \*
        9 \* \* \* \* \* \* \* \* \*

#### 4.生成雷



> 
> test.c
> 
> 
> 



//生成雷
S\_L(LQu, ROW, COL,LEI); 
printf("\n");


> 
> game.h
> 
> 
> 



//生成雷
void S\_L(char LQu[ROWS][COLS], int row, int col,int lei);


> 
> game.c
> 
> 
> 



//生成雷
void S\_L(char LQu[ROWS][COLS], int row, int col,int lei)
{

	int i = lei;
	while(i)
	{
		int x = rand() % row+1;
		int y = rand() % col+1;

		if (LQu[x][y] != '1')
		{
			LQu[x][y] = '1';
			i--;
		}
	}
}


思路:
    1.x y在规定坐标内 生成随机数
    一个随机数%10 则得到的结果不会大于10 也就是最大得到9
    2.在随机产生的坐标中放入字符'1'

###### 产生随机数rand()



在主函数中调用srand()
srand((unsigned int)time(NULL));
接收time系统时间 强制准换成无符号整型(unsigned int)

srand() 的头文件    <stdlib.h>
time()  的头文件    <time.h>

此时就可以在已经声明的范围内 使用rand()


> 
> #### 还差一步就完成啦 ٩(๑>◡<๑)۶ 加油!
> 
> 
> 


#### 5.排查雷


###### 败北:坐标 = ‘1’


###### 胜利:输入坐标 = 坐标 - 雷



> 
> test.c
> 
> 
> 



//排查雷
P\_C(LQu,PCha, ROW, COL);
DY(PCha, ROW, COL);//打印排查区


> 
> game.h
> 
> 
> 



//排查雷
char P\_C(char LQu[ROWS][COLS], char PCha[ROWS][COLS], int row, int col);


> 
> game.c
> 
> 
> 



//判断周围的雷数
int LS(char LQu[ROWS][COLS], int x,int y)
{
	return (LQu[x-1][y]
		+ LQu[x - 1][y - 1]
		+ LQu[x][y - 1]
		+ LQu[x + 1][y - 1]
		+ LQu[x + 1][y]
		+ LQu[x + 1][y + 1]
		+ LQu[x][y + 1]
		+ LQu[x - 1][y + 1]
		- 8 \* '0');
}

//排查
char P\_C(char LQu[ROWS][COLS], char PCha[ROWS][COLS], int row, int col)
{
	int x = 0;//横坐标
	int y = 0;//纵坐标
	int win = 0; //输入坐标次数
	//判断坐标合法
	while (win<row\*col-LEI)
	{
		printf("请输入坐标:");
		scanf("%d %d", &x, &y);

		//排查雷
		if ((x > 0 && x <=row) && (y > 0 && y <=col))
		{
			if (LQu[x][y] != '1')
			{
				//判断周围有几个雷
				int L = LS(LQu, x, y);
				PCha[x][y] = (L+'0');
				DY(PCha, ROW, COL);//打印排查区

				win++;
			}
			else
			{
				printf("很遗憾,你输了\n\n");
				DY(LQu, ROW, COL);//打印雷区

				break;
			}
		}

		else
		{
			printf("坐标非法,请重新输入!\n\n");
		}
	}
	if (win == ROW \* COL - LEI)
	{
		printf("恭喜你胜利了\n\n");
	}
}

解释说明:



x       横坐标
y       纵坐标
win     输入坐标数

当输入坐标次数 < 雷区-雷
    接收坐标;
    如果: x y 符合要求
        如果:底层坐标xy != '1'
            则判断周雷数
            函数() - 下面单独讲
            假如返回数字 3
            打印时需要打印字符'3' - 下面单独讲
            打印雷区;
            win++;
        否则:
            游戏败北
            打印雷区
            跳出
    否则:
        重新输入

当输入坐标次数 = 雷区-雷
    恭喜胜利!

###### 首先是函数



int LS(char LQu[ROWS][COLS], int x,int y)
{
	return (LQu[x-1][y]
		+ LQu[x - 1][y - 1]
		+ LQu[x][y - 1]
		+ LQu[x + 1][y - 1]
		+ LQu[x + 1][y]
		+ LQu[x + 1][y + 1]
		+ LQu[x][y + 1]
		+ LQu[x - 1][y + 1]
		- 8 \* '0');
}


在ASCII码表中
'0' = 48
'1' = 49
'2' = 50
'3' = 51
所以在字符'1' - 字符'0' = (59-48 = 1)
用%d打印就能打印出数字1;

计算雷的个数 因为雷用'1'表示

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

    int LS(char LQu[ROWS][COLS], int x,int y)
    {
    	return (LQu[x-1][y]
    		+ LQu[x - 1][y - 1]
    		+ LQu[x][y - 1]
    		+ LQu[x + 1][y - 1]
    		+ LQu[x + 1][y]
    		+ LQu[x + 1][y + 1]
    		+ LQu[x][y + 1]
    		+ LQu[x - 1][y + 1]
    		- 8 \* '0');
    }

    在ASCII码表中
    '0' = 48
    '1' = 49
    '2' = 50
    '3' = 51
    所以在字符'1' - 字符'0' = (59-48 = 1)
    用%d打印就能打印出数字1;
    
    计算雷的个数 因为雷用'1'表示


[外链图片转存中...(img-oEbfisaF-1715557440299)]
[外链图片转存中...(img-kHjjpcZZ-1715557440299)]

**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**[需要这份系统化的资料的朋友,可以添加戳这里获取](https://bbs.csdn.net/topics/618668825)**


**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值