背景
个人比较喜欢玩扫雷,恰好又在学习C语言,所以想用自己薄弱的C语言水平实现简单的扫雷小游戏。一来提高自己的编程水平,二来通过编写自己喜欢的游戏,从另一方面获得不一样的成就感。
框架
实现扫雷不同于我前面写过的三子棋,扫雷的功能更加复杂,更加有逻辑性。
我首先将我能想到的几个模块都一一列举出来:
游戏实现函数 菜单 初始化雷区 布置雷区 打印雷区 统计雷区剩余方块
无雷方块展开函数 新手保护函数(第一次踩雷不死)
这里我已将大纲写好, 之后开始编写补充函数内容。
运行效果
不过想必小伙伴们也看到了,这个小游戏只适合展示,不适合尽情玩耍。(因为实在太费眼睛)
( 也请有意改进的小伙伴,关注我接下来对扫雷的完善,我最终会将这个简易版扫雷实现为windows系统下经典扫雷的样式。)
源代码
下面是我写的代码,如果有不足之处,非常欢迎小伙伴们积极指出。
(如果有小伙伴有不懂的地方,欢迎在评论区提问)
头文件
#ifndef __SAOLEI_H__ #define __SAOLEI_H__ #include <stdio.h> #include <time.h> #include <string.h> #include <stdlib.h> #define ROW 10 #define COL 10 void game(void); //游戏主体 void menu(void); //菜单 void set_mine(char mine[ROW + 2][COL + 2], int row, int col, int num); //布雷 int mine_num(char mine[ROW + 2][COL + 2], int x, int y); //统计某个位置周围雷的个数 int mine_count(char board[ROW + 2][COL + 2], int row, int col); //统计剩余*的数目 void spread_board(char board[ROW + 2][COL + 2], char mine[ROW + 2][COL + 2], int x, int y); //展开无雷区 void print_board(char board[ROW + 2][COL + 2], int row, int col); //打印雷区 void new_help(char mine[ROW + 2][COL + 2], int x, int y); //新手保护(第一次扫雷不会被炸死) #endif
功能函数
#define _CRT_SECURE_NO_WARNINGS #include "saolei.h" #include <stdio.h> #include <time.h> #include <string.h> #include <stdlib.h> #define ROW 10 #define COL 10 void print_board(char board[ROW + 2][COL + 2], int row, int col) //打印雷区 { printf("\n"); int i = 0; printf(" 0 1 2 3 4 5 6 7 8 9 10\n"); for (i = 1; i < (row - 1); i++) { int j = 0; printf("%2d ", i); for (j = 1; j < (col - 1); j++) { printf("%2c", board[i][j]); } printf("\n"); } printf("\n"); } int mine_count(char board[ROW + 2][COL + 2], int row, int col) //统计剩余*的数目 { int count = 0; for (int i = 1; i < (row - 1); i++) { for (int j = 1; j < (col - 1); j++) { if (board[i][j] == '*') count++; } } return count; } int mine_num(char mine[ROW + 2][COL + 2], int x, int y) //统计某个位置周围雷的个数 { return ((mine[x - 1][y - 1] - '0') + (mine[x - 1][y] - '0') + (mine[x - 1][y + 1] - '0') + (mine[x][y + 1] - '0') + (mine[x + 1][y + 1] - '0') + (mine[x + 1][y] - '0') + (mine[x + 1][y - 1] - '0') + (mine[x][y - 1] - '0')); } void spread_board(char board[ROW + 2][COL + 2], char mine[ROW + 2][COL + 2], int x, int y) //展开无雷区 { if ((1 <= x && x <= 10) && (1 <= y && y <= 10) && (mine[x][y] != '1') && (board[x][y] == '*')) { if (mine_num(mine, x, y) > 0) { board[x][y] = mine_num(mine, x, y) + '0'; } else { board[x][y] = ' '; spread_board(board, mine, x - 1, y - 1); spread_board(board, mine, x - 1, y); spread_board(board, mine, x - 1, y + 1); spread_board(board, mine, x, y + 1); spread_board(board, mine, x + 1, y + 1); spread_board(board, mine, x + 1, y); spread_board(board, mine, x + 1, y - 1); spread_board(board, mine, x, y - 1); } } } void set_mine(char mine[ROW + 2][COL + 2], int row, int col, int num) //布雷 { int i = 0; srand((unsigned)time(NULL)); for (i = 0; i < num; i++) { int x = rand() % (row - 2) + 1; int y = rand() % (col - 2) + 1; if (mine[x][y] == '0') { mine[x][y] = '1'; } else { i--; } } } void new_help(char mine[ROW+2][COL+2], char board[ROW+2][COL+2]) //新手保护(第一次扫雷不会被炸死) { int x = 0; int y = 0; srand((unsigned)time(NULL)); while (1) { //输入排雷坐标(同时判断坐标合法性) printf("请输入坐标(X,Y):>"); scanf("%d,%d", &x, &y); if ((1 <= x && x <= 10) && (1 <= y && y <= 10)) { if (mine[x][y] == '1') { mine[x][y] = '0'; while (1) { int m = rand() % ROW + 1; int n = rand() % COL + 1; if ((m != x) && (n != y) && (mine[m][n] == '0')) { mine[m][n] = '1'; spread_board(board, mine, x, y); print_board(board, (ROW + 2), (COL + 2)); break; } } } else { spread_board(board, mine, x, y); print_board(board, (ROW + 2), (COL + 2)); } break; } else { printf("你输入的坐标可能指向其他星系。\n\n"); } } } void menu(void) //菜单 { printf("*********************\n"); printf("** 1.开始游戏 **\n"); printf("** 0.退出游戏 **\n"); printf("*********************\n"); printf("请选择要进行的动作:>"); } void game(void) //游戏主体 { int x = 0; int y = 0; int count = 0; //定义剩余雷数 int num = 0; //定义雷区,迷雾区 char mine[ROW + 2][COL + 2]; char board[ROW + 2][COL + 2]; //初始化雷区,迷雾区 memset(mine, '0', sizeof(mine)); memset(board, '*', sizeof(board)); //布雷 printf("请输入地雷数(建议10~30) : >"); scanf("%d", &num); set_mine(mine, (ROW + 2), (COL + 2), num); //打印迷雾区 print_board(board, (ROW + 2), (COL + 2)); //新手保护 new_help(mine, board); while (1) { //判断是否胜利 count = mine_count(board, (ROW + 2), (COL + 2)); if (count == num) { printf("恭喜你,你成功的排掉了所有雷!\n\n"); break; } //输入排雷坐标(同时判断坐标合法性) printf("请输入坐标(X,Y):>"); scanf("%d,%d", &x, &y); if ((1 <= x && x <= 10) && (1 <= y && y <= 10)) { if (mine[x][y] == '1') { printf("哦!你踩到雷了,再接再厉吧!!!\n\n"); break; } else { spread_board(board, mine, x, y); print_board(board, (ROW + 2), (COL + 2)); } } else { printf("你输入的坐标可能指向其他星系。\n"); } } }
主体函数
#define _CRT_SECURE_NO_WARNINGS 1 #include <stdio.h> #include "saolei.h" int main() { int input = 0; do { menu(); scanf("%d", &input); switch (input) { case 1: game(); break; case 0: printf("\n退出游戏。\n\n"); break; default: printf("\n输入错误!\n\n请重新输入。\n\n"); break; } } while (input); return 0; }