C语言经典小游戏之扫雷(超详解释+源码)

“少年气,是历尽千帆举重若轻的沉淀,也是乐观淡然笑对生活的豁达!” 今天我们学习一下扫雷游戏怎么用C语言来实现!

扫雷小游戏

  • 1.游戏介绍
  • 2.游戏准备
  • 3.游戏实现
    • 3.1生成菜单
    • 3.2游戏的具体实现
      • 3.2.1初始化棋盘
      • 3.2打印棋盘
      • 3.3布置雷
      • 3.4排查雷
    • 4.扫雷游戏的详细代码

1.游戏介绍

一个扫雷盘面由许多方格(cell)组成,方格中随机分布着一定数量的雷(mine),一个格子中至多只有1雷。胜利条件是打开所有安全格(非雷格,safe cell),失败条件是打开了一个雷格(踩雷)。下面图片中是一个9*9的示例:
在这里插入图片描述

2.游戏准备

和前面的三子棋一样,这里,我们也需要三个源文件来共同实现这个程序。
在这里插入图片描述

(1)头文件game.h,头文件里是用来存放函数的声明,#define常量的定义,库函数的引用的。
(2)源文件test.c,这个文件里面放的是游戏的测试逻辑。
(3)源文件game.c,这个文件里面放的是游戏的实现逻辑(函数实现)。

3.游戏实现

3.1生成菜单

这里呢,我们和三子棋一样,还是通过switch语句给用户选择,当用户输入不同的数字,我们的程序就会给出不同的功能。

#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
#include <stdio.h>
void menu()
{printf("******************************\n");printf("*********   1.play   *********\n");printf("*********   0.exit   *********\n");printf("******************************\n");
}
void game()
{}
int main()
{int input = 0;do{menu();printf("请选择:>");scanf("%d", &input);switch(input){case 1:game();break;case 0:printf("退出游戏!\n");break;default:printf("选择错误,重新选择!\n");break;}} while (input);return 0;
}

大致的框架就出来了,现在我们就需要看扫雷游戏的具体实现了。
在这里插入图片描述

3.2游戏的具体实现

这里我们简化游戏,设置一个9*9的棋盘,安置10个雷
排查过程如下:
1.如果这个位置是雷,那么游戏结束。
2.如果把不是雷的位置都找出来了,那么游戏结束。
3.如果这个位置不是雷,就计算这个位置的周围的8个格子有几个雷,并显示出雷的个数。

3.2.1初始化棋盘

我们这里的棋盘是9*9的,可以和三子棋一样,先将每个棋盘都初始化为0,如下图所示,然后有雷的地方填上1,如下图所示:
在这里插入图片描述
但是,我们从游戏规则中知道,当我们点到一个不是雷的格子的时候,要返回它周围八个格子中雷的个数。如下图中,如果我们点到了绿色1的那个格子,那么该位置将返回1这个值,此时,这里的1就会和表示雷的1就混起来了。
在这里插入图片描述
同时,当我们点到一个处于四边的格子的时候,还会出现越界的问题:
在这里插入图片描述
这个时候,我们就可以考虑在排查雷的时候,将棋盘扩展成11*11的棋盘。
在这里插入图片描述

同时,我们可以将排查雷的9*9的格子里都初始化为*,避免出现两个1意义不同混淆的情况。这样的话,我们就得到两个11*11的棋盘。
在这里插入图片描述

//game.h
#pragma once
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
//初始化棋盘函数的声明
void Init_Board(char board[ROWS][COLS], int rows, int cols, char set);//game.h*
//初始化棋盘的定义
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
void Init_Board(char board[ROWS][COLS], int rows, int cols, char set)
{int i = 0;for (i = 0; i < rows; i++){int j = 0;for (j = 0; j < cols; j++){board[i][j] = set;}}
}//test.c
void game()
{char assign[ROWS][COLS] = { 0 };char show[ROWS][COLS] = { 0 };Init_Board(assign,ROWS,COLS,'0');Init_Board(show, ROWS, COLS, '*');
}

初始化完成之后,我们想要验证一下对不对呢?这个时候,我们就需要将棋盘打印出来。

3.2打印棋盘

虽然我们这里初始化的是11*11的棋盘,但是用户需要的是中间区域的9*9,因此,我们只需要打印中间的9*9就可以了。

//game.h
//打印棋盘函数的声明
void Display_Board(char board[ROWS][COLS], int row, int col);//game.c
//打印棋盘函数的定义
//我们只需要打印出中间的9*9的格子
void Display_Board(char board[ROWS][COLS], int row, int col)
{int i = 0;for (i = 1; i <= row; i++){int j = 0;for (j = 1; j <= col; j++){printf("%c ", board[i][j]);}printf("\n");}
}//test.c
void game()
{Display_Board(assign, ROW, COL);
}

在这里插入图片描述
这里我们需要把行号和列号也打印出来,能够看的更清晰。代码进行这样的修改就好啦!
在这里插入图片描述
再优化一下,就如下图所示:
在这里插入图片描述

3.3布置雷

我们希望的是在这个9*9的棋盘里随机生成10个雷,这里我们就想到了能够产生随机数的函数rand()和srand(),使用这两个函数,需要添加头文件#include <time.h>和#include <stdlib.h>,同时,在主函数内还需要添加语句srand((unsigned int)time(NULL));来产生随机数的种子。

//game.h
#define Easy_Thunder 10
#include <stdlib.h>
#include <time.h>
//布置雷函数的声明
void Set_thunder(char board[ROWS][COLS], int row, int col);//game.c
//布置雷函数的定义
void Set_thunder(char board[ROWS][COLS], int row, int col)
{int count = Easy_Thunder;while (count){int x = rand() % row + 1;//生成横坐标int y = rand() % col + 1;//生成纵坐标if (board[x][y] == '0')//防止在同一个地方重复布雷{board[x][y] = '1';count--;}}
}//test.c
void game()
{char assign[ROWS][COLS] = { 0 };char show[ROWS][COLS] = { 0 };Init_Board(assign,ROWS,COLS,'0');Init_Board(show, ROWS, COLS, '*');Display_Board(assign, ROW, COL);Set_thunder(assign, ROW, COL);
}
int main()
{srand((unsigned int)time(NULL));return 0;
}

那么,代码写好了,我们来验证一下,这样是不是能够布置出十个雷呢?
在这里插入图片描述

3.4排查雷

我们开始随机点一个格子,当这个格子不是雷的时候,可以计算它周围八个格子字符的ASCII码值,减去8个'0'的ASCII码值,就可以知道,这个格子周围有多少个雷了,然后我们加上'0'的ASCII码值就能在该处的格子上返回相应的字符。当我们把所有不是雷的格子找出来的时候,给用户提示排雷成功。当我们踩到雷的时候,也给出相应的提示给用户,游戏结束。这里和三子棋一样,我们可以添加清屏的操作system("cls");,让我们的游戏面板不是那么的冗长。

在这里插入图片描述

//game.h
//排查雷函数的声明
void Find_thunder(char assign[ROWS][COLS], char show[ROWS][COLS], int row, int col);//game.c
int Getassign(char assign[ROWS][COLS], int row, int col)//查找不是雷的格子周围有几个雷
{return (assign[row - 1][col - 1]//字符'0'的ASCII值为48,字符'1'的ASCII值为49+ assign[row - 1][col]+ assign[row - 1][col + 1]+ assign[row][col - 1]+ assign[row][col + 1]+ assign[row + 1][col - 1]+ assign[row + 1][col]+ assign[row + 1][col + 1] - 8 * '0');
}
//排查雷函数的定义
void Find_thunder(char assign[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{int x = 0;int y = 0;int win = 0;//计算没有踩到雷的次数while (win<col*row-Easy_Thunder){printf("请输入坐标:>");scanf("%d%d", &x, &y);if (x >= 1 && x <= row && y >= 1 && y <= col){if (assign[x][y] == '1'){printf("很遗憾,你被炸死了!\n");Display_Board(assign, ROW, COL);break;}else{//如果这个位置不是雷就统计周围八个格子雷的个数int c = Getassign(assign, x, y);show[x][y] = c + '0';Display_Board(show, ROW, COL);system("cls");Display_Board(show, ROW, COL);win++;}}else{printf("坐标非法,请重新输入!\n");}}if (win == row * col - Easy_Thunder){printf("恭喜你排雷成功!\n");Display_Board(assign, ROW, COL);}	
}//test.c
void game()
{Find_thunder(assign, show, ROW, COL);//排雷函数的引用
}

这里,我们随机输入,不用思考,试一下踩到雷的结果:
在这里插入图片描述
那么,如果我们仔细思考,看看当我们把所有不是雷的格子找出来的时候,能不能成功:
在这里插入图片描述

4.扫雷游戏的详细代码

//game.h
#pragma once
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
#define Easy_Thunder 10
#include <stdlib.h>
#include <time.h>
//初始化棋盘函数的声明
void Init_Board(char board[ROWS][COLS], int rows, int cols, char set);
//打印棋盘函数的声明
void Display_Board(char board[ROWS][COLS], int row, int col);
//布置雷函数的声明
void Set_thunder(char board[ROWS][COLS], int row, int col);
//排查雷函数的声明
void Find_thunder(char assign[ROWS][COLS], char show[ROWS][COLS], int row, int col);//game.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
//初始化棋盘的定义
void Init_Board(char board[ROWS][COLS], int rows, int cols, char set)
{int i = 0;for (i = 0; i < rows; i++){int j = 0;for (j = 0; j < cols; j++){board[i][j] = set;}}
}
//打印棋盘函数的定义
//我们只需要打印出中间的9*9的格子
void Display_Board(char board[ROWS][COLS], int row, int col)
{int i = 0;int j = 0;printf("--------扫雷--------\n");for (i = 0; i <= col; i++){printf("%d ", i);}printf("\n");for (i = 1; i <= row; i++){printf("%d ", i);for (j = 1; j <= col; j++){printf("%c ", board[i][j]);}printf("\n");}
}
//布置雷函数的定义
void Set_thunder(char board[ROWS][COLS], int row, int col)
{int count = Easy_Thunder;//布置10个雷while (count){int x = rand() % row + 1;//生成横坐标int y = rand() % col + 1;//生成纵坐标if (board[x][y] == '0')//防止在同一个地方重复布雷{board[x][y] = '1';count--;}}
}
int Getassign(char assign[ROWS][COLS], int row, int col)//查找不是雷的格子周围有几个雷
{return (assign[row - 1][col - 1]//字符'0'的ASCII值为48,字符'1'的ASCII值为49+ assign[row - 1][col]+ assign[row - 1][col + 1]+ assign[row][col - 1]+ assign[row][col + 1]+ assign[row + 1][col - 1]+ assign[row + 1][col]+ assign[row + 1][col + 1] - 8 * '0');
}
//排查雷函数的定义
void Find_thunder(char assign[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{int x = 0;int y = 0;int win = 0;//计算没有踩到雷的次数while (win<col*row-Easy_Thunder){printf("请输入坐标:>");scanf("%d%d", &x, &y);if (x >= 1 && x <= row && y >= 1 && y <= col){if (assign[x][y] == '1'){printf("很遗憾,你被炸死了!\n");Display_Board(assign, ROW, COL);break;}else{//如果这个位置不是雷就统计周围八个格子雷的个数int c = Getassign(assign, x, y);show[x][y] = c + '0';Display_Board(show, ROW, COL);system("cls");//清屏操作Display_Board(show, ROW, COL);win++;}}else{printf("坐标非法,请重新输入!\n");}}if (win == row * col - Easy_Thunder){printf("恭喜你排雷成功!\n");Display_Board(assign, ROW, COL);}	
}//test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
#include <stdio.h>
void menu()
{printf("******************************\n");printf("*********   1.play   *********\n");printf("*********   0.exit   *********\n");printf("******************************\n");
}
void game()
{char assign[ROWS][COLS] = { 0 };char show[ROWS][COLS] = { 0 };Init_Board(assign,ROWS,COLS,'0');Init_Board(show, ROWS, COLS, '*');Display_Board(assign, ROW, COL);Set_thunder(assign, ROW, COL);Find_thunder(assign, show, ROW, COL);
}
int main()
{srand((unsigned int)time(NULL));int input = 0;do{menu();printf("请选择:>");scanf("%d", &input);switch(input){case 1:game();break;case 0:printf("退出游戏!\n");break;default:printf("选择错误,重新选择!\n");break;}} while (input);return 0;
}

以上就是关于扫雷游戏的全部代码啦!当然这个程序还是存在可优化的空间(比如我们的游戏只能一个一个点,但是不能像网页版的那样能展示一片,这还有待思考),欢迎大家在评论区交流,优化代码。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/58345.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Ubuntu】安装docker,docker compose 以及部署一个docker应用

大家好&#xff01;在过去&#xff0c;已经分享了很多有关通过Docker部署应用的内容。今天&#xff0c;我将为大家详细介绍如何在Ubuntu系统上部署最新的Docker平台。 Docker是什么 Docker是一个开源的容器化平台&#xff0c;它允许您将应用程序及其所有依赖项打包到称为容器…

Clickhouse 存储引擎

一、常用存储引擎分类 1.1 ReplacingMergeTree 这个引擎是在 MergeTree 的基础上&#xff0c;添加了”处理重复数据”的功能&#xff0c;该引擎和MergeTree的不同之处在于它会删除具有相同主键的重复项。 特点: 1使用ORDERBY排序键作为判断重复的唯一键 2.数据的去重只会在合并…

ClickHouse(十一):Clickhouse MergeTree系列表引擎 - MergeTree(1)

进入正文前&#xff0c;感谢宝子们订阅专题、点赞、评论、收藏&#xff01;关注IT贫道&#xff0c;获取高质量博客内容&#xff01; &#x1f3e1;个人主页&#xff1a;含各种IT体系技术&#xff0c;IT贫道_Apache Doris,Kerberos安全认证,大数据OLAP体系技术栈-CSDN博客 &…

洛阳Geotrust旗下有RapidSSL https证书吗

Geotrust是知名的CA认证机构&#xff0c;旗下的https数字证书产品众多&#xff0c;Geotrust的数字证书具有高度的兼容性和可信度&#xff0c;得到了全球用户的广泛认可和信赖。Geotrust是一家全球领先的数字证书颁发机构&#xff0c;提供多种数字证书服务&#xff0c;包括SSL证…

漫画算法做题笔记

诸神缄默不语-个人CSDN博文目录 哦这是我三年前写的&#xff0c;我现在Java语法都快忘光了…… 反正之前的博文也发一下好了。这个因为我当年是用有道云笔记而不是直接用CSDN编辑器写的&#xff0c;所以后面有些内容写乱了&#xff0c;因为我现在猛的一看有点看不懂&#xff0…

Tailwind CSS:简洁高效的工具,提升前端开发体验

112. Tailwind CSS&#xff1a;简洁高效的工具&#xff0c;提升前端开发体验 1. 什么是Tailwind CSS&#xff1f; Tailwind CSS是由Adam Wathan、Jonathan Reinink、David Hemphill和Steve Schoger等人共同创建的一种现代CSS框架。与传统的CSS框架不同&#xff0c;Tailwind CS…

C语言学习笔记 vscode使用外部console-11

前言 在默认情况下&#xff0c;我们运行C语言程序都是在vscode终端的&#xff0c;在小程序运行时这个是没有问题的&#xff0c;但是当程序变得复杂它就不好用了&#xff0c;这时我们可以将这个终端设置为外部console&#xff0c;这样方便处理更多、更复杂的程序。 步骤 1.点击…

zookeeper --- 基础篇

一、zookeeper简介 1.1、什么是zookeeper zookeeper官网&#xff1a;https://zookeeper.apache.org/ 大数据生态系统里的很多组件的命名都是某种动物或者昆虫&#xff0c;他是用来管 Hadoop&#xff08;大象&#xff09;、Hive(蜜蜂)、Pig(小 猪)的管理员。顾名思义就是管理…

网络防御(7)

课堂实验 R1 [Huawei] int g0/0/0 [Huawei-GigabitEthernet0/0/0]ip add 100.1.12.2 24 protocolAug 1 2023 10:24:09-08:00 Huawei gOlIFNET/4/LINK STATE(1)[4]:The1ineIp on the interface GigabitEthernet0/0/0 has entered the Up state. [Huawei-GigabitEthernet0/0/…

python中文官网下载安装,python官方中文文档下载

大家好&#xff0c;小编来为大家解答以下问题&#xff0c;python官网下载步骤图解&#xff0c;python官方中文文档下载&#xff0c;现在让我们一起来看看吧&#xff01; python官网网址 python官方网站 python官网网址中文。像我们想要抓住一门好的编程语言&#xff0c;如何开始…

vue 路由页面跳转

从index.vue跳转到data.vue index.vue <el-table-column label"客户数" align"center" :show-overflow-tooltip"true"><template slot-scope"scope"><router-link :to"/system/enterprise-data/index/ scope.ro…

如何解决 Elasticsearch 查询缓慢的问题以获得更好的用户体验

作者&#xff1a;Philipp Kahr Elasticsearch Service 用户的重要注意事项&#xff1a;目前&#xff0c;本文中描述的 Kibana 设置更改仅限于 Cloud 控制台&#xff0c;如果没有我们支持团队的手动干预&#xff0c;则无法进行配置。 我们的工程团队正在努力消除对这些设置的限制…