文章目录
- 前言
- 一、排雷函数菜单
- 二、排雷函数菜单的实现
- 三、拓展棋盘功能
- 四、源码
- 1. test.c源文件
- 2. game.h头文件
- 3. game.c源文件
- 总结
前言
C语言实现扫雷游戏的排雷菜单,以及功能的实现,拓展棋盘功能,以及源码等。
上半部分的链接地址:
C语言扫雷游戏完整实现(上)
一、排雷函数菜单
- 排雷函数菜单就只有1.排雷 和 2. 退出两个选择。
//test.c 源文件
void game()
{int choose = 0;int count = 0;int sum = 0;// 定义两个二维数组char mine[ROWS][COLS] = { 0 };char show[ROWS][COLS] = { 0 };// 初始化棋盘InitBoard(mine, ROWS, COLS, '0');InitBoard(show, ROWS, COLS, '*');// 布置雷SetBoard(mine, ROW, COL);// 打印棋盘DisplayBoard(mine, ROW, COL);DisplayBoard(show, ROW, COL);// 玩家开始排雷do{printf("****************\n");printf("*** 1. 标记 ***\n");printf("*** 2. 排雷 ***\n");printf("*** 0. 退出 ***\n");printf("****************\n");printf("请选择:>");scanf("%d", &choose);if (1 == choose){count = SignBoard(show, mine, ROW, COL);if (count != 0){printf("恭喜你,排雷成功!!\n");break;}}else if (2 == choose){printf("排雷功能\n"); // 可以删除sum = FineBoard(show, mine, ROW, COL);}else if (0 == choose){printf("退出游戏\n");break;}else{printf("输入错误,请重新输入\n");}} while (choose);}
//game.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 EASY_COUNT 1// 初始化函数声明
void InitBoard(char board[ROWS][COLS], int rows, int cols, char sign);// 打印函数声明
void DisplayBoard(char board[ROWS][COLS], int row, int col);// 布置雷函数声明
void SetBoard(char board[ROWS][COLS], int row, int col);// 标记功能函数声明
int SignBoard(char show[ROWS][COLS],char mine[ROWS][COLS], int row, int col);// 排雷函数声明
int FineBoard(char show[ROWS][COLS], char mine[ROWS][COLS], int row, int col);
//game.c 源文件 -- FineBoard函数菜单部分
// 排雷函数声明
int FineBoard(char show[ROWS][COLS], char mine[ROWS][COLS], int row, int col)
{int goway = 0;do{printf("**************\n");printf("*** 1.排雷 ***\n");printf("*** 0.退出 ***\n");printf("**************\n");printf("请选择:>");scanf("%d", &goway);if (1 == goway){printf("排雷开始\n");}else if (0 == goway){printf("退出游戏\n");}else{printf("输入错误,请重新输入\n");}} while (goway);
效果如下图:
二、排雷函数菜单的实现
- 玩家需要输入坐标,若超出范围或不合法应该重新输入,所以要用循环
- 若玩家选择的位置不是雷,则显示周围雷的个数。
//test.c 源文件-- game函数
void game()
{int choose = 0;int count = 0;int sum = 0;// 定义两个二维数组char mine[ROWS][COLS] = { 0 };char show[ROWS][COLS] = { 0 };// 初始化棋盘InitBoard(mine, ROWS, COLS, '0');InitBoard(show, ROWS, COLS, '*');// 布置雷SetBoard(mine, ROW, COL);// 打印棋盘DisplayBoard(mine, ROW, COL);DisplayBoard(show, ROW, COL);// 玩家开始排雷do{printf("****************\n");printf("*** 1. 标记 ***\n");printf("*** 2. 排雷 ***\n");printf("*** 0. 退出 ***\n");printf("****************\n");printf("请选择:>");scanf("%d", &choose);if (1 == choose){count = SignBoard(show, mine, ROW, COL);if (count != 0){printf("恭喜你,排雷成功!!\n");break;}}else if (2 == choose){printf("排雷功能\n");sum = FineBoard(show, mine, ROW, COL);if (-1 == sum){printf("恭喜你,排雷成功!!\n");DisplayBoard(mine, ROW, COL);break;}else if (404 == sum){printf("很遗憾,你被炸死了!\n");DisplayBoard(mine, ROW, COL);break;}}else if (0 == choose){printf("退出游戏\n");break;}else{printf("输入错误,请重新输入\n");}} while (choose);}
//game.c 源文件-- FindBoard函数和BoomCount函数
// 计算周围雷的个数函数
int BoomCount(char board[ROWS][COLS], int x, int y)
{int i = 0;int sum = 0;for (i = -1; i <= 1; i++){int j = 0;for (j = -1; j <= 1; j++){if (i == j && 0 == j){continue;}sum = sum + board[x+i][y+j] - '0';}}return sum;
}// 排雷函数声明
int FineBoard(char show[ROWS][COLS], char mine[ROWS][COLS], int row, int col)
{int goway = 0;int x = 0;int y = 0;static int number = 0;do{printf("**************\n");printf("*** 1.排雷 ***\n");printf("*** 0.取消 ***\n");printf("**************\n");printf("请选择:>");scanf("%d", &goway);if (1 == goway){while (1){printf("请输入排雷坐标(空格间隔):");scanf("%d %d", &x, &y);if (x >= 1 && x <= row && y >= 1 && y <= col) // 判断坐标合法性{if (show[x][y] == '*') // 判断是否被排查{if (mine[x][y] == '1'){return 404;}else{// 调用计算周围雷个数的函数int bct = BoomCount(mine, x, y);show[x][y] = bct + '0';DisplayBoard(show, ROW, COL);number++;break;}}else{printf("此位置已经排查完,请勿重复排查\n");break;}}else{printf("超出棋盘范围,请重新输入\n");}}if (number == row * col - EASY_COUNT){number = 0; // 游戏胜利,number重置为1return -1;}}else if (0 == goway){printf("取消排雷\n");}else{printf("输入错误,请重新输入\n");}} while (goway);}
- 将雷的数量设置为79个即只有两个不是雷进行测试
- 效果如下图:
三、拓展棋盘功能
- 此功能再排雷是判定选择的位置已经不是雷情况下执行。
- 采用函数递归
-
- 如果这个位置周围没有雷,则这个位置可以为空格。
-
- 这个位置周围八个坐标没有排查过,排查过的位置直接跳过。
-
- 函数内部调用再次调用拓展函数,重新判断
-
- 如果满足继续排查
-
- 如果周围有雷,则停止排查,并将此位置显示周围雷的个数。
//game.c 源文件--ExtendBoard函数
// 拓展函数定义
void ExtendBoard(char show[ROWS][COLS], char mine[ROWS][COLS], int x, int y)
{int count = BoomCount(mine, x, y);if (count == 0){show[x][y] = ' ';int i = 0;for (i = -1; i <= 1; i++){int j = 0;for (j = -1; j <= 1; j++){if (i == j && 0 == j){continue;}if (show[x + i][y + j] != '*'){continue;}ExtendBoard(show, mine, x + i, y + j);}}}else{show[x][y] = count + '0';}}
这里只展示了一下拓展的效果。
拓展的效果如下图:
四、源码
1. test.c源文件
#include "game.h"
// 定义游戏菜单函数
void menu()
{printf("**********************\n");printf("***** 1. Play *****\n");printf("***** 0. Quit *****\n");printf("**********************\n");
}
void game()
{int choose = 0;int count = 0;int sum = 0;// 定义两个二维数组char mine[ROWS][COLS] = { 0 };char show[ROWS][COLS] = { 0 };// 初始化棋盘InitBoard(mine, ROWS, COLS, '0');InitBoard(show, ROWS, COLS, '*');// 布置雷SetBoard(mine, ROW, COL);// 打印棋盘//DisplayBoard(mine, ROW, COL);DisplayBoard(show, ROW, COL);// 玩家开始排雷do{printf("****************\n");printf("*** 1. 标记 ***\n");printf("*** 2. 排雷 ***\n");printf("*** 0. 退出 ***\n");printf("****************\n");printf("请选择:>");scanf("%d", &choose);if (1 == choose){count = SignBoard(show, mine, ROW, COL);if (count != 0){printf("恭喜你,排雷成功!!\n");break;}}else if (2 == choose){//printf("排雷功能\n");sum = FineBoard(show, mine, ROW, COL);if (-1 == sum){printf("恭喜你,排雷成功!!\n");DisplayBoard(mine, ROW, COL);break;}else if (404 == sum){printf("很遗憾,你被炸死了!\n");DisplayBoard(mine, ROW, COL);break;}}else if (0 == choose){printf("退出游戏\n");break;}else{printf("输入错误,请重新输入\n");}} while (choose);}
int main()
{int input = 0; // 定义输入菜单选项的变量srand((unsigned int)time(NULL));do{// 游戏菜单menu();printf("请选择:>");scanf("%d", &input);// 不同选择对应不同结果switch (input){case 1:printf("扫雷游戏开始!!!\n");game();break;case 0:printf("退出游戏!!!\n");break;default:printf("选择错误,请重新输入\n");break; // 因为要重新输入所以从菜单开始循环}} while (input); // 输入为0退出游戏,同时停止循环return 0;
}
2. game.h头文件
#pragma once
#define _CRT_SECURE_NO_WARNINGS#include <stdio.h>
#include <stdlib.h>
#include <time.h>#define ROW 9
#define COL 9#define ROWS ROW + 2
#define COLS COL + 2#define EASY_COUNT 10// 初始化函数声明
void InitBoard(char board[ROWS][COLS], int rows, int cols, char sign);// 打印函数声明
void DisplayBoard(char board[ROWS][COLS], int row, int col);// 布置雷函数声明
void SetBoard(char board[ROWS][COLS], int row, int col);// 标记功能函数声明
int SignBoard(char show[ROWS][COLS],char mine[ROWS][COLS], int row, int col);// 排雷函数声明
int FineBoard(char show[ROWS][COLS], char mine[ROWS][COLS], int row, int col);// 拓展函数声明
void ExtendBoard(char show[ROWS][COLS], char mine[ROWS][COLS], int x, int y);
3. game.c源文件
#pragma once#include "game.h"// 初始化棋盘函数的定义
void InitBoard(char board[ROWS][COLS], int rows, int cols, char sign)
{int i = 0;for (i = 0; i < rows; i++){int j = 0;for (j = 0; j < cols; j++){board[i][j] = sign;}}
}// 打印棋盘函数定义
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{// 打印游戏开头分割线printf("-----扫雷游戏------\n");int i = 0;// 打印每一列数字for (i = 0; i <= row; i++){printf("%d ", i); // 打印每一列数字}printf("\n");// 打印列数字完换行for (i = 1; i <= row; i++){// 打印每一列数字之前先打印出行号printf("%d ", i);int j = 0;for (j = 1; j <= col; j++){printf("%c ", board[i][j]);}printf("\n");}// 打印游戏结尾分割线printf("-----扫雷游戏------\n");
}// 布置雷函数定义
void SetBoard(char board[ROWS][COLS], int row, int col)
{int count = EASY_COUNT;int x = 0;int y = 0;while (count){x = rand() % row + 1;y = rand() % col + 1;if (board[x][y] == '0'){board[x][y] = '1';count--;}}
}// 标记功能函数定义
int SignBoard(char show[ROWS][COLS], char mine[ROWS][COLS], int row, int col)
{int x = 0;int y = 0;int choose = 0;static int sum = 0; // 定义标记的总数static int count = 0; // 定义标记的雷的总数do{printf("******************\n");printf("*** 1.标记位置 ***\n");printf("*** 2.取消标记 ***\n");printf("*** 0.不标记了 ***\n");printf("******************\n");printf("请选择:>");scanf("%d", &choose);if (1 == choose){DisplayBoard(show, ROW, COL);printf("请输入标记坐标(空格隔开):>");scanf("%d %d", &x, &y);if (x >= 1 && x <= row && y >= 1 && y <= col) // 判断坐标合法性{if (show[x][y] == '*') // 判断坐标是否排查过{show[x][y] = '$';sum++; // 没标记一个加1if (mine[x][y] == '1'){count++; // 标记的位置如果是雷 加1}}else{printf("坐标已经被排查过了,请勿重复排查\n");}}else{printf("超出棋盘范围,请重新输入\n");}DisplayBoard(show, ROW, COL);}else if (2 == choose){printf("请输入标记坐标(空格隔开):>");scanf("%d %d", &x, &y);if (x >= 1 && x <= row && y >= 1 && y <= col) // 判断坐标合法性{if (show[x][y] == '$') // 判断坐标是否标记过{show[x][y] = '*';sum--; // 没标记一个加1if (mine[x][y] == '1'){count--; // 标记的位置如果是雷 加1}}else{printf("坐标未被标记,请重新选择\n");}}else{printf("超出棋盘范围,请重新输入\n");}DisplayBoard(show, ROW, COL);}else if (0 == choose){// 不标记直接跳转break;}else{printf("输入错误,请重新输入\n");}if (sum == count && count == EASY_COUNT){sum = 0;count = 0;return EASY_COUNT;}else{return 0;}} while (choose);
}// 计算周围雷的个数函数
int BoomCount(char board[ROWS][COLS], int x, int y)
{int i = 0;int sum = 0;for (i = -1; i <= 1; i++){int j = 0;for (j = -1; j <= 1; j++){if (i == j && 0 == j){continue;}sum = sum + board[x+i][y+j] - '0';}}return sum;
}// 排雷函数声明
int FineBoard(char show[ROWS][COLS], char mine[ROWS][COLS], int row, int col)
{int goway = 0;int x = 0;int y = 0;static int number = 0;do{printf("**************\n");printf("*** 1.排雷 ***\n");printf("*** 0.取消 ***\n");printf("**************\n");printf("请选择:>");scanf("%d", &goway);if (1 == goway){DisplayBoard(show, ROW, COL);while (1){printf("请输入排雷坐标(空格间隔):");scanf("%d %d", &x, &y);if (x >= 1 && x <= row && y >= 1 && y <= col) // 判断坐标合法性{if (show[x][y] == '*') // 判断是否被排查{if (mine[x][y] == '1'){return 404;}else{number++;// 调用计算周围雷个数的函数int bct = BoomCount(mine, x, y);if (bct == 0){// 如果满足不是雷,并且周围没有雷的种种条件,则先调用拓展函数ExtendBoard(show, mine, x, y);DisplayBoard(show, ROW, COL);break;}else{show[x][y] = bct + '0';DisplayBoard(show, ROW, COL);break;}}}else{printf("此位置已经排查完,请勿重复排查\n");break;}}else{printf("超出棋盘范围,请重新输入\n");}}if (number == row * col - EASY_COUNT){number = 0;return -1;}}else if (0 == goway){printf("取消排雷\n");}else{printf("输入错误,请重新输入\n");}} while (goway);}// 拓展函数定义
void ExtendBoard(char show[ROWS][COLS], char mine[ROWS][COLS], int x, int y)
{int count = BoomCount(mine, x, y);if (count == 0){show[x][y] = ' ';int i = 0;for (i = -1; i <= 1; i++){int j = 0;for (j = -1; j <= 1; j++){if (i == j && 0 == j){continue;}if (show[x + i][y + j] != '*'){continue;}ExtendBoard(show, mine, x + i, y + j);}}}else{show[x][y] = count + '0';}}
总结
C语言实现扫雷游戏的排雷菜单,以及功能的实现,拓展棋盘功能,以及源码等。