这次,我们要做一个小游戏--扫雷
要想完成这个游戏,首先最重要的事就是我们要知道扫雷的原理,玩过旧电脑的应该都知道扫雷游戏由一个n*n的棋盘组成,而玩家初始是不知道炸弹在哪里的,只能先随机点击一个格子,如若踩到雷,则游戏直接over,反之,空白格子会显示出周围8个格子所含雷的个数,重复此步骤,直到玩家将不是雷的格子全部找出来,游戏结束,玩家胜利
了解完原理后,我们要明确我们的任务由几部分组成:(我们可以尝试用函数实现功能)
这其中会涉及到多个函数,倘若全部把他们放在一个文件内阅读会十分困难,所以我们可以将其分成几个文件,首先第一个文件text.c用来容纳游戏的主体函数(游戏的整体框架),第二个文件game.c用来容纳游戏的局部函数(实现各部分功能的),最后一个文件game.h用来容纳两个文件中所需要的库以及需要用到的宏还有作为两个文件之间的链接作用(需要传输数据的的函数)
.h函数中包含的函数文件:
//初始化棋盘(函数实现)
void stardboard(char board[ROWS][COLS], int rows, int cols, char set);
//打印棋盘查看效果(函数实现)
void showboard(char board[ROWS][COLS], int row, int col);
//布置雷
void boom(char answer[ROWS][COLS], int row, int col);
//统计非雷坐标周围8个格的雷的总个数
//int getcount(char answer[ROWS][COLS], int x, int y);
//猜测雷
void guess(char answer[ROWS][COLS],char show[ROWS][COLS], int row, int col);
1.菜单进入界面,意味给用户提供一个初始界面,选择开始游戏或者是退出游戏,命名为text,其中首先设计一个munu函数打印初始界面提示玩家做出选择,想要让玩家玩了一次还想继续玩,那我们就需要一个循环while,当输入0时才终止程序,与此同时我们还得在这里面嵌入游戏主函数game
void text()
{
int input;
do
{
menu();
printf("请选择:");
scanf("%d", &input);
switch (input)
{
case 1:
//进入游戏;
printf("-----开始扫雷-----\n");
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("无效输入,请输入0或1\n");
break;
}
} while (input);
}
接下来我们就要设计game函数内部的局部函数
2.首先我们便是要打印一个游戏画面,也就是棋盘,而要做到这一步我们可以创建一个二维数组,同时我们可以在.h文件中定义两个宏ROW和COL,用来改变棋盘的大小
//初始化棋盘(函数实现)
void stardboard(char board[ROWS][COLS], int rows, int cols, char set)
{
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
board[i][j] = set;//面对两个棋盘设置两种不同的参数,这样就可以分开
}
}
}
这里我们要注意宏是作为参数给对应的函数传递的,所以对应的函数需要有变量来接收,这里我们用到row和col,简而言之就是使用函数的时候可以用到宏,但用void定义函数的时候要给一个数来接收ho
其次我们期待这个棋盘初始化时显示的全是0,炸弹用1来表示,玩家看到的画面全是*,而玩家点击一个不是雷的位置时会显示出周围8个格子雷的个数,这里面既会用到int类型也会用到char类型,为了方便我们可以创立一个参数set同时储存
3.想要查看是否初始化成功我们可以打印一下棋盘看一下效果,我们可以编写一个函数,这样可以展示我们想要的棋盘(带有雷的棋盘、给玩家看的游戏画面)
void stardboard(char board[ROWS][COLS], int rows, int cols, char set)
{
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
board[i][j] = set;//面对两个棋盘设置两种不同的参数,这样就可以分开
}
}
}
4.初始化棋盘后我们就要埋雷了,首先要明确雷的位置肯定是随机的,这里我们就要引进一个rand函数的概念,它可以生成一个伪随机数,伪随机数是基于一个固定的种子生成的,所以我们还要改变种子
如果想生成一个a~b的随机数:a + rand()%(b-a+1)包含头文件stdlib
记得要在该函数前面带上srand((unsigned int)time(NULL))这样才能使种子变化,记得包含头文件time
//布置雷
void boom(char answer[ROWS][COLS], int row, int col)
{
int count = easy;//在棋盘上随机放置10个雷
srand((unsigned int)time (NULL));
while (count)
{
int x = rand() % 9 + 1;
int y = rand() % 9 + 1;
if (answer[x][y] != '1')//不能在有雷的地方布置
{
answer[x][y] = '1';
count--;
}
}
}
4.埋完雷之后我们就要进行最重要的猜雷步骤了,也就是玩家玩的部分,我们设计一个guess函数,想要玩家一个接着一个输入,我们就要利用while函数,当输入的坐标是‘1’也就意味着踩到了雷,那么游戏结束,如果不是雷,我们就要统计周围8个格子所含雷的个数。于是我们可以在写一个getcount函数单独去计算雷的个数、
从这就可以看出我们所选坐标周围8个坐标的信息,接着把他们加起来,return这个值
//统计非雷坐标周围8个格的雷的总个数
int getcount(char answer[ROWS][COLS], int x, int y)
{
return answer[x - 1][y - 1] + answer[x][y - 1] + answer[x + 1][y - 1] + answer[x + 1][y]
+ answer[x + 1][y + 1] + answer[x][y + 1] + answer[x - 1][y + 1] + answer[x - 1][y]-8*'0';
//八个坐标都是字符,所以要减去字符‘0’得到1
}
这里要注意一个点,因为前面我们另它的是char类型,所以在这里我们要把它转换为int类型,怎么转换呢,一个int类型加上一个‘0’就能转换成char类型,所以这里我们只需要减去8个‘0’就可以了
此外在guess函数里面我们还要创立一个数接收getcount函数返回的值
想要判断获胜的条件很简单,我们只需要定义一个win,猜中一次win的大小就+1,当win的次数等于棋盘格子总个数减去雷的个数时,那么游戏结束,玩家胜利
//猜测雷:由用户输入猜测的雷的坐标
void guess(char answer[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int win = 0;
while (win<row*col-easy)
{
printf("输入猜测的坐标(1<=x<=9 1<=y<=9):");
scanf("%d %d", &x, &y);
if (x > 0 && x <= row && y>0 && y <= col)
{
if (answer[x][y] == '1')//输入的坐标是雷,over
{
printf("遗憾踩雷,游戏结束\n");
showboard(answer, ROW,COL);
break;
}
else//统计周围8个格子雷的个数
{
if (show[x][y] != '*')
{
printf("该位置已经被探查过,请重新输入\n");
}
int count = getcount(answer, x,y);
show[x][y] = count+'0';
win++;
showboard(show, ROW, COL);
}
}
else
{
printf("输入的坐标有误,请重新输入\n");
}
if (win == row * col - easy)
{
printf("恭喜你,排雷成功!\n");
break;
showboard(answer, ROW, COL);
}
}
}
总体代码如下:
game.h文件:
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
//简单模式棋盘的大小是9*9
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
#define easy 10//easy模式雷的个数
//初始化棋盘(函数实现)
void stardboard(char board[ROWS][COLS], int rows, int cols, char set);
//打印棋盘查看效果(函数实现)
void showboard(char board[ROWS][COLS], int row, int col);
//布置雷
void boom(char answer[ROWS][COLS], int row, int col);
//统计非雷坐标周围8个格的雷的总个数
//int getcount(char answer[ROWS][COLS], int x, int y);
//猜测雷
void guess(char answer[ROWS][COLS],char show[ROWS][COLS], int row, int col);
game.c文件:
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
//初始化棋盘(函数实现)
void stardboard(char board[ROWS][COLS], int rows, int cols, char set)
{
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
board[i][j] = set;//面对两个棋盘设置两种不同的参数,这样就可以分开
}
}
}
//打印棋盘查看效果(函数实现)
void showboard(char board[ROWS][COLS], int row, int col)
{
for (int i = 0; i <= col; i++)
{
printf("%d ", i);
}
printf("\n");
for (int i = 1; i <=row; i++)
{
printf("%d ", i);
for (int j = 1; j <= col; j++)
{
printf("%c ",board[i][j]);
}
printf("\n");
}
}
//布置雷
void boom(char answer[ROWS][COLS], int row, int col)
{
int count = easy;//在棋盘上随机放置10个雷
srand((unsigned int)time (NULL));
while (count)
{
int x = rand() % 9 + 1;
int y = rand() % 9 + 1;
if (answer[x][y] != '1')//不能在有雷的地方布置
{
answer[x][y] = '1';
count--;
}
}
}
//统计非雷坐标周围8个格的雷的总个数
int getcount(char answer[ROWS][COLS], int x, int y)
{
return answer[x - 1][y - 1] + answer[x][y - 1] + answer[x + 1][y - 1] + answer[x + 1][y]
+ answer[x + 1][y + 1] + answer[x][y + 1] + answer[x - 1][y + 1] + answer[x - 1][y]-8*'0';
//八个坐标都是字符,所以要减去字符‘0’得到1
}
//猜测雷:由用户输入猜测的雷的坐标
void guess(char answer[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int win = 0;
while (win<row*col-easy)
{
printf("输入猜测的坐标(1<=x<=9 1<=y<=9):");
scanf("%d %d", &x, &y);
if (x > 0 && x <= row && y>0 && y <= col)
{
if (answer[x][y] == '1')//输入的坐标是雷,over
{
printf("遗憾踩雷,游戏结束\n");
showboard(answer, ROW,COL);
break;
}
else//统计周围8个格子雷的个数
{
if (show[x][y] != '*')
{
printf("该位置已经被探查过,请重新输入\n");
}
int count = getcount(answer, x,y);
show[x][y] = count+'0';
win++;
showboard(show, ROW, COL);
}
}
else
{
printf("输入的坐标有误,请重新输入\n");
}
if (win == row * col - easy)
{
printf("恭喜你,排雷成功!\n");
break;
showboard(answer, ROW, COL);
}
}
}
text.c文件:
#define _CRT_SECURE_NO_WARNINGS 1
//游戏测试
#include "game.h"
//游戏进入页面的菜单,由玩家选择开始还是退出
void menu()
{
printf("---------------------\n");
printf("--------1.开始-------\n");
printf("--------0.退出-------\n");
printf("---------------------\n");
}
void game()
{
//创建两个二维数组
//第一个数组用来储存正确的雷所在的位置,第二个数组储存展示给玩家的部分
char answer[ROWS][COLS] = {0};
char show[ROWS][COLS] = {0};
//初始化棋盘
stardboard(answer,ROWS,COLS,'0');//初始化符号
stardboard(show, ROWS, COLS,'*');//用户看到的全是*
//打印棋盘查看效果
showboard(show,ROW, COL);
//showboard(answer,ROW, COL);
布置雷
boom(answer, ROWS, COLS);
//showboard(answer, ROW, COL);
//猜测雷
guess(answer,show, ROW, COL);
}
void text()
{
int input;
do
{
menu();
printf("请选择:");
scanf("%d", &input);
switch (input)
{
case 1:
//进入游戏;
printf("-----开始扫雷-----\n");
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("无效输入,请输入0或1\n");
break;
}
} while (input);
}
int main()
{
text();
return 0;
}
运行结果如下: