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

2024-04-25 05:52

本文主要是介绍C语言扫雷游戏完整实现(下),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 前言
  • 一、排雷函数菜单
  • 二、排雷函数菜单的实现
  • 三、拓展棋盘功能
  • 四、源码
    • 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语言实现扫雷游戏的排雷菜单,以及功能的实现,拓展棋盘功能,以及源码等。

这篇关于C语言扫雷游戏完整实现(下)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/933847

相关文章

使用Python和OpenCV库实现实时颜色识别系统

《使用Python和OpenCV库实现实时颜色识别系统》:本文主要介绍使用Python和OpenCV库实现的实时颜色识别系统,这个系统能够通过摄像头捕捉视频流,并在视频中指定区域内识别主要颜色(红... 目录一、引言二、系统概述三、代码解析1. 导入库2. 颜色识别函数3. 主程序循环四、HSV色彩空间详解

PostgreSQL中MVCC 机制的实现

《PostgreSQL中MVCC机制的实现》本文主要介绍了PostgreSQL中MVCC机制的实现,通过多版本数据存储、快照隔离和事务ID管理实现高并发读写,具有一定的参考价值,感兴趣的可以了解一下... 目录一 MVCC 基本原理python1.1 MVCC 核心概念1.2 与传统锁机制对比二 Postg

SpringBoot整合Flowable实现工作流的详细流程

《SpringBoot整合Flowable实现工作流的详细流程》Flowable是一个使用Java编写的轻量级业务流程引擎,Flowable流程引擎可用于部署BPMN2.0流程定义,创建这些流程定义的... 目录1、流程引擎介绍2、创建项目3、画流程图4、开发接口4.1 Java 类梳理4.2 查看流程图4

C++中零拷贝的多种实现方式

《C++中零拷贝的多种实现方式》本文主要介绍了C++中零拷贝的实现示例,旨在在减少数据在内存中的不必要复制,从而提高程序性能、降低内存使用并减少CPU消耗,零拷贝技术通过多种方式实现,下面就来了解一下... 目录一、C++中零拷贝技术的核心概念二、std::string_view 简介三、std::stri

C++高效内存池实现减少动态分配开销的解决方案

《C++高效内存池实现减少动态分配开销的解决方案》C++动态内存分配存在系统调用开销、碎片化和锁竞争等性能问题,内存池通过预分配、分块管理和缓存复用解决这些问题,下面就来了解一下... 目录一、C++内存分配的性能挑战二、内存池技术的核心原理三、主流内存池实现:TCMalloc与Jemalloc1. TCM

OpenCV实现实时颜色检测的示例

《OpenCV实现实时颜色检测的示例》本文主要介绍了OpenCV实现实时颜色检测的示例,通过HSV色彩空间转换和色调范围判断实现红黄绿蓝颜色检测,包含视频捕捉、区域标记、颜色分析等功能,具有一定的参考... 目录一、引言二、系统概述三、代码解析1. 导入库2. 颜色识别函数3. 主程序循环四、HSV色彩空间

Python实例题之pygame开发打飞机游戏实例代码

《Python实例题之pygame开发打飞机游戏实例代码》对于python的学习者,能够写出一个飞机大战的程序代码,是不是感觉到非常的开心,:本文主要介绍Python实例题之pygame开发打飞机... 目录题目pygame-aircraft-game使用 Pygame 开发的打飞机游戏脚本代码解释初始化部

Python实现精准提取 PDF中的文本,表格与图片

《Python实现精准提取PDF中的文本,表格与图片》在实际的系统开发中,处理PDF文件不仅限于读取整页文本,还有提取文档中的表格数据,图片或特定区域的内容,下面我们来看看如何使用Python实... 目录安装 python 库提取 PDF 文本内容:获取整页文本与指定区域内容获取页面上的所有文本内容获取

基于Python实现一个Windows Tree命令工具

《基于Python实现一个WindowsTree命令工具》今天想要在Windows平台的CMD命令终端窗口中使用像Linux下的tree命令,打印一下目录结构层级树,然而还真有tree命令,但是发现... 目录引言实现代码使用说明可用选项示例用法功能特点添加到环境变量方法一:创建批处理文件并添加到PATH1

Java使用HttpClient实现图片下载与本地保存功能

《Java使用HttpClient实现图片下载与本地保存功能》在当今数字化时代,网络资源的获取与处理已成为软件开发中的常见需求,其中,图片作为网络上最常见的资源之一,其下载与保存功能在许多应用场景中都... 目录引言一、Apache HttpClient简介二、技术栈与环境准备三、实现图片下载与保存功能1.