目录
一.游戏框架
1.打印一个菜单:
2.打印一个扫雷界面:
3.扫雷:
4.扫雷成功/游戏结束:
二.游戏实现
1.main函数构建整体框架
2.菜单函数meau()
3.游戏函数game()
4.游戏函数中所需函数
5.头文件game.h
三.游戏运行效果展示
一.游戏框架
1.打印一个菜单:
和三子棋小游戏一样,我们需要打印一个菜单(如下图),玩家根据提示选择是否进入游戏
??
2.打印一个扫雷界面:
当玩家选择1进入游戏时,打印如下图所示的扫雷界面,每一个位置都有唯一的坐标,为了方玩家进行游戏,我们将行列标号打印出来
3.扫雷:
玩家通过输入坐标,即可进行扫雷游戏,如下图
输入坐标后,扫雷界面上该坐标出现的数字代表该数字所在九宫格中雷的个数
例:3就表示其余八个位置埋有三个雷,0即表示其余八个位置安全
4.扫雷成功/游戏结束:
游戏结束:扫到雷则游戏结束,或排完所有的雷游戏结束
扫雷成功:排完所有的雷
二.游戏实现
1.main函数构建整体框架
和三子棋游戏一样,我们使用do while循环构建框架?
int main()
{
int input = 0;
srand((unsigned int)time(NULL));
do
{
meau();//菜单函数
printf("请输入:");
scanf("%d", &input);
switch(input)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("选择错误,重新选择\n");
break;
}
} while (input);
return 0;
}
2.菜单函数meau()
void meau()
{
printf("*********************\n");
printf("****** 1. play ******\n");
printf("****** 0. exit ******\n");
printf("*********************\n");
}
3.游戏函数game()
通过以下步骤构建游戏函数:?
注: ROWS和COLS是在头文件中定义的两个标识符常量????
以下是我们在game.h中定义的标识符常量
#define ROW 9 #define COL 9 //棋盘扩展 #define ROWS ROW+2 #define COLS COL+2
?#define COUNT 10
void game()
{
//存放布雷信息
char mine[ROWS][COLS] = { 0 };
//存放排雷信息
char show[ROWS][COLS] = { 0 };
//初始化
init_board(mine, ROWS, COLS, '0');
init_board(show, ROWS, COLS, '*');
//布雷
set_mine(mine, ROW, COL);
//print_board(mine, ROW, COL);
//打印
print_board(show, ROW, COL);
//排雷
find_mine(mine,show, ROW, COL);
}
4.游戏函数中所需函数
假如我们要创建一个如下图所示的9*9的扫雷棋盘:
当我们排雷时,位于棋盘中间的坐标我们遍历其周围八个位置即可排雷
但是位于棋盘边界的坐标,我们遍历其周围八个位置时,数组就会越界访问
因此,我们需要创建一个比原因棋盘多两行两列的棋盘
void init_board(char board[ROWS][COLS], int row, int col, char set);?
由函数的定义,我们可以看出函数的参数有四个
char set:set是要初始化的内容
init_board(mine, ROWS, COLS, '0'); init_board(show, ROWS, COLS, '*');
我们创建了俩个棋盘,一个用来存放布雷信息,一个用来存放排雷信息
排雷时只需要俩个数组之间建立联系,提高了代码效率
在布雷数组mine[ROWS][COLS]中:
字符‘0’代表安全位置,字符‘1’代表埋有雷的位置,初始化只需要将该数组所有元素赋值为字符0
在排雷数组show[ROWS][COLS]中:
我们将该数组所有元素初始化为字符‘*”,打印时也是打印为‘*’
因为我们需要使用一个函数将俩个数组初始化,所以被初始化的内容也应该作为参数传给函数
void init_board(char board[ROWS][COLS],int row,int col,char set)
{
int i = 0;
for (i = 0; i < ROWS; i++)
{
int j = 0;
for (j = 0; j < COLS; j++)
{
board[i][j] = set;
}
}
}
?我们在game.h中定义一个标识符常量COUNT,可以自行设置需要布置的雷的个数
定义一个整型常量count用来存储已经布置的雷的数量
当已布置的雷的数量少于COUNT时,继续布雷,直到count>=COUNT时,停止布雷
当row=9时,rand() % row产生0~8的数字,但是我们需要产生数字1~9,所以x = rand() % row + 1;
void set_mine(char board[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
//count用来计算已布置雷的数量
int count = 0;
while (count<COUNT)
{
x = rand() % row + 1;
y = rand() % col + 1;
if (board[x][y] == '0')
{
board[x][y] = '1';
count++;
}
}
}
布雷成功后,我们需要打印存放布雷信息的棋盘,验证代码的正确性,但是程序运行的时候,我们并不需要打印布雷信息,只需要打印排雷棋盘
我们需要打印行列标号,以便玩家更快找到坐标信息?
void print_board(char board[ROWS][COLS], int row, int col)
{
int i = 0;
//打印坐标行
for (i = 0; i <= ROW; 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");
}
printf("--------------扫雷--------------\n");
}
排雷首先要保证玩家输入坐标的正确性?
在输入坐标正确的前提下,再判断该坐标是否为雷
- 是雷:输出“很遗憾,被炸死了”,退出游戏
- 非雷:打印排雷棋盘,并在该坐标显示其周围的雷的数量?
统计雷的数量:
int i = 0;
int count = 0;
for (i = -1; i <= 1; i++)
{
int j = 0;
for (j = -1; j <= 1; j++)
{
if (mine[x][y] == '1')
{
count++;
}
}
}
show[x][y] = count;
字符0的ASCII码值为48;字符1的ASCII码值为49
‘1’ - ‘0’ = 1
除坐标(x,y)外其他八个位置的任意一个坐标里的字符减去字符0,得到0则为安全位置,得到1则为有雷的位置,我们可以把这八个字符加起来再减去8*‘0’,即可得到这八个位置里雷的个数,直接return返回这个值就可以,返回的值为整形,但是show数组的类型为字符型,所以要进行类型转换,show[x][y] = count + '0';
非雷情况下要进行多次扫雷,所以我们需要一个循环多次输入
循环的条件为win < row * col - COUNT,即排过雷的坐标个数小于实际的非雷坐标个数
循环结束后还应当判断win的值,因为被炸死后也会跳出循环
int get_mine_count(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 - 1] +
mine[x + 1][y] +
mine[x + 1][y + 1] - 8 * '0';
}
void find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
//用来计算没有雷的位置的个数
int win = 0;
while (win < row * col - COUNT)
{
printf("请输入坐标:");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= ROW && y >= 1 && y <= COL)
{
if (mine[x][y] == '1')
{
printf("很遗憾,被炸死了!\n");
print_board(mine, ROW, COL);
break;
}
else
{
int count = get_mine_count(mine, x, y);
show[x][y] = count + '0';
print_board(show, ROW, COL);
win++;
}
}
else
{
printf("输入坐标非法,请重新输入:");
}
}
if (win == row * col - COUNT)
{
printf("恭喜你,扫雷成功!\n");
}
}
5.头文件game.h
头文件进行一些头文件的包含,常量的定义和函数的声明?
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define ROW 9
#define COL 9
//棋盘扩展
#define ROWS ROW+2
#define COLS COL+2
#define COUNT 10
//初始化
void init_board(char board[ROWS][COLS], int row, int col, char set);
//打印
void print_board(char board[ROWS][COLS], int row, int col);
//布雷
void set_mine(char board[ROWS][COLS], int row, int col);
//扫雷
void find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
三.游戏运行效果展示
?扫雷效果演示-CSDN直播
|