前言
结合前边我们所学的C语言知识,本期我们将使用C语言实现一个简单的小游戏——扫雷
1. 总体框架设计
和三子棋相同,游戏开始时不需要任何判断与操作直接进入游戏(符合我们所学的do…while结构),然后再根据菜单选择,开始游戏和退出游戏,这部分的操作与三子棋较为类似,这里不再详细讲解(详请看三子棋那期博客)。
int main() { int input = 0; srand((unsigned int)time(NULL)); do { menu(); printf("请选择>:\n"); scanf("%d", &input); switch (input) { case 1: game(); break; case 0: printf("退出游戏!\n"); break; default: printf("输入错误请重新输入>:\n"); break; } } while (input); return 0; }
菜单打印部分也是相同
void menu() { printf("******************************\n"); printf("********* 1.play *********\n"); printf("********* 0.exit *********\n"); printf("******************************\n"); }
2. 多文件分装程序
当然根据之前的方法,我将程序分装到多文件,.h文件用于声明函数,test.c文件用于程序设计,game.c文件用于函数定义。
注意:函数的定义和声明是不同的(详细请看函数那期内容)
函数声明(在.h文件中)
//初始化棋盘 void InitBoard(char board[ROWS][COLS], char set);
函数定义(在函数实现.c文件中)
void InitBoard(char board[ROWS][COLS], char set) { }
3. 各功能模块化实现
接下来是最重要的部分,game()游戏部分的实现。游戏开始首先我们需要布置棋盘,设置雷的个数,和三子棋有所不同,这里我们最好是创建两个二维数组来存放我们的棋盘信息,一个棋盘用于玩家下棋棋盘,另外一个用于存放雷的信息。
3.1 初始化棋盘
InitBoard(mine,'0');//埋雷棋盘 InitBoard(show,'*');//玩家棋盘
棋盘初始化和二维数组初始化相同
void InitBoard(char board[ROWS][COLS], char set)//字符型变量用于接收传入的字符 { for (int i = 0; i < ROWS; i++) {//为了便于更改棋盘大小这里需要定义字符型常量 for (int j = 0; j < COLS; j++) { board[i][j] = set; } } }
3.2 棋盘打印
棋盘的打印没有三子棋那么难,如果想要美化棋盘也是可以使用与三子棋结合的棋盘。
效果图如下:
这里我们采用上图的效果进行讲解
void DisPlaybroad(char board[ROWS][COLS]) { printf("------------------扫雷游戏------------------\n");//棋盘分割线 printf(" "); //与行打印对齐 for (int i = 1; i <=COL; i++) { //打印列数序号1~9 printf(" %d ", i); } printf("\n"); //打印完一行及时换行 printf(" -----------------------------------");//列与棋盘分割线 printf("\n"); for (int i = 1; i <= ROW; i++) { //打印行数序号 printf("%d ",i); for (int j = 1; j <= COL; j++) { //与三子棋打印一样" %c |"为一次循环进行打印 printf(" %c ", board[i][j]); if (j < COL) { printf("|"); } } printf("\n"); if (i < ROW) { for (int i = 1; i <=ROW; i++) { if (i ==1) { printf(" "); //空出第一列用于打印序列号 } printf("---"); if (i < ROW) { //---|---|---为一个整体(一次循环)循环打印 printf("|"); } } printf("\n"); } } }
3.3 埋雷
首先我们需要了解扫雷的规则,玩家选择一个坐标,然后检测该坐标附近8个坐标是否有雷,然后在玩家棋盘中显示附近雷的个数,简单的9*9的棋盘在边缘检测时比较复杂,那么我们就可以采用11*11的棋盘去初始化,埋雷的位置限制在9*9的棋盘中,这样就可以避免许多没必要的判断。
void SetMine(char board[ROWS][COLS]) { int count = N;//雷的个数 while (count) { int x = rand() % ROW + 1;//使用随机数来进行埋雷,与srand配合使用来实现真正的随机。 int y = rand() % COL + 1;//COL,ROW等于9,随机数与9求余范围是0~8,加一范围就变成了1~9 if (board[x][y] == '0') {//确保雷的位置不重复布置 board[x][y] = '1';//用1来表示雷 count--;//布置之后雷的数量减一 } } }
字符型常量定于如下:
#define ROW 9 #define COL 9 #define ROWS ROW+2 #define COLS COL+2 #define N 10
3.4 判赢与排雷
这部分特别需要注意的是两个棋盘之间的联系。判断雷的数量在埋雷的棋盘中进行,打印输出雷的信息在show这个数组展现。
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS]) { int x = 0; int y = 0; int win = 0; while (win<COL*ROW-N) //判赢 { printf("请输入要排查的位置>:\n"); scanf("%d%d", &x, &y); if (x >= 1 && x <= 9 && y >= 1 && y <= 9) { if (mine[x][y] == '1') { printf("很遗憾,你踩到了雷,游戏结束!\n"); DisPlaybroad(mine); //游戏结束打印埋雷棋盘 break; } else { show[x][y] = Get_Mine(mine, x, y) + '0';//扫雷部分函数返回值是一个数字,而打印时是以字符的形式打印数字,所以加上‘0’转变为对应的ascll值,注意这里将埋雷棋盘的排雷信息通过函数返回给show棋盘。 DisPlaybroad(show);//没有踩到雷继续打印棋盘 win++;//计数 } } else { printf("坐标非法,请重新输入!\n"); } } if (win == ROW * COL - N) {//9*9的棋盘埋10个雷,那需要走71步才能将雷扫完。 printf("恭喜你排雷成功!\n"); DisPlaybroad(mine); } } int Get_Mine(char mine[ROWS][COLS], int x, int y)//排雷 {//在ascll表中数字都有对应的ascll值,且是10个连续的,对应0~9,数字字符 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'); }//判断附近8个位置中雷的个数,1是字符不是数字有对应的ascll值,-8*‘0’减去8个字符0的ascll值
以上便是游戏各模块的实现。
3.5 游戏逻辑安排
游戏的各个模块我们已经基本实现,接下来我们需要将各个模块进行组装,使游戏顺利运行。
void game() { char mine[ROWS][COLS]; char show[ROWS][COLS]; //初始化棋盘 InitBoard(mine,'0'); InitBoard(show,'*'); //埋雷 SetMine(mine); //打印棋盘 DisPlaybroad(show); //排雷+判赢 FindMine(mine,show); }
首先我们创建了两个二维数组,游戏开始需要先初始化棋盘,游戏开始前我们需要先进行埋雷操作,然后才是打印棋盘,最后就是判赢。这就是游戏大概整体逻辑。
4. 代码
以下便是整体代码的呈现:
用于声明的头文件(.h文件)
#include<stdio.h> #include<stdlib.h> #include<time.h> #define ROW 9 #define COL 9 #define ROWS ROW+2 #define COLS COL+2 #define N 10 //初始化棋盘 void InitBoard(char board[ROWS][COLS], char set); //打印棋盘 void DisPlaybroad(char board[ROWS][COLS]); //埋雷 void SetMine(char board[ROWS][COLS]); //排雷 void FindMine(char mine[ROWS][COLS],char show[ROWS][COLS]);
函数定义文件(.c文件)
#include"game1.h" void InitBoard(char board[ROWS][COLS], char set) { for (int i = 0; i < ROWS; i++) { for (int j = 0; j < COLS; j++) { board[i][j] = set; } } } void DisPlaybroad(char board[ROWS][COLS]) { printf("------------------扫雷游戏------------------\n"); printf(" "); for (int i = 1; i <=COL; i++) { printf(" %d ", i); } printf("\n"); printf(" -----------------------------------"); printf("\n"); for (int i = 1; i <= ROW; i++) { printf("%d ",i); for (int j = 1; j <= COL; j++) { printf(" %c ", board[i][j]); if (j < COL) { printf("|"); } } printf("\n"); if (i < ROW) { for (int i = 1; i <=ROW; i++) { if (i ==1) { printf(" "); } printf("---"); if (i < ROW) { printf("|"); } } printf("\n"); } } } void SetMine(char board[ROWS][COLS]) { int count = N; while (count) { int x = rand() % ROW + 1; int y = rand() % COL + 1; if (board[x][y] == '0') { board[x][y] = '1'; count--; } } } void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS]) { int x = 0; int y = 0; int win = 0; while (win<COL*ROW-N) //判赢 { printf("请输入要排查的位置>:\n"); scanf("%d%d", &x, &y); if (x >= 1 && x <= 9 && y >= 1 && y <= 9) { if (mine[x][y] == '1') { printf("很遗憾,你踩到了雷,游戏结束!\n"); DisPlaybroad(mine); break; } else { show[x][y] = Get_Mine(mine, x, y) + '0'; DisPlaybroad(show); win++; } } else { printf("坐标非法,请重新输入!\n"); } } if (win == ROW * COL - N) { printf("恭喜你排雷成功!\n"); DisPlaybroad(mine); } } int Get_Mine(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'); }
游戏主体(.c文件)
#include"game1.h" void menu() { printf("******************************\n"); printf("********* 1.play *********\n"); printf("********* 0.exit *********\n"); printf("******************************\n"); } void game() { char mine[ROWS][COLS]; char show[ROWS][COLS]; //初始化棋盘 InitBoard(mine,'0'); InitBoard(show,'*'); //埋雷 SetMine(mine); //打印棋盘 DisPlaybroad(show); //排雷+判赢 FindMine(mine,show); } int main() { int input = 0; srand((unsigned int)time(NULL)); do { menu(); printf("请选择>:\n"); scanf("%d", &input); switch (input) { case 1: game(); break; case 0: printf("退出游戏!\n"); break; default: printf("输入错误请重新输入>:\n"); break; } } while (input); return 0; }
总结
以上就是今天要讲的内容,本文仅仅使用简单的C语言基础语法来实现的扫雷小游戏,希望可以对你有所帮助,感谢阅读!