C语言扫雷游戏完整实现(下)

embedded/2024/12/23 5:59:44/

文章目录

  • 前言
  • 一、排雷函数菜单
  • 二、排雷函数菜单的实现
  • 三、拓展棋盘功能
  • 四、源码
    • 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个即只有两个不是雷进行测试
  • 效果如下图:
    在这里插入图片描述

三、拓展棋盘功能

  • 此功能再排雷是判定选择的位置已经不是雷情况下执行。
  • 采用函数递归
    1. 如果这个位置周围没有雷,则这个位置可以为空格。
    1. 这个位置周围八个坐标没有排查过,排查过的位置直接跳过。
    1. 函数内部调用再次调用拓展函数,重新判断
    1. 如果满足继续排查
    1. 如果周围有雷,则停止排查,并将此位置显示周围雷的个数。

在这里插入图片描述

//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语言实现扫雷游戏的排雷菜单,以及功能的实现,拓展棋盘功能,以及源码等。


http://www.ppmy.cn/embedded/23450.html

相关文章

uniapp app权限说明弹框2024.4.23更新

华为上架被拒绝 用uni-app开发的app&#xff0c;上架华为被拒&#xff0c;问题如下&#xff1a; 您的应用在运行时&#xff0c;未见向用户告知权限申请的目的&#xff0c;向用户索取&#xff08;电话、相机、存储&#xff09;等权限&#xff0c;不符合华为应用市场审核标准。…

设计模式之中介者模式

详细介绍 中介者模式&#xff08;Mediator Pattern&#xff09;是一种行为设计模式&#xff0c;它通过定义一个中介类来封装多个对象之间的交互&#xff0c;使各对象不需要显示地相互引用&#xff0c;从而降低耦合度&#xff0c;提高系统的可维护性和灵活性。中介者模式将原本一…

后端面试---分布式微服务

分布式&微服务 分布式1、什么时候用到分布式开发三级目录 微服务 分布式 1、什么时候用到分布式开发 三级目录 微服务 1、谈谈你对微服务的理解&#xff0c;什么时候用微服务 2、若A服务请求B服务B1接口&#xff0c;B1接口又请求A服务的A2接口&#xff0c;会不会有问题…

微信小程序:基于MySQL+Nodejs的汽车品牌管理系统

各位好&#xff0c;接上期&#xff0c;今天分享一个通过本地MySQLNodejs服务器实现CRUD功能的微信小程序&#xff0c;一起来看看吧~ 干货&#xff01;微信小程序通过NodeJs连接MySQL数据库https://jslhyh32.blog.csdn.net/article/details/137890154?spm1001.2014.3001.5502 …

前端开发攻略---用原生JS在网页中也能实现文本转语音

1、原理 语音合成 (也被称作是文本转为语音&#xff0c;英语简写是 tts) 包括接收 app 中需要语音合成的文本&#xff0c;再在设备麦克风播放出来这两个过程。 Web API中对此有一个主要控制接口 SpeechSynthesis&#xff0c;外加一些处理如何表示要被合成的文本 (也被称为 utte…

react挂载后函数

在React中&#xff0c;当组件被挂载到DOM后&#xff0c;你可以使用生命周期方法 componentDidMount() 来执行某些操作。这是React组件生命周期中的一个重要阶段&#xff0c;此时组件已经被渲染并插入到DOM中。 componentDidMount() 是一个在组件输出到DOM后立即自动调用的方法…

Redux(类似vue中的vuex和pina)

什么是Redux Redux 是React最常用的集中状态管理工具&#xff0c;类似于Vue中的Pinia&#xff08;Vuex&#xff09;&#xff0c;可以独立于框架运行 作用&#xff1a;通过集中管理的方式管理应用的状态 为什么要使用Redux&#xff1f; 独立于组件&#xff0c;无视组件之间的层…

python初级笔记5 面向对象

创造类的方式 class 类名&#xff08;object&#xff09;&#xff1a; 属性 方法 类名用大驼峰命名法 函数在类中叫做方法 类名后面的括号用来继承 class Student(object):name Noneage Noneid Noneprint(Student) 结果&#xff1a; E:\Python\python.exe E:\学习笔记\Py…