函数和数组实践:扫雷游戏初阶

一:扫雷游戏原理分析

如何利用C语言中函数和数组的关系,写一个9x9阶的扫雷游戏呢?首先我们要清楚其原理。

在编译器中,我们只能利用控制台输入输出数据,因此,游戏的运行实在控制台实现的。

功能如下:

1>. 玩家可以通过菜单选择游戏继续进行或者退出,

2>. 棋盘为9x9的格子,

3>. 默认布置十个雷,

4>. 可以排查雷的数量:如果所排查的位置不是雷,就标记周围一圈类的数量;如果是雷,就被炸死了,游戏结束,退出游戏;如果把十个都是雷之外的所有位置都找出来了,则排雷成功,游戏结束。

游戏界面如图所示:

1. 游戏的分析

                                    首先我们需要创建一个二维9*9数组用于储存雷并且排查雷

                                                 没雷的位置放1,有雷的位置放0

由于我们需要在排查过每个坐标过后标记它位置上的雷的数量;因此若打印雷的个数的信息,将其存放在排查雷的数组中时,会和原本有没有雷的信息相混解决这个问题,我们可以将雷和非雷的信息用字符表示,

为了增加神秘感,我们可以先初始化为show数组为'*'

mine数组初始化字符为'0',布置雷之后存放'1'

char mine[11][11] = {0};

char show[11][11] = {0};

为了使程序结构清晰,我们可以将实现不同功能的代码放到不同的文件中,比如:将函数的声明放到game.h文件中,将函数的实现放到game.c文件中,将游戏的底层运行逻辑放到test.c文件中。

  • test.c文件
    

    void menu()//先用menu函数打印一个菜单,作用是接下来让玩家选择进行游戏还是退出游戏

    {

    printf("----------扫雷游戏----------\n");

    printf("****************************\n");

    printf("******** 1. play ********\n");

    printf("******** 0. exit ********\n");

    printf("****************************\n");

    }

int main()

{

int count = 10;//存放雷的数量

int input = 0;

do {

menu();//先打印菜单

printf("请输入:");

scanf("%d", &input);//再输入值判断是否进行游戏

//我们可以用switch语句输入值判断游戏是进行还是退出

switch (input)

{

case 1: //若输入1,则进行游戏

game();//调用自己编写的game()函数实现游戏

break;

//每结束一把游戏,玩家可自行选择是否进行下一把游戏,break跳出循环后再输入input选择

case 0: //若输出入0,则退出游戏

printf("退出游戏\n");

break;

default: printf("输入错误,请重新输入:\n");//若输入的既不是1,也不是0,则重新输入

break;

}

} while (input);

return 0;

}

前面我们提到用两个二维数组分别用来存放和展示雷的信息

void game()

{

printf("游戏开始:\n");

调用game.c文件中的函数实现游戏

char mine[ROWS][COLS];//二维数组存放雷

char show[ROWS][COLS];//二维数组存放排查出的雷的信息

Initboard(mine, ROWS, COLS, '0');//初始化存放雷的棋盘为' 0 '

Initboard(show, ROWS, COLS, '*');//初始化展示棋盘 ' * '

Displayboard(show, ROW, COL);//展示棋盘

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

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

  • 将函数的声明放到 game.h 文件中去:

#include<stdio.h>//在其头文件中将所需的头文件都放在一起,后面test.c和game.c函数要使用时,只需引用自定义头文件#include"game.h"就行(用户自定义头文件用" "引用)

//随机数的生成需要包含
#include<time.h>

#include<stdlib.h>

//两个头文件

//雷的排列为9乘9,初始化行和列都为9

#define ROW 9

#define COL 9

//可以任意改变雷的数量,

#define EASY_COUNT 10

//棋盘排列为11乘11,比雷多两行两,方便计算边缘位置的雷的数量

#define ROWS ROW+2

#define COLS COL+2

//初始化棋盘

void Initboard(char board[ROWS][COLS], int rows, int cols, int 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);

  • 将游戏的实现放到  game.c  文件中去:

void Initboard(char board[ROWS][COLS], int rows, int cols, int set)

{

int i = 0;

for (i = 0; i < rows; i++)

{

int j = 0;

for (j = 0; j < cols; j++)

{

board[i][j] = set; //对棋盘进行初始化,放入字符 '0';

}

}

}

void Displayboard(char board[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++)

{

int j = 0;

printf("%d ", i);//每行开头对行进行标号

for (j = 1; j <= col; j++)

{

printf("%c ", board[i][j]);//

}

printf("\n");

}

}

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

{

int count = EASY_COUNT;

while (count)

{

//rand()函数随机生成一个坐标

int x = rand() % row + 1;//1-9

int y = rand() % col + 1;//1-9

if (board[x][y] == '0')//初始化为字符'0',都没有雷

{

board[x][y] = '1';//在此坐标位置布置雷

count--; //每布置一个雷,雷的总数减一,当count为0时,判断循环的条件

//不成立,退出循环

}

}

}

//我们需要统计所输入坐标外一层的雷的个数,可以用mine数组中的字符提取出来('0'或'1'),然后进行字符型数字与十进制数字之间的转换就行了,方法如下:

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)

{

//给定x,y坐标用于确定二维数组中某一点的位置

int x = 0;

int y = 0;

int win = 0;

while (win < row * col - EASY_COUNT)

//当棋盘大小9x9行共81个时,布置有x个雷,若查找了81-x个坐标仍未排查到雷,那么说明剩余的位置全为雷

//因此就可以判定游戏成功了,可以跳出循环了

{

printf("请输入的坐标:");

scanf("%d%d", &x, &y); //输入坐标信息

if (x >= 1 && x <= row && y >= 1 && y <= col)//在9x9棋盘中查找雷

{

if (mine[x][y] == '1')//如果排查到了雷,那么肯定被炸死了,就跳出循环

{

printf("很遗憾,你被炸死了\n游戏结束\n");

Displayboard(mine, ROW, COL);//但是要死的明明白白,就要让玩家看到所有雷的信息

break;

}

else

{

int m = GetMinecount(mine, x, y);

//如果还未排查到雷,那么通过排查他周围的雷的数量就可以排查其他位置的雷了,但棋盘中存放

//的是字符类型的数据,因此排查出的值(0 - 9)就要通过转化成字符( '0 '-- '9' )进行储存

show[x][y] = m + '0';//将值转化为字符型储存

Displayboard(show, ROW, COL);//然后再打印排查后的棋盘信息,进行下一次雷的排查

win++;//每排查到一次到非的值,就说明离成功更进一步,非雷的数量加一

}

}

else

{

printf("非法坐标,请重新输入\n");//若输出的坐标不在9x9的棋盘中,那么就需要重新输入坐标值再次判断

}

}

//当所有非雷的位置排查完之后,剩下的位置都是雷,说明游戏成功,因此就可以退出游戏了,

// 最后打印出所有雷所在位置的信息

if (win == row * col - EASY_COUNT)

{

printf("恭喜你,排雷成功\n");

Displayboard(mine, ROW, COL);

}

}

代码的完整版在函数和数组实践:扫雷游戏/函数和数组实践:扫雷游戏 · fanyunxi/范云熙的C仓库 - 码云 - 开源中国 (gitee.com)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值