文章目录
前言
每日鸡汤
我们到底为什么学习?
核心观点学习的目的,是为了获取竞争优势,增加选择机会,提升认知水平。人生就是一个不断学习的过程,终究有一天,我们会感谢现在努力学习的自己,加油吧!少年,将来的你终究会感谢努力学习的自己!
基本思路
一.框架与打印菜单
当你打印菜单过后,会面临的选项,你要进行输入所对应功能的选项,时进行对应的功能,所以开始的框架必不可少,好的开始是成功的一半,接下来让我们实现它吧!
1.实现功能的分装
实现逻辑在一个源文件中,运行逻辑在另一个源文件中,可以更好地让我们的思路更加的清晰,而实现逻辑的函数声明与所需要的define与include(包含的c语言的头文件)等预处理要放在头文件中,因为这个头文件是驾起两个源文件的桥梁,并且方便数据的修改也可以起到化繁为简的作用。
如图:
代码的实现:
#define _CRT_SECURE_NO_WARNINGS 1
#include"mine.h"//包含的
int main()
{
int judge = 0;
do
{
menu();
scanf("%d", &judge);
switch (judge)
{
case 1:
printf("扫雷开始\n");//这里是扫雷的实现逻辑
break;
case 2:
printf("成功退出扫雷\n");
break;
default:
printf("输入错误,请重新输入!\n");
break;
}
}while(judge!=2);
return 0;
}
2.菜单
下面这是实现逻辑的源文件放的函数。
void menu()
{
printf("**************************\n");
printf("****** 1.开始扫雷 *******\n");
printf("****** 2.退出扫雷 *******\n");
printf("**************************\n");
}
在头文件放函数的声明以及所需的头文件
#include<stdio.h>//这里如果两个源文件都要使用,只需包含项目头文件mine.h即可
void menu();
二.设置雷盘(11*11)
我们先看一下雷盘
这是9*9的雷盘,但你是否会想到当进行扫雷的时候,排查雷的时候如果是边上的雷和中间的雷有什么区别呢?
当边上的雷我们只会排查它周围的几个雷,而中间的则会排查周围的八个雷,试想一下,倘若这是个11 11的数组时,再进行我们再来检查一下
当你再在原来的棋盘(蓝色的部分)进行排查,周围的白色部分,都没有雷,这时,结果是不是还跟原来一样?结果不变,当我们只使用中间的99时,输入坐标是不是跟我们平常的一样(想一下数组下标的规则)?那这是不是一石二鸟?,so我们看一下实现思路,这里为了方便我们使用两个数组,一个是打印信息的数组,一个是存放雷的数组。
代码实现:
头文件
#define _CRT_SECURE_NO_WARNINGS 1
#define ROW 9//打印的行
#define COL 9//打印的列
#define ROWS (ROW+2)//实际的行
#define COLS (COL+2)//实际的列
#include<stdio.h>
//函数的声明
void menu();
void Initboard(char board[ROWS][COLS],int rows ,int cols , char letter);
实现逻辑的文件
void Initboard(char board[ROWS][COLS], int rows, int cols, char letter)
{
int i = 0;
int j = 0;
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
board[i][j] = letter;
}
}
}
运行逻辑的文件
#define _CRT_SECURE_NO_WARNINGS 1
#include"mine.h"
void game()
{
char mine[ROWS][COLS] = { 0 };
char show[ROWS][COLS] = { 0 };
//初始化雷盘
Initboard(mine ,ROWS,COLS,'0');//这是里设置第四个参数是为了更好的体现函数的兼容性
Initboard(show, ROWS, COLS, '*');
}
int main()
{
int judge = 0;
do
{
menu();
scanf("%d", &judge);
switch (judge)
{
case 1:
game();//这里是扫雷的实现逻辑
break;
case 2:
printf("成功退出\n");
break;
default:
printf("输入错误,请重新输入!\n");
break;
}
}while(judge!=2);
return 0;
}
三.打印雷盘(9*9)
我们只需打印出9*9的雷盘即可。
实现代码
头文件
#define _CRT_SECURE_NO_WARNINGS 1
#define ROW 9
#define COL 9
#define ROWS (ROW+2)
#define COLS (COL+2)
#include<stdio.h>
void menu();
void Initboard(char board[ROWS][COLS],int rows ,int cols , char letter);
void Showboard(char board[ROWS][COLS], int row, int col);
实现逻辑的文件
#define _CRT_SECURE_NO_WARNINGS 1
#include"mine.h"
void menu()
{
printf("**************************\n");
printf("****** 1.开始扫雷 *******\n");
printf("****** 2.退出扫雷 *******\n");
printf("**************************\n");
}
void Initboard(char board[ROWS][COLS], int rows, int cols, char letter)
{
int i = 0;
int j = 0;
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
board[i][j] = letter;
}
}
}
void Showboard(char board[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
for (i = 1; i <=row; i++)
{
for (j = 1; j <= col; j++)
{
printf("%c ", board[i][j]);
}
printf("\n");
}
}
运行逻辑的文件
#define _CRT_SECURE_NO_WARNINGS 1
#include"mine.h"
void game()
{
char mine[ROWS][COLS] = { 0 };
char show[ROWS][COLS] = { 0 };
//初始化雷盘
Initboard(mine ,ROWS,COLS,'0');
Initboard(show, ROWS, COLS, '*');
//打印雷盘
Showboard(mine, ROW, COL);
Showboard(show, ROW, COL);
}
int main()
{
int judge = 0;
do
{
menu();
scanf("%d", &judge);
switch (judge)
{
case 1:
game();//这里是扫雷的实现逻辑
break;
case 2:
printf("成功退出\n");
break;
default:
printf("输入错误,请重新输入!\n");
break;
}
}while(judge!=2);
return 0;
}
看一下效果:
这里我们会发现,这里的会有一点瑕疵,就是当你输入坐标排查雷的时候,会出现坐标不清楚的时候,而且打印棋盘中间没有空隙,会比较不好看,为了解决以上的缺点,我们做一个优化,打印分割行与坐标。
效果:
代码:
void Showboard(char board[ROWS][COLS], int row, int col)
{
printf("----------扫雷---------\n");//打印分割行
int i = 0;
int j = 0;
printf(" ");//与雷盘进行对齐
for (i = 1; 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");
}
}
三.放置雷(10颗)
1.生成随机数
涉及的函数(头文件都为stdio.h)
函数1:srand()——类型为unsigned int
功能:设置随机数种子,设置一次即可
函数2:time()——类型为time_t
功能:生成从1970 年 1 月 1 日 00:00 小时(即当前 unix 时间戳)以来的秒数。
函数3:rand()
功能:生成0到32767的随机数,但并不是真的生成随机数,需要设置随机数种子。
代码实现:
运行逻辑的函数
int main()
{
srand((unsigned int)time(NULL));//生成随机数种子
int judge = 0;
do
{
menu();
scanf("%d", &judge);
switch (judge)
{
case 1:
game();//这里是扫雷的实现逻辑
break;
case 2:
printf("成功退出\n");
break;
default:
printf("输入错误,请重新输入!\n");
break;
}
}while(judge!=2);
return 0;
}
注意:
1.time不知道设什么值时,设为NULL
2.srand()里面的类型为unsigned int ,因此time的返回类型要强制类型转换为srand的返回类型。
2.生成随机坐标
int x = rand()%9+1;//生成1到9的随机数作为横坐标
int y = rand()%9*1;//生成1到9的随机数作为纵坐标
3.布置10颗雷
在布置雷时,若新生成的坐标与原来坐标相等,则要再生成一次,因此要满足条件再布置。
头文件:
#define _CRT_SECURE_NO_WARNINGS 1
#define ROW 9//打印的行
#define COL 9//打印的列
#define ROWS (ROW+2)//实际的行
#define COLS (COL+2)//实际的列
#define MINE 10//雷
#include<stdio.h>
//函数的声明
void menu();
void Initboard(char board[ROWS][COLS], int rows, int cols, char letter);
void Showboard(char board[ROWS][COLS], int row, int col);
void Setmine(char board[ROWS][COLS]);
代码实现:
void Setmine(char board[ROWS][COLS])
{
int count = 0;
while (count < MINE)
{
int x = rand() % 9 + 1;
int y = rand() % 9 + 1;
if (board[x][y] == '0')
{
board[x][y] = '1';
count++;
}
}
}
四.排查雷
1.具体思路
当我们输入的坐标满足情况时才可排查。
1.输入的坐标在雷盘范围
2.第二次输入的坐标不能与原坐标保持相同
3.查找的坐标不是雷
如果满足以上情况
查找坐标范围内的雷,并将其赋为周围的雷数,并打印雷盘。
查完雷或者被雷炸死跳出循环。
2.代码实现
//查找雷的个数
static int find(char board[ROWS][COLS],int x,int y)
{
int i = 0;
int j = 0;
int count = 0;
for (i = x-1; i <= x+1; i++)
{
for (j = y - 1; j <= y + 1;j++)
{
if (board[i][j] == '1')
{
count++;
}
}
}
return count;
}
static void is_win(int count)
{
if (count == ROW * COL - MINE)
{
printf("恭喜您取得游戏胜利!\n");
}
else
{
printf("游戏失败,很遗憾您被炸死了!\n");
}
}
void Findmine(char mineboard[ROWS][COLS], char showboard[ROWS][COLS], int row, int col)
{
int count = 0;
while (count<ROW*COL-MINE)//
{
int x = 0;
int y = 0;
printf("请输入坐标:");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= 9 && y >= 1 && y <= 9)
{
if (showboard[x][y] != '*')
{
printf("该坐标已被排查过了,请重新输入!\n");
continue;
}
if (mineboard[x][y] == '0')
{
int ret = find(mineboard, x, y);//查找雷的个数
showboard[x][y] = '0' + ret;
Showboard(showboard, ROW, COL);
count++;
}
else if (mineboard[x][y] == '1')
{
break;
}
}
else
{
printf("坐标非法,请重新输入!\n");
}
}
//循环终止或结束时跳到这里。
//1.赢的话count等于棋盘数减去雷的个数
//2.除了赢就是输
is_win(count);//判断输赢
}
尾序
头文件:mine.h
#define _CRT_SECURE_NO_WARNINGS 1
#define ROW 9//打印的行
#define COL 9//打印的列
#define ROWS (ROW+2)//实际的行
#define COLS (COL+2)//实际的列
#define MINE 10
#include<stdio.h>
//函数的声明
void menu();
void Initboard(char board[ROWS][COLS], int rows, int cols, char letter);
void Showboard(char board[ROWS][COLS], int row, int col);
void Setmine(char board[ROWS][COLS]);
void Findmine(char mineboard[ROWS][COLS],char showboard[ROWS][COLS] ,int row, int col);
运行逻辑的源文件:源.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"mine.h"
void game()
{
char mine[ROWS][COLS] = { 0 };
char show[ROWS][COLS] = { 0 };
//初始化雷盘
Initboard(mine ,ROWS,COLS,'0');
Initboard(show, ROWS, COLS, '*');
//布置雷
Setmine(mine);
//打印雷盘
Showboard(mine, ROW, COL);
Showboard(show, ROW, COL);
//排查雷
Findmine(mine, show, ROW, COL);
}
int main()
{
srand((unsigned int)time(NULL));//生成随机数种子
int judge = 0;
do
{
menu();
scanf("%d", &judge);
switch (judge)
{
case 1:
game();//这里是扫雷的实现逻辑
break;
case 2:
printf("成功退出\n");
break;
default:
printf("输入错误,请重新输入!\n");
break;
}
}while(judge!=2);
return 0;
}
实现逻辑的源文件:mine.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"mine.h"
static int find(char board[ROWS][COLS],int x,int y)
{
int i = 0;
int j = 0;
int count = 0;
for (i = x-1; i <= x+1; i++)
{
for (j = y - 1; j <= y + 1;j++)
{
if (board[i][j] == '1')
{
count++;
}
}
}
return count;
}
static void is_win(int count)
{
if (count == ROW * COL - MINE)
{
printf("恭喜您取得游戏胜利!\n");
}
else
{
printf("游戏失败,很遗憾您被炸死了!\n");
}
}
void menu()
{
printf("**************************\n");
printf("****** 1.开始扫雷 *******\n");
printf("****** 2.退出扫雷 *******\n");
printf("**************************\n");
}
void Initboard(char board[ROWS][COLS], int rows, int cols, char letter)
{
int i = 0;
int j = 0;
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
board[i][j] = letter;
}
}
}
void Showboard(char board[ROWS][COLS], int row, int col)
{
printf("----------扫雷---------\n");
int i = 0;
int j = 0;
printf(" ");
for (i = 1; 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");
}
}
void Setmine(char board[ROWS][COLS])
{
int count = 0;
while (count < MINE)
{
int x = rand() % 9 + 1;
int y = rand() % 9 + 1;
if (board[x][y] == '0')
{
board[x][y] = '1';
count++;
}
}
}
void Findmine(char mineboard[ROWS][COLS], char showboard[ROWS][COLS], int row, int col)
{
int count = 0;
while (count<ROW*COL-MINE)
{
int x = 0;
int y = 0;
printf("请输入坐标:");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= 9 && y >= 1 && y <= 9)
{
if (showboard[x][y] != '*')
{
printf("该坐标已被排查过了,请重新输入!\n");
continue;
}
if (mineboard[x][y] == '0')
{
int ret = find(mineboard, x, y);
showboard[x][y] = '0' + ret;
Showboard(showboard, ROW, COL);
count++;
}
else if (mineboard[x][y] == '1')
{
break;
}
}
else
{
printf("坐标非法,请重新输入!\n");
}
}
is_win(count);
}
总结
如果能认真看到这里,我坚信你能收获很多很多!也希望这篇文章能帮助到你,如果觉得不错,请点击一下不要钱的赞,如果有误请温柔的指出,在这里感谢大家了!
下一篇我将会将扫雷进行以下优化:
- 能够展开一片的操作
- 标记和取消雷
- 显示剩余雷的个数
- 图形化界面