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

相关文章

大模型研发全揭秘:客服工单数据标注的完整攻略

在人工智能(AI)领域,数据标注是模型训练过程中至关重要的一步。无论你是新手还是有经验的从业者,掌握数据标注的技术细节和常见问题的解决方案都能为你的AI项目增添不少价值。在电信运营商的客服系统中,工单数据是客户问题和解决方案的重要记录。通过对这些工单数据进行有效标注,不仅能够帮助提升客服自动化系统的智能化水平,还能优化客户服务流程,提高客户满意度。本文将详细介绍如何在电信运营商客服工单的背景下进行

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi

让树莓派智能语音助手实现定时提醒功能

最初的时候是想直接在rasa 的chatbot上实现,因为rasa本身是带有remindschedule模块的。不过经过一番折腾后,忽然发现,chatbot上实现的定时,语音助手不一定会有响应。因为,我目前语音助手的代码设置了长时间无应答会结束对话,这样一来,chatbot定时提醒的触发就不会被语音助手获悉。那怎么让语音助手也具有定时提醒功能呢? 我最后选择的方法是用threading.Time

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo

C#实战|大乐透选号器[6]:实现实时显示已选择的红蓝球数量

哈喽,你好啊,我是雷工。 关于大乐透选号器在前面已经记录了5篇笔记,这是第6篇; 接下来实现实时显示当前选中红球数量,蓝球数量; 以下为练习笔记。 01 效果演示 当选择和取消选择红球或蓝球时,在对应的位置显示实时已选择的红球、蓝球的数量; 02 标签名称 分别设置Label标签名称为:lblRedCount、lblBlueCount

科研绘图系列:R语言扩展物种堆积图(Extended Stacked Barplot)

介绍 R语言的扩展物种堆积图是一种数据可视化工具,它不仅展示了物种的堆积结果,还整合了不同样本分组之间的差异性分析结果。这种图形表示方法能够直观地比较不同物种在各个分组中的显著性差异,为研究者提供了一种有效的数据解读方式。 加载R包 knitr::opts_chunk$set(warning = F, message = F)library(tidyverse)library(phyl

透彻!驯服大型语言模型(LLMs)的五种方法,及具体方法选择思路

引言 随着时间的发展,大型语言模型不再停留在演示阶段而是逐步面向生产系统的应用,随着人们期望的不断增加,目标也发生了巨大的变化。在短短的几个月的时间里,人们对大模型的认识已经从对其zero-shot能力感到惊讶,转变为考虑改进模型质量、提高模型可用性。 「大语言模型(LLMs)其实就是利用高容量的模型架构(例如Transformer)对海量的、多种多样的数据分布进行建模得到,它包含了大量的先验

Kubernetes PodSecurityPolicy:PSP能实现的5种主要安全策略

Kubernetes PodSecurityPolicy:PSP能实现的5种主要安全策略 1. 特权模式限制2. 宿主机资源隔离3. 用户和组管理4. 权限提升控制5. SELinux配置 💖The Begin💖点点关注,收藏不迷路💖 Kubernetes的PodSecurityPolicy(PSP)是一个关键的安全特性,它在Pod创建之前实施安全策略,确保P