目录
本章设计的C语言知识包括:循环语句,条件语句,数组,函数,宏定义,随机数生成等
游戏规则
扫雷棋盘为9*9方格,玩家目标是避开雷,找出其他非雷的格子。玩家打开格子,如果该方格为雷,则玩家被炸死,游戏结束,如果该方格非雷,则该处显示相邻8格中的雷数,玩家可根据这些信息推导出安全位置。
根据游戏规则,在代码实现过程中应该包含游戏开始&结束主流程,以及单独定义游戏的模块。
主流程
该模块定义用户从开始游戏到退出游戏的整个游戏周期。首先定义menu()函数,展示筛选菜单供用户选择是否开始游戏或退出游戏。
#define _CRT_SECURE_NO_WARNINGS //放在代码第一行,解决scanf报错不安全问题
#include <stdio.h>
//游戏开始
menu()
{
printf("*****************\n");
printf("******1.play*****\n");
printf("******0.exit*****\n");
printf("*****************\n");
}
//主流程:
int main()
{
menu(); //游戏开始&结束菜单
int input = 0;
do {
scanf("%d", &input);
switch (input)
{
case 1:
{
printf("游戏开始\n");
game(); //通过游戏模块实现游戏功能
break;
}
case 0:
printf("退出游戏");
break;
default:
printf("输入错误");
break;
}
} while (input);
return 0;
}
游戏模块
游戏模块整体思路可大致拆解为:
- 生成9*9雷盘;
- 随机设置雷点
- 向用户展示雷盘
- 用户搜索雷点
- 依据搜索结果,判断输赢
需要注意的是,除了向用户展示隐藏雷的棋盘外,内部后台需要一份记录雷点的数据来对比用户扫雷结果,以判断输赢。因此,可以创建两张二维数组用来存储埋点和扫雷的结果信息。这里,用'1'表示雷点,'0'表示非雷点;'*'表示向用户展示的隐藏雷盘,后续会根据用户搜索结果返回非雷点周围8格中的雷数。
尽管需要展示9*9的雷盘,但是考虑到后续需要统计非雷点周围8格中的雷数,这里可以创建11*11的数组来避免越界问题。
基本思路以及该注意的细节基本介绍差不多了,话不多说,上代码!!!
- 初始化棋盘
1。vs2022编译器,数组的大小必须为常量,这里通过宏常量进行定义。宏常量,一般用#define来定义一个符号常量,修改时只需要修改#define这条语句即可,不必处处修改。
2。对于数值或者字符串等常量的定义,一般默认采用全大写的英文字母,单词之间下划线的方式命名。
//游戏模块
#define _CRT_SECURE_NO_WARNINGS //放在代码第一行,解决scanf报错不安全问题
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
//棋盘初始化
void initboard(char arr[ROWS][COLS],int rows, int cols, char set)
{
int i, j;
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
arr[i][j] = set;
}
}
}
game()
{
char mine[ROWS][COLS]; //创建数组存储雷点信息
char show[ROWS][COLS]; //创建数组存储扫雷信息
initboard(mine, ROWS, COLS, '0'); //初始化雷盘,雷点表用'0'填充
initboard(show, ROWS, COLS, '*'); //初始化雷盘,向用户呈现的雷盘界面用'*'填充
}
- 随机设置雷点
rand()函数所生成的随机数,并不是真实的随机值,而是伪随机。该函数是通过某个公式计算的随机结果,因此当输入一致时,输入也会保持一样。这里引入srand()函数,生成随机种子,相当于让rand()函数生成随机数的公式随着种子变化而变化。在后面,将srand()函数加入主流程模块中。
//随机设置雷点
#define _CRT_SECURE_NO_WARNINGS //放在代码第一行,解决scanf报错不安全问题
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
void setboard(char arr[ROWS][COLS], int row, int col, int mine_count)
{
while (mine_count)
{
int rand1 = rand() % row + 1;
int rand2 = rand() % col + 1;
if (arr[rand1][rand2] = '0') //如果随机设置的雷点坐标处已有雷,则重新随机置雷
{
arr[rand1][rand2] = '1';
mine_count--;
}
}
}
- 打印雷盘交互界面
//打印雷盘交互界面
#define _CRT_SECURE_NO_WARNINGS //放在代码第一行,解决scanf报错不安全问题
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
void displayboard(char arr[ROWS][COLS], int row, int col)
{
int i, j;
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 ", arr[i][j]);
}
printf("\n");
}
}
- 统计非雷点周围雷数
#define _CRT_SECURE_NO_WARNINGS //放在代码第一行,解决scanf报错不安全问题
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
//统计非雷点雷数
int roudboard(char arr[ROWS][COLS],int row, int col)
{
int i, j;
int sum = 0;
for (i = row - 1; i <= row + 1; i++)
{
for (j = col - 1; j <= col + 1; j++)
{
sum = sum+arr[i][j]-'0';
}
}
return sum;
}
- 与用户交互
//与用户交互
#define _CRT_SECURE_NO_WARNINGS //放在代码第一行,解决scanf报错不安全问题
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
#define MINE_COUNT 10 //通过宏常量定义雷数为10
void minegame(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
int row1, col1;
int win = row*col-MINE_COUNT; //所有的方格数减去10个雷点数,则为需要胜利的次数
printf("请输入坐标\n");
while (win)
{
scanf("%d %d", &row1, &col1);
if (row1 >= 1 && row1 <= row && col1 >= 1 && col1 <= col)
{
if (mine[row1][col1] == '1')
{
printf("你被炸死了\n");
displayboard(mine, ROW, COL);
break;
}
if (mine[row1][col1] == '0')
{
int count = roudboard(mine, row1, col1);
show[row1][col1] = count + '0';
displayboard(show, ROW, COL);
win--;
}
}
else
{
printf("输入有误,请重新输入\n");
}
}
if (win == 0)
{
printf("恭喜顺利通过!");
displayboard(mine, ROW, COL);
}
}
整体代码
#define _CRT_SECURE_NO_WARNINGS //放在代码第一行,解决scanf报错不安全问题
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
#define MINE_COUNT 10
//扫雷游戏:主流程+游戏模块
//主流程:游戏开始,游戏结束
//游戏模块:初始化棋盘——>埋雷——>展示游戏界面——>扫雷——>返回结果
//游戏开始
menu()
{
printf("*****************\n");
printf("******1.play*****\n");
printf("******0.exit*****\n");
printf("*****************\n");
}
//棋盘初始化
void initboard(char arr[ROWS][COLS],int rows, int cols, char set)
{
int i, j;
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
arr[i][j] = set;
}
}
}
//打印雷盘交互界面
void displayboard(char arr[ROWS][COLS], int row, int col)
{
int i, j;
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 ", arr[i][j]);
}
printf("\n");
}
}
//随机设置雷点
void setboard(char arr[ROWS][COLS], int row, int col, int mine_count)
{
while (mine_count)
{
int rand1 = rand() % row + 1;
int rand2 = rand() % col + 1;
if (arr[rand1][rand2] = '0')
{
arr[rand1][rand2] = '1';
mine_count--;
}
}
}
//统计非雷点周围雷数
int roudboard(char arr[ROWS][COLS],int row, int col)
{
int i, j;
int sum = 0;
for (i = row - 1; i <= row + 1; i++)
{
for (j = col - 1; j <= col + 1; j++)
{
sum = sum+arr[i][j]-'0';
}
}
return sum;
}
//开始扫雷游戏
void minegame(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
int row1, col1;
int win = row*col-MINE_COUNT;
printf("请输入坐标\n");
while (win)
{
scanf("%d %d", &row1, &col1);
if (row1 >= 1 && row1 <= row && col1 >= 1 && col1 <= col)
{
if (mine[row1][col1] == '1')
{
printf("你被炸死了\n");
displayboard(mine, ROW, COL);
break;
}
if (mine[row1][col1] == '0')
{
int count = roudboard(mine, row1, col1);
show[row1][col1] = count + '0';
displayboard(show, ROW, COL);
win--;
}
}
else
{
printf("输入有误,请重新输入\n");
}
}
if (win == 0)
{
printf("恭喜顺利通过!");
displayboard(mine, ROW, COL);
}
}
//游戏模块
game()
{
char mine[ROWS][COLS];
char show[ROWS][COLS];
initboard(mine, ROWS, COLS, '0');
initboard(show, ROWS, COLS, '*');
setboard(mine, ROW, COL, MINE_COUNT);
displayboard(show, ROW, COL);
//displayboard(mine, ROW, COL);
minegame(mine,show, ROW, COL);
}
//主流程:
int main()
{
menu();
srand((unsigned int)time(NULL));
int input = 0;
do {
scanf("%d", &input);
switch (input)
{
case 1:
{
printf("游戏开始\n");
game();
break;
}
case 0:
printf("退出游戏");
break;
default:
printf("输入错误");
break;
}
} while (input);
return 0;
}
写到最后:这里仅实现了扫雷游戏的简易版,仍然有很多地方值得思考和探索,比如当用户选中的方格为非雷点的时候,是否可以展开一片;用户第一次扫雷一定不会遇到雷,来提高用户体验。