提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
~~目录~~~~~~~~~~~~~~~~~~~~~~~~~
前言
随着开学季的到来,c语言作为大学工科学习中不可或缺的一部分,今天笔者就为大家带来C语言中函数与数组的运用实例—扫雷游戏的教学;
本程序对于初学者有些许难度,多加练习理解透彻后方可掌握;
一、关于扫雷
扫雷是一款年代久远的小游戏,相信熟悉电脑的小伙伴们在初高中的计算机课上都略有接触。让我们先来回顾一下原版的扫雷游戏吧~
1、游戏规则;
1、扫雷游戏是一种单人的数字游戏,在一个包含有隐藏雷的方格板上进行。
2、每个方格都可能包含一颗雷,也可能不包含任何内容。如果玩家点击了一个带有雷的方格,就会失去游戏。
3、当用户将非雷方块全部找出时,就可以赢得这场比赛
2、扫雷程序的功能模板
1.菜单//menu
2.初始化
3.游戏界面的打印
4.布置雷
5.排查雷
二、扫雷功能的具体分析
主函数需要有2个数组:一个用于存储雷等用作内核;一个用于每次排查完显示雷的个数用于显示。
1.菜单
菜单功能的实现 便于游戏界面的引入【创建变量1/0用于游戏的开始/退出】
void main()
{
printf("**************************");
printf("**********1.play**********");//用于游戏的开始 变量1
printf("**********0.exit**********");//用于游戏的退出 变量0
printf("**************************");
}
2.初始化
定下雷的个数以及棋盘大小
对棋盘的行列进行宏定义 #define
新手棋盘为9x9,12个格子的定义便于后文扫除雷 的程序操作
宏定义的好处不会把程序的变量定死,便于后续改变,换句话说就是 想要多大棋盘与多少颗雷我们可以随时更改.
//对棋盘的行列进行宏定义
#define row 9//游戏内棋盘
#define col 9
#define rows row+2//扫雷外棋盘 便于程序的融洽
#define cols col+2
#define art 10//十颗雷 艺术就是---boom
棋盘初始化
棋盘初始化就是 将我们想放的东西(set)放到棋盘上 利用函数模块化表示
void Init(char board[ROWS][COLS],int rows,int cols,char set)//set用于设计要布置什么
{
int i = 0;
for (i = 0; i < rows; i++)
{
int j = 0;
for ( j = 0; j < cols; j++)
{
board[i][j] = set;
}
}
}
3.游戏界面打印
玩游戏的时,需要看到游戏界面才能进行各种操作,所以这里要设置一个函数来打印扫雷的棋盘(数组的内容)
1.打印行列来让玩家能够确认坐标; 2.打印键盘的9x9格数构成游戏内容
void Display(char board[ROWS][COLS], int row, int col)
{
printf("=============扫雷游戏==============\n");
int i = 0;
for (i = 0; i < row; i++)
{
printf("%d", i);//打印行(无j 全都处于第一行)
}
printf("\n");
for (i = 0; i < row; i++)
{
int j = 0;
for (j = 0; j < col; j++)
{
if ( j == 0)//j=0时 都处于第一格
printf("%d", i);//打印列
else
{
printf("%c", board[i][j]);//打印棋盘
}
printf("\n");
}
}
printf("=============扫雷游戏==============\n");
}
4.布置雷
来到了关键且复杂的一步;
布置雷首先需要知道雷的数量,我们则用宏定义便于后续修改雷的数量
#define art 10
- 关于雷分布在数组中的位置
需要俩个变量x与y来实现定位(扫雷中的雷是随机分布的,所以需要随机数 rand)
创建随机数放于x与y中,作为行号和列号
布置雷需要放在数组中的位置上,因此需要我们设置雷的数字为’1’
注意 这里不是数字1是字符’1’
设置一个循环来不断放雷 根据while函数()为0时停止 来设置一个count表示剩余的雷
每次布置雷时需检查是否已经布置过雷,若已布置需重新生成随机数重新布置
void getart(char board[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int count = ART;
while (count)
{
int x = rand() % row + 1;
int y = rand()%col + 1;
if ('1'!= board[x][y] )//检查是否布置过雷
{
board[x][y] = '1';
count--;
}
}
}
5.排查雷
布置好雷后,游戏进入主要部分,排查雷;
我们需要设计程序达成一下目的:
- 输入坐标值来排查该位置有无雷
- 若有雷 显示被炸死 游戏结束并跳回菜单界面;
- 若没有雷 计算周围一圈8个格的雷的数目并显示在该坐标上
- ;每次排查完都要进行一次排查完的展示(打印)
- 一直循环 直到被炸死 或者雷被排查干净->显示胜利
void outart(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int count = row * col - ART;
while (count)
{
printf("请输入坐标x y\n");
scanf("%d %d", &x, &y);
if (x > 1 && x < row && y>1 && y < col)
{
if('*'!=show[x][y])
{
printf("该位置已经被检查过了!请重新输入\n");
}
if ('1'==mine[x][y])
{
printf("很遗憾,你被炸死了\n");
break;
}
else
{
char num = getnum(mine, x, y);//引入一个新的函数来计算数量
show[x][y] = num;
Display(show, ROW, COL);
}
}
}
}
数雷的个数 //getnum
因为我们的俩个数组mine 和show 都是字符类型数组 所以我们的返回雷的个数也需要是字符,将返回类型设置为char类型。
char getnum(char board[ROW][COL], int x, int y)
{
return(board[x - 1][y - 1] +
board[x - 1][y] +
board[x - 1][y + 1] +
board[x][y - 1] +
board[x][y + 1] +
board[x + 1][y] +
board[x + 1][y - 1]+board[x + 1][y + 1] - 8 * 48 + 48);//48为一个字符'0',一个字符数字减去字符'0'会等于数字本身
}
接下来,请特邀嘉宾GGBOND 对这一大串加减运算进行解释~
- x-1、x+1、x、y、y-1、y+1分别代表什么
首先由上可知 x,y皆为坐标的定位,因此我们有:
为坐标示意图 中间方块为x,y 为我们所需要求坐标
- 8*48代表什么
根据ASCII表不难发现:各个字符数字减去字符’0’ (ascii码值48) 就等于数字本身*e.g. ‘1’-48=1,‘1’-‘0’=1(数学运算便于理解不代表最终函数表示)
- 为什么加上48
若不加上48,则运算结果是从ASCII值为0的地方开始,而从上表可发现 ascii值=0时,对应的输出结果是不显示字符;但是字符0对应的编码是48,所以需要加上48后,才能从字符0开始输出。
三、效果演示
现有的功能大概就是这些了,接下来将代码优化后让ggbond放上源码
四、源码
1、头文件
game .h
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>//随机数头函数
#include <time.h>//随机数时间随机
//对棋盘的行列进行宏定义
//游戏内棋盘
#define ROW 9
#define COL 9
//程序用棋盘 便于计数时不超界
#define ROWS ROW + 2
#define COLS COL + 2
#define ART 10//十颗雷 艺术就是---boom
void menu();
void Init(char board[ROWS][COLS], int rows, int cols, char set);
void Display(char board[ROWS][COLS], int row, int col);
void getart(char board[ROWS][COLS], int row, int col);
void outart(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
int getnum(char board[ROWS][COLS], int x, int y);
2 函数实现部分
game.c
#include "game.h"
void menu()
{
printf("**************************\n");
printf("**********1.play**********\n");
printf("**********0.exit**********\n");
printf("**************************\n");
}
void Init(char board[ROWS][COLS],int rows,int cols,char set)//set用于设计要布置什么
{
int i = 0;
for (i = 0; i < rows; i++)
{
int j = 0;
for ( j = 0; j < cols; j++)
{
board[i][j] = set;
}
}
}
void Display(char board[ROWS][COLS], int row, int col)
{
printf("=============扫雷游戏==============\n");
int i = 0;
for (i = 0; i <= col; i++)
{
printf("%d ", i);//打印行(无j 全都处于第一行)
}
printf("\n");
for (i = 1; i <= row; i++)
{
printf("%d ", i);//打印列
int j = 0;
for (j = 1; j <=col; j++)
{
printf("%c ", board[i][j]);//打印棋盘
}
printf("\n");
}
printf("=============扫雷游戏==============\n");
}
void getart(char board[ROWS][COLS], int row, int col)
{
int count = ART;
while (count)
{
int x = rand()%row + 1;
int y = rand()%col + 1;
if ('0' == board[x][y] )
{
board[x][y] = '1';
count--;
}
}
}
int getnum(char mine[ROWS][COLS], int x, int y)
{
return (mine[x - 1][y - 1] +
mine[x - 1][y] +
mine[x - 1][y + 1] +
mine[x][y - 1] +
mine[x][y + 1] +
mine[x + 1][y] +
mine[x + 1][y - 1]+mine[x+1][y+1] - 8 * 48);//48为一个字符'0',一个字符数字减去字符'0'会等于数字本身
}
void outart(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int count = row * col - ART;
while (count)
{
printf("请输入坐标x y\n");
scanf("%d %d", &x, &y);
if (x >=1 && x <= row && y>=1 && y <= col)
{
if(show[x][y]!='*')
{
printf("该位置已经被检查过了!请重新输入\n");
}
if (mine[x][y]=='1')
{
printf("很遗憾,你被炸死了\n");
break;
}
else
{
int num = getnum(mine, x, y);//引入一个新的函数来计算数量
show[x][y] = num+'0';
Display(show, ROW, COL);
count--;
}
}
else
{
printf("坐标非法,请重新输入\n");
break;
}
}
if (0 == count)
printf("Win!!!!");
}
3、主函数部分
test.c
void game()
{
char mine[ROWS][COLS] ;//内核数组放雷
char show[ROWS][COLS] ;//展示数组打印雷数
//初始化
Init(mine, ROWS, COLS, '0');
Init(show, ROWS, COLS, '*');
//打印
Display(show, ROW, COL);
//布置雷
getart(mine, ROW, COL);
//排查雷
outart(mine, show, ROW, COL);
}
int main()
{
srand((unsigned)time(NULL));//设置随机数
int input = 0;
do
{
menu();
printf("请选择:>\n");
scanf("%d", &input);
switch (input)
{
case 1:
printf("=======扫雷=======\n");
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("输出错误,请重新选择\n");
break;
}
} while (input);
return 0;
}
到这里,本期的分享就结束啦,欢迎各位小伙伴留言,博主看到就会回复的!
求关注求点赞一键三连~~~~
别忘记点赞!!!