大家好啊!
目录
一)前言
二)准备工作
三)创建扫雷雷区【二维数组(字符型)】
四)初始化雷区 InitBoard
五)打印雷区 DisPlayBoard
六)布置地雷 Setmine
七)排查雷 Findmine
八)效果展示
九)完整代码
game.h
text.c
game.c
十)一些后话
相信大家都玩过扫雷这款十分经典的小游戏,今天我们来用C语言实现扫雷游戏。
首先,要实现“扫雷”我们要先理清在代码层面的逻辑。
我们可以像实现“三子棋”一样创建三个文件:
game.h //头文件 用来储存函数声明和定义常量,使代码更简洁
game.c //源文件 用来存放函数主体,实现游戏的逻辑和内容
text.c //源文件 存放主函数,测试游戏逻辑
游玩的基础逻辑:因为我们游玩不可能玩一次所以我们可以写一个‘do-while’函数进行控制,当我们输入非0值时,则可以进行游戏,当输入 0时,游戏则会结束。并且还可以使用'switch'用来对玩家进行提醒和使逻辑更清晰。
int main()
{
int n = 0;
printf("请选择:\n");
do
{
menu();//菜单打印
scanf_s("%d", &n);
switch (n)
{
case 1:
printf("游戏开始》》》》\n");
game()
break;
case 0:
printf("退出游戏《《《《\n");
break;
default:
printf("erorr\n");
break;
}
printf("请选择是否继续游玩:\n");
} while (n);
return 0;
}
菜单:通过菜单提醒玩家需要输入什么值来进行或结束游戏。我们可以建立 menu()函数。
void menu()
{
printf("<<<<<<<********>>>>>>>\n");
printf("<<<<<<<*1.play*>>>>>>>\n");
printf("<<<<<<<*0.exit*>>>>>>>\n");
printf("<<<<<<<********>>>>>>>\n");
}
当我们为扫雷游戏创建二维数组时,显然仅仅是一个二维数组满足不了我们的需求的,所以我们应该创建二个二维数组:(雷区是9*9的) char mine[9][9] = { 0 };//存放地雷的数组 char show[9][9] = { 0 };//存放周围地雷数量的数组 我们要尽可能保证两个数组的大小规格一致,以便我们相互对照
注意:(1)数组越界问题:我们都知道,扫雷排雷是根据我们点击的坐标,周围3×3范围内,另外八个坐标中雷的个数进行统计。但是当我们点击棋盘最外周的坐标时,显然,如果我们想要探查坐标周围八个坐标中雷的个数,我们的探查范围是必然会越界的,所以我们不应采用[9][9]的数组,而是应采用[11][11]的数组,使我们探查不会越界。
(2)雷区通用性问题(定义常量): 我们知道,当我们游玩扫雷使雷区的大小是可以变化的,所以要想达到这样的目的,我们可以运用'#define'来定义常量
#define ROW 9
#define COL 9
#define ROWS ROW+2 //即 11
#define COLS COL+2
在初始化雷区时,我们可以创建:
void InitBoard(char board[ROWS][COLS], int rows, int cols,char set);//初始化雷区
注:运用char set是为了初始化时可以将两个数组对应字符传进函数。
这样一个函数,并定义在mine数组中‘0’--没有地雷,‘1’--有地雷。在show数组中‘*’--表示未探查区,‘(地雷数量如0 1 ...)’表示已探查区。
所以我们将mine数组中元素初始化为‘0’,而show数组中元素初始化为‘*’。
InitBoard(mine, ROWS, COLS, '0'); InitBoard(show, ROWS, COLS, '*');
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set)
{
int i = 0;
int j = 0;
for(i=0;i
为了使我们更好观察雷区的变化以及为了玩家的游玩体验我们应该将雷区打印出来
void DisPlayBoard(char board[ROWS][COLS], int row, int col );
注意:我们只需打印9*9的雷区部分,只要注意数组的范围,运用for循环即可解决
DisPlayBoard(mine, ROW, COL); //测试用,游戏时不用
DisPlayBoard(show, ROW, COL); //玩家看到的
void DisPlayBoard(char board[ROWS][COLS], int row, int col)
{
int i = 0;
int j = 0;
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");
}
}
我们创建一个名为Setmine来进行地雷的布置。
void Setmine(char mine[ROWS][COLS],int row,int col);
因为地雷的布置是随机的,所以我们采用随机数的方式。
#include
#include
srand((unsigned int)time(NULL));
int x = 0;
int y = 0;
x = rand() % row+ 1;
y = rand() % col+ 1;
在game.h中放入#include
在text.c中放入srand((unsigned int)time(NULL));
由于我们的雷区是在1~9范围内的,所以我们使用rand() % row+ 1;来保证不会越界
(以下是函数代码)
void Setmine(char mine[ROWS][COLS],int row, int col)
{
int x = 0;
int y = 0;
int count = minecount;
while (count)
{
x = rand() % row+ 1;//1~9
y = rand() % col+ 1;
if (mine[x][y] == '0')
{
mine[x][y] = '1';
count--;
}
}
}
我们可以创建findmine函数来排查地雷
void Findmine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
在排查地雷的过程中可能会有以下几种情况:
1.你被炸死了
2.你没被炸死——周围有雷或没雷
如果没被炸死,那么我们就要探查周围有几个雷,我们可以创建
static int getin(char mine[ROWS][COLS],int x,int y)函数
用来统计周围有几个雷并输出雷的个数,在这里我们使用static来修饰函数,使其他文件不能使用这个函数,并使该函数作用域变小。在这里我们使用最简单的方式进行统计。
//static有三个作用情况 1.修饰局部变量 2.修饰全局变量 3.修饰函数
static int getin(char mine[ROWS][COLS],int x,int y)//static有三个作用 1.修饰局部变量 2.修饰全局变量 3.修饰函数
{
return mine[x][y] + mine[x][y - 1] + mine[x][y + 1] +
mine[x - 1][y] + mine[x - 1][y + 1] + mine[x - 1][y - 1] +
mine[x + 1][y] + mine[x + 1][y + 1] + mine[x + 1][y - 1]- 9 * '0';//可用循环
}
因为getin函数返回的是整型,所以我们可以show[x][y] = count + '0';因为‘0’的ASCLL码为49,所以只要加上‘0’就可以返回‘1‘’2‘等字符
void Findmine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int win = 0;
while (win=1 && x <=row && y>=1 && y <=col)
{
if (mine[x][y] == '1')
{
printf("很遗憾,你失败了!");
break;
}
else
{
int count = 0;
count = getin(mine, x, y);
show[x][y] = count + '0';
win++;
printf("\n");
DisPlayBoard(show, row, col);
}
}
else
{
printf("输入错误,请重新输入\n");
}
}
if (win == row * col - minecount)
{
printf("恭喜你,排雷成功\n");
DisPlayBoard(mine, ROW, COL);
}
}
。。。。(这种方法太长啦!!)
(大家可以自己实现以下“炸金花”展开,可以运用函数递归实现,在基础篇就不细讲了)
#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
#define minecount 10
//菜单
void menu();
//初始化雷区
void InitBoard(char board[ROWS][COLS], int rows, int cols,char set);
//打印雷区
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);
#define _CRT_SECURE_NO_WARNINGS
#include
#include "game.h"
void game()
{
//定义数组————字符型
char mine[ROWS][COLS] = { 0 };//空格
char show[ROWS][COLS] = { 0 };
//初始化雷区
InitBoard(mine, ROWS, COLS, '0');
InitBoard(show, ROWS, COLS, '*');
//打印雷区
//DisPlayBoard(mine, ROW, COL);//测试用,游戏时不用
//printf("\n");
DisPlayBoard(show, ROW, COL);
//布置地雷
printf("\n");
Setmine(mine, ROW, COL);
//DisPlayBoard(mine, ROW, COL);
//排查雷
Findmine(mine, show, ROW, COL);
}
int main()
{
int n = 0;
srand((unsigned int)time(NULL));
printf("请选择:\n");
do
{
menu();//菜单打印
scanf_s("%d", &n);
switch (n)
{
case 1:
printf("游戏开始》》》》\n");
game();//游戏函数
break;
case 0:
printf("退出游戏《《《《\n");
break;
default:
printf("erorr\n");
break;
}
printf("请选择是否继续游玩:\n");
} while (n);
return 0;
}
#define _CRT_SECURE_NO_WARNINGS
#include "game.h"
void menu()
{
printf("<<<<<<<********>>>>>>>\n");
printf("<<<<<<<*1.play*>>>>>>>\n");
printf("<<<<<<<*0.exit*>>>>>>>\n");
printf("<<<<<<<********>>>>>>>\n");
}
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set)
{
int i = 0;
int j = 0;
for(i=0;i=1 && x <=row && y>=1 && y <=col)
{
if (mine[x][y] == '1')
{
printf("很遗憾,你失败了!");
break;
}
else
{
int count = 0;
count = getin(mine, x, y);
show[x][y] = count + '0';
win++;
printf("\n");
DisPlayBoard(show, row, col);
}
}
else
{
printf("输入错误,请重新输入\n");
}
}
if (win == row * col - minecount)
{
printf("恭喜你,排雷成功\n");
DisPlayBoard(mine, ROW, COL);
}
}
到这里C语言实现扫雷游戏(基础篇)就结束啦,后续的“标记地雷”“炸金花展开”将在扫雷游戏(进阶篇)叙述,这里打个预告(正在肝~)
若有错误或者建议,还望大家包涵和多多斧正。谢谢大家阅读!