时间:2020-10-04 14:43:20 | 栏目:C代码 | 点击:次
这是一个用C语言实现的控制台扫雷小游戏,实现了随机布置炸弹、扫描炸弹、标记炸弹、百分百第一次不被炸死等功能。
编译器:vs2015
功能模块图
源代码
#include<stdio.h> #include<stdlib.h> #include<time.h> void show(int cbd[10][10],int u[10][10]) //界面输出函数 { int i, j; //for (i = 0; i < 10; i++) //输出全部炸弹信息(上帝视角,调试用) //{ // for (j = 0; j < 10; j++) // { // printf("%2d ", cbd[i][j]); // } // printf("\n"); //} printf(" 1 2 3 4 5 6 7 8 9 10\n"); //行标 printf(" --------------------\n"); for (i = 0; i<10; i++) //根据u数组和cbd数组的值选择输出 { //■:未扫描,□:周围无炸弹,◇:炸弹标记 for (j = 0; j<10; j++) { if (j == 0)printf("%2d?U ", i+1); if (u[i][j] == 0)printf("■"); else if (u[i][j] == 1) { if (cbd[i][j] == 0)printf("□"); else printf("%2d", cbd[i][j]); } else if (u[i][j] == -1) { printf("◇"); } } printf("\n"); } } int find(int cbd[10][10], int i, int j) //扫描周围炸弹数目 { int l, c,lmin,cmin, lmax, cmax, num = 0; l = lmin = (i - 1) >= 0 ? (i - 1) : 0; //计算行、列起点 c = cmin = (j - 1) >= 0 ? (j - 1) : 0; lmax = ((i + 1) < 10 ? (i + 1) : 9); //计算行、列终点 cmax = ((j + 1) < 10 ? (j + 1) : 9); for (l = lmin; l <= lmax; l++) { for (c = cmin; c <= cmax; c++) { if (l == i&&c == j)continue; //跳过自身 if (cbd[l][c] == -1)num++; //炸弹计数 } } return num; } void init(int cbd[10][10]) //cbd数组初始化(随机布置炸弹并填充各个格子的数目) { int n = 10, l, c, i, j; srand(time(NULL)); //随机数种子设置 for (i = 0; i< 10; i++) { for (j = 0; j< 10; j++) { cbd[i][j] = 0; //全0填充 } } while (n--) //随机行列放置炸弹 { l = rand() % 10; c = rand() % 10; if (cbd[l][c] != -1)cbd[l][c] = -1; //炸弹重复处理 else n++; } for (i = 0; i< 10; i++) { for (j = 0; j< 10; j++) { if (cbd[i][j] != -1) { cbd[i][j] = find(cbd, i, j); //炸弹数目填充 } } } } void open(int cbd[10][10],int u[10][10], int i, int j) //周围无炸弹时的展开函数(递归展开) { u[i][j] = 1; if (cbd[i][j] == 0) { if(i - 1 >= 0 && u[i - 1][j] != 1)open(cbd, u, i - 1, j); //上 if(j - 1 >= 0 && u[i][j - 1] != 1)open(cbd, u, i, j - 1); //左 if (i + 1 <= 9 && u[i + 1][j] != 1)open(cbd, u, i + 1, j); //下 if (j + 1 <= 9 && u[i][j + 1] != 1)open(cbd, u, i, j + 1); //右 } } int judge(int u[10][10]) //判断游戏是否通关 { int i, j, num = 0; for (i = 0; i < 10; i++) { for (j = 0; j < 10; j++) { if (u[i][j] == 0 || u[i][j] == -1)num++; } } if (num == 10)return 1; else return 0; } void fail(int cbd[10][10], int u[10][10]) //游戏失败函数 { int i, j; for (i = 0; i < 10; i++) //输出全部炸弹信息 { for (j = 0; j < 10; j++) { if (cbd[i][j] == 0)printf(" "); else if (cbd[i][j] != -1)printf("%2d", cbd[i][j]); else printf("●"); } printf("\n"); } printf("请大侠重新来过~\n"); } void menu(int cbd[10][10],int u[10][10]) //菜单函数 { int chs,i,j; int boom = 10; //剩余炸弹数 int num = 0; //步数 while (1) { system("cls"); show(cbd,u); printf("还有%d个炸弹\n",boom); printf("1.扫描 2.标记 3.取消标记\n"); printf("请输入选项:>"); scanf("%d", &chs); if (chs > 3 || chs < 1) { printf("请输入正确选项!\n"); system("pause"); continue; } printf("请输入坐标:>"); scanf("%d %d", &i, &j); if (i < 1 || i>10) { printf("请输入正确坐标!\n"); system("pause"); continue; } i--; //输入行列数处理(适用数组下标) j--; if (chs == 1) { if (cbd[i][j] == -1) { if (num == 0) { //若第一步扫描到炸弹,就重新初始化棋盘 init(cbd); show(cbd, u); open(cbd, u, i, j); num++; continue; } else { fail(cbd, u); //否则游戏失败,循环跳出 break; } } if (u[i][j] == 1) //重复扫描时的处理 { printf("该位置已经扫描过了!\n"); system("pause"); continue; } open(cbd, u, i, j); num++; } else if(chs == 2) { if (u[i][j] == 1) { printf("该位置已经扫描过了!\n"); //只能标记未扫描到的 system("pause"); continue; } u[i][j] = -1; boom --; } else if (chs == 3) { if (u[i][j] != -1) { printf("该位置没有标记!\n"); //只能取消标记过的 system("pause"); continue; } u[i][j] = 0; boom++; } if (judge(u)) //判断游戏是否通关 { printf("Old Fe 666!\n"); //老铁666!,循环跳出 break; } } } int main() { int cbd[10][10] = { 0 }; //保存炸弹信息的二维数组 int u[10][10] = { 0 }; //保存是否翻开信息的二维数组 init(cbd); //数组初始化 menu(cbd, u); //进入菜单 return 0; }
Tips:在扫描到周围无炸弹的格子时,要将此格子周围的部分依次打开,直到上下左右都出现炸弹数字为止,这里要用到递归的方法,我的顺序为依次递归处理上、左、下、右的格子,这里顺序可以任意。