C语言实现简易版扫雷游戏
本文实例为大家分享了C语言实现扫雷游戏的具体代码,供大家参考,具体内容如下
这个小项目源自两个月前学数组的时候,由于觉得比较重要,想记录一下。
首先,大概的思路是要做出两个二维数组充当棋盘,一个用于后台储存雷的情况,一个用于打印给玩家玩游戏
那么第一步我们知道,需要声明两个二维数组,一个打印出来给用户看,一个自己深埋在心里。
第二步应该是要埋雷,这里我们可以定义几个数值去让玩家选择埋雷的数量。
第三步也就是最难的扫雷部分了,我的思路是,首先玩家先输入一个坐标,我们再对玩家输入的坐标找到对应藏雷的数组,若此坐标就是雷,则反馈玩家游戏结束,若不是雷,则计算周围九宫格的雷数,并以数字的形式反馈给玩家。
第四步是最后一步,我们要在玩家输入坐标并得到反馈之后判断雷的数量是否为0,如果是则游戏结束,不是则继续,显然,第三第四步是在一个循环里面的。
下面是整个游戏的流程图
下面开始代码实现
我们先写出一个主函数
int main(void) { test(); return 0; }
我们在test()函数中实现所有的游戏
首先写出游戏主体
游戏主体
void test() { int input = 0; srand((unsigned)time(NULL)); do { menu();//打印菜单 scanf("%d", &input);//让用户输入 switch (input) { case 1: printf("游戏开始\n"); game();//玩游戏 break; case 0: printf("退出游戏\n"); break; default: printf("输入非法,请重新输入:>\n"); break; } } while (input); }
设计菜单
void menu() { printf("******************************************************\n"); printf("**************** 1.进入游戏 ****************\n"); printf("**************** 0.退出游戏 ****************\n"); printf("******************************************************\n"); }
我们把game函数暂时注释后打印菜单检查
接着进行下一步操作–制作游戏主体
游戏主体
自己定义头文件game.h,并在其中引用头文件
#include <stdio.h> #include <stdlib.h> #include <time.h>
我想做一个10*10大小的棋盘,但是考虑到后面查找雷数量需要遍历9宫格,如果遍历到边界处则特别麻烦,所以我们不妨把数组行列设置为11 * 11。这样设置以后,布置雷的时候只要用到10 * 10的数组,外边一圈不布置,就很巧妙的避开了上述问题。
#define ROWS 11 #define COLS 11
接下来开始写game()函数
void game() { //创建棋盘并初始化 char mine[ROWS][COLS] = {0}; char show[ROWS][COLS] = {0}; //0代表不是雷 //mine数组是后天储存雷用的 //show数组是打印出来给玩家看的 }
接着分别初始化两个数组
//创建棋盘 char mine[ROWS][COLS] = {0}; char show[ROWS][COLS] = {0}; //初始化棋盘 initBoard(mine, ROWS, COLS, '0'); initBoard(show, ROWS, COLS, '*');
定义初始化数组的函数
void initBoard(char board[ROWS][COLS], int rows, int cols, char set) { int i; int j; for (i = 0; i < rows; i++) { for (j = 0; j < cols; j++) { board[i][j] = set; } } }
接下来打印棋盘给玩家看
void game() { //1.布置好的雷的信息 char mine[ROWS][COLS] = {0}; //2.排查出雷的信息 char show[ROWS][COLS] = {0}; //初始化 initBoard(mine, ROWS, COLS, '0'); initBoard(show, ROWS, COLS, '*'); //打印棋盘 printBoard(show, ROW, COL); }
之前说了最后一圈数组是不给玩家看的,所以再加入宏定义
#define ROW ROWS - 2 #define COL COLS - 2
打印棋盘函数设置
void printBoard(char board[ROWS][COLS], int row, int col) { int i, j; int cnt = 0; //打印列号 printf(" "); for (i = 1; i <= col; i++) { printf("%d ", i); } printf("\n"); for (i = 1; i <= row; i++) { printf("%d", i); //打印行号 for (j = 1; j <= col; j++) { printf(" %c ", board[i][j]); cnt++; if (cnt % 9 == 0) { printf("\n"); cnt = 0; } } } }
接下来布置雷
void game() { //1.布置好的雷的信息 char mine[ROWS][COLS] = {0}; //2.排查出雷的信息 char show[ROWS][COLS] = {0}; //初始化 initBoard(mine, ROWS, COLS, '0'); initBoard(show, ROWS, COLS, '*'); //打印棋盘 printBoard(show, ROW, COL); //布置雷 putMine(mine, ROW, COL); }
布置雷函数设置
void putMine(char board[ROWS][COLS], int row, int col) { int cnt = modeChoose();//在此加入模式选择 while (cnt > 0) { int x; int y; while (1) { //置入随机坐标 x = rand() % row + 1; y = rand() % col + 1; if (board[x][y] == '0') { board[x][y] = '1'; cnt--; break; } } } }
设置模式选择函数
首先定义不同难度所放置的雷数
#define EASY_COUNT 10 #define PRIME_COUNT 20 #define HARD_COUNT 50
接下来做modeChoose()函数
int modeChoose(void) { printf("**************** 1.简单难度 ****************\n"); printf("**************** 2.普通难度 ****************\n"); printf("**************** 3.困难难度 ****************\n"); printf("请输入你想要玩的难度:>"); int mode; int n; do { scanf("%d", &mode); switch (mode) { case 1: n = EASY_COUNT; break; case 2: n = PRIME_COUNT; break; case 3: n = HARD_COUNT; break; default: printf("输入非法,请重新输入:>\n"); break; } } while (mode != 1 && mode != 2 && mode != 3); return n; }
类比菜单,让用户选择
做完这些以后,就开始扫雷了
扫雷
void game() { //创建棋盘 char mine[ROWS][COLS] = {0}; char show[ROWS][COLS] = {0}; //初始化棋盘 initBoard(mine, ROWS, COLS, '0'); initBoard(show, ROWS, COLS, '*'); //布置雷 putMine(mine ,ROW,COL); //打印棋盘 printBoard(show,ROW,COL); //扫雷 findMine(mine,show,ROWS,COLS); }
扫雷函数设置
void findMine(char mine[ROWS][COLS], char show[ROWS][COLS], int rows, int cols) { printf("请输入你要排查雷的坐标(示例:2 5):>"); int x, y; }
首先提示玩家输入坐标,然后在循环里读入这个坐标
void findMine(char mine[ROWS][COLS], char show[ROWS][COLS], int rows, int cols) { printf("请输入你要排查雷的坐标(示例:2 5):>"); int x, y; //判断x,y周围在mine数组周围有几个雷,并将此数目传给show while (1) { scanf("%d %d", &x, &y); } }
首先判断输入坐标是否超出数组范围,是的话提醒用户重新输入,不是的话进行下一步处理。
接下来分情况考虑,首先判断读入的坐标在数组中是不是雷(用1表示雷),是的话游戏结束,不是的话进行下一步处理
void findMine(char mine[ROWS][COLS], char show[ROWS][COLS], int rows, int cols) { printf("请输入你要排查雷的坐标(示例:2 5):>"); int x, y; //判断x,y周围在mine数组周围有几个雷,并将此数目传给show while (1) { scanf("%d %d", &x, &y); while (1) { if (x < 1 || x > 9 || y < 1 || y > 9) { printf("输入坐标非法,请重新输入!:>\n"); break; } else { break; } } if (mine[x][y] == '1') { printf("很遗憾,你被炸死了!\n"); printBoard(mine, ROW, COL);//游戏结束了就可以打印后台棋盘给玩家看了 break; } else { //下一步处理 } } }
现在我们需要确定,踩下坐标不为雷的情况。
若不为0,我们通过递归去判断这个坐标周围为0的情况,把为0的情况自动去除后再打印给玩家看,去除雷的坐标用空格打印。
这样分析下来,我们需要再封装一个函数
void findMine(char mine[ROWS][COLS], char show[ROWS][COLS], int rows, int cols) { printf("请输入你要排查雷的坐标(示例:2 5):>"); int x, y; //判断x,y周围在mine数组周围有几个雷,并将此数目传给show while (1) { scanf("%d %d", &x, &y); while (1) { if (x < 1 || x > 9 || y < 1 || y > 9) { printf("输入坐标非法,请重新输入!:>\n"); break; } else { break; } } if (mine[x][y] == '1') { printf("很遗憾,你被炸死了!\n"); printBoard(mine, ROW, COL); break; } else { findZero(mine, show, x, y); } } }
findzero函数实现
void findZero(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y) { if (mineCount(mine, x, y) == '0')//若雷的数量为0 { show[x][y] = ' '; if (show[x - 1][y] == '*') { findZero(mine, show, x - 1, y); } if (show[x][y - 1] == '*') { findZero(mine, show, x, y - 1); } if (show[x][y + 1] == '*') { findZero(mine, show, x, y + 1); } if (show[x + 1][y] == '*') { findZero(mine, show, x + 1, y); } } else { char count = mineCount(mine, x, y); show[x][y] = count; } }
其中mineCount函数定义如下
char mineCount(char board[ROWS][COLS], int x, int y) { //遍历从x-1,y-1到x+1,y+1的雷数并返回 int i, j; char cnt = '0'; for (i = x - 1; i <= (x + 1); i++) { for (j = y - 1; j <= (y + 1); j++) { if (board[i][j] == '1') { cnt = cnt + 1; } } } return cnt; }
记得每次操作完要打印数组给玩家看,这之后再写一段判断游戏是否结束的代码就大功告成了qwq。
void findMine(char mine[ROWS][COLS], char show[ROWS][COLS], int rows, int cols) { printf("请输入你要排查雷的坐标(示例:2 5):>"); int x, y; //判断x,y周围在mine数组周围有几个雷,并将此数目传给show while (1) { scanf("%d %d", &x, &y); while (1) { if (x < 1 || x > 9 || y < 1 || y > 9) { printf("输入坐标非法,请重新输入!:>\n"); break; } else { break; } } if (mine[x][y] == '1') { printf("很遗憾,你被炸死了!\n"); printBoard(mine, ROW, COL); break; } else { findZero(mine, show, x, y); printBoard(show, ROW, COL); int i, j; int cnt = 0; //判断扫雷是否全部完成 for (i = 1; i <= ROW; i++) { for (j = 1; j <= COL; j++) { if (show[i][j] == '*') { cnt++; } } } if (cnt == 0) { printf("恭喜你通关游戏!\n"); break; } else { printf("请输入你要排查雷的坐标(示例:2 5):>\n"); } } } }
总代码如下
总代码
test.c
#include "game.h" void menu() { printf("******************************************************\n"); printf("**************** 1.进入游戏 ****************\n"); printf("**************** 0.退出游戏 ****************\n"); printf("******************************************************\n"); } void game() { //创建棋盘 char mine[ROWS][COLS] = {0}; char show[ROWS][COLS] = {0}; //初始化棋盘 initBoard(mine, ROWS, COLS, '0'); initBoard(show, ROWS, COLS, '*'); //布置雷 putMine(mine ,ROW,COL); //打印棋盘 printBoard(show,ROW,COL); //扫雷 findMine(mine,show,ROWS,COLS); } void test() { int input = 0; srand((unsigned)time(NULL)); do { menu(); scanf("%d", &input); switch (input) { case 1: printf("游戏开始\n"); game(); break; case 0: printf("退出游戏\n"); break; default: printf("输入非法,请重新输入:>\n"); break; } } while (input); } int main(void) { test(); return 0; }
头文件game.h
#include <stdio.h> #include <stdlib.h> #include <time.h> #define ROWS 11 #define COLS 11 #define ROW ROWS - 2 #define COL COLS - 2 #define EASY_COUNT 10 #define PRIME_COUNT 20 #define HARD_COUNT 50 void initBoard(char board[ROWS][COLS], int row, int col, char ch); void printBoard(char show[ROWS][COLS], int row, int col); void putMine(char board[ROWS][COLS], int row, int col); void findMine(char mine[ROWS][COLS], char show[ROWS][COLS], int rows, int cols);
game.c
#include "game.h" void initBoard(char board[ROWS][COLS], int row, int col, char ch) { //初始化数组 int i, j; for (i = 0; i < row; i++) { for (j = 0; j < col; j++) { board[i][j] = ch; } } } void printBoard(char board[ROWS][COLS], int row, int col) { int i; int j; int flag = 0; printf(" "); for (i = 1; 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 ", board[i][j]); flag++; } if (flag % 9 == 0) { printf("\n"); flag = 0; } } } int modeChoose(void) { printf("**************** 1.简单难度 ****************\n"); printf("**************** 2.普通难度 ****************\n"); printf("**************** 3.困难难度 ****************\n"); printf("请输入你想要玩的难度:>"); int mode; int n; do { scanf("%d", &mode); switch (mode) { case 1: n = EASY_COUNT; break; case 2: n = PRIME_COUNT; break; case 3: n = HARD_COUNT; break; default: printf("输入非法,请重新输入:>\n"); break; } } while (mode != 1 && mode != 2 && mode != 3); return n; } void putMine(char board[ROWS][COLS], int row, int col) { int cnt = modeChoose();//再此加入模式选择 while (cnt > 0) { int x; int y; while (1) { //置入随机坐标 x = rand() % row + 1; y = rand() % col + 1; if (board[x][y] == '0') { board[x][y] = '1'; cnt--; break; } } } } char mineCount(char board[ROWS][COLS], int x, int y) { //遍历从x-1,y-1到x+1,y+1的雷数并返回 int i, j; char cnt = '0'; for (i = x - 1; i <= (x + 1); i++) { for (j = y - 1; j <= (y + 1); j++) { if (board[i][j] == '1') { cnt = cnt + 1; } } } return cnt; } void findZero(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y) { if (mineCount(mine, x, y) == '0')//若雷的数量为0 { show[x][y] = ' '; if (show[x - 1][y] == '*') { findZero(mine, show, x - 1, y); } if (show[x][y - 1] == '*') { findZero(mine, show, x, y - 1); } if (show[x][y + 1] == '*') { findZero(mine, show, x, y + 1); } if (show[x + 1][y] == '*') { findZero(mine, show, x + 1, y); } } else { char count = mineCount(mine, x, y); show[x][y] = count; } } void findMine(char mine[ROWS][COLS], char show[ROWS][COLS], int rows, int cols) { printf("请输入你要排查雷的坐标(示例:2 5):>"); int x, y; //判断x,y周围在mine数组周围有几个雷,并将此数目传给show while (1) { scanf("%d %d", &x, &y); while (1) { if (x < 1 || x > 9 || y < 1 || y > 9) { printf("输入坐标非法,请重新输入!:>\n"); break; } else { break; } } if (mine[x][y] == '1') { printf("很遗憾,你被炸死了!\n"); printBoard(mine, ROW, COL); break; } else { findZero(mine, show, x, y); printBoard(show, ROW, COL); int i, j; int cnt = 0; //判断扫雷是否全部完成 for (i = 1; i <= ROW; i++) { for (j = 1; j <= COL; j++) { if (show[i][j] == '*') { cnt++; } } } if (cnt == 0) { printf("恭喜你通关游戏!\n"); break; } else { printf("请输入你要排查雷的坐标(示例:2 5):>\n"); } } } }
运行示例
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。