C语言实现扫雷游戏(含注释详解)
作者:3 ERROR(s) 发布时间:2023-11-02 15:25:07
本文实例为大家分享了C语言实现扫雷游戏的具体代码,供大家参考,具体内容如下
前言
一、游戏规则介绍
扫雷是一个十分经典的游戏,一张棋盘中有很多个不确定是雷还是安全区域的格子,当点击之后若没有雷则会在该区域显示周围八个格子雷的数目,若有雷则游戏结束。今天我就跟大家分享一下如何用c语言实现初阶版扫雷。
二、基本思路流程介绍
1.创建一个用户交互菜单
2.创建一个Show_Mines棋盘用来埋雷并初始化
3.创建一个Show_Table 棋盘用来和用户交互并初始化
4.玩家选择想要扫描的坐标
5.判定游戏是否结束
6.若没有踩雷则在刚扫描的区域上显示周围八个区域的地雷数目并继续游戏
7.继续扫雷
8.判定游戏是否结束
…
9.若全部扫描完非雷区域则游戏结束
效果展示
三、代码实现
1.用户交互菜单(Menu函数)
Menu(){
printf("########################\n");
printf("# 1. Play 0.Exit #\n");
printf("########################\n");
}
2. Game函数
void Game()
{
srand((unsigned long)time(NULL)); //生成随机数种子
char show_board[ROW][COL];
char mines_board[ROW][COL];
memset(show_board, WHAT, sizeof(show_board));//生成并且初始化用户显示棋盘
memset(mines_board, '0', sizeof(mines_board));//生成并且初始化扫雷棋盘
SetMines(mines_board, ROW, COL);//放雷
int count = (ROW - 2)*(COL - 2) - NUM; //若扫完这些次 不触雷则胜利
while (count){
system("cls");
ShowBoard(show_board, ROW, COL);
printf("请选择你要扫描的区域坐标 ");
int x = 0;
int y = 0;
scanf("%d %d", &x, &y);
if (x < 1 || x > ROW-2 || y < 1 || y > COL-2){ //非法性输入判断
printf("输入错误!\n");
continue;
}
if (show_board[x][y] != WHAT){
printf("此处已经被扫过了,请从新输出\n");
continue;
}
if (mines_board[x][y] == '1'){
system("cls");
ShowBoard(mines_board, ROW, COL);
printf("踩雷了!游戏结束!\n");
break;
}
show_board[x][y] = CountMines(mines_board, x, y);
count--;
}
}
1.memset函数直接定义show_board函数并且初始化二维数组为全WHAT宏定义的*。
2.先向用户展示用户展示棋盘,用户输入一个坐标进行非法性判断。
3.把用户输入的坐标拿给放置雷的棋盘中,若该区域有雷则游戏结束,反之则继续
4.游戏胜利条件为扫描完所有非雷区域
3.放雷函数(SetMines函数)
void SetMines(char board[][COL], int row, int col){ //放雷函数
int count = NUM;
while (count){
int x = rand() % (row - 2) + 1;
int y = rand() % (col - 2) + 1;
if (board[x][y] == '0'){
board[x][y] = '1';
count--;
}
}
}
使用随机数种子生成1到 棋盘大小长宽-2的随机数,这些随机数组成的坐标放雷,循环次数就是雷的数目。因为随机数可能生成一样的,所以要进行一次非法性判断,当棋盘这个位置没有雷的情况下才能往里面放雷。
4.扫雷展示面板(ShowBoard函数和ShowLine函数)
void ShowBoard(char board[][COL], int row, int col){//扫雷展示面板
printf(" ");
for (int i = 1; i <= (col - 2); i++){ //打印表头数字
printf("%d ", i);
}
printf("\n");
ShowLine(col);//显示行线
for (int i = 1; i <= (row - 2); i++){
printf("%-3d|", i);
for (int j = 1; j <= (col - 2); j++){
printf(" %c |", board[i][j]);
}
printf("\n");
ShowLine(col);
}
}
void ShowLine(int col){ //显示横着的虚线,作为行间隔
for (int i = 0; i <= (col - 2); i++){
printf("----");
}
printf("\n");
}
5.统计周围雷的个数(CountMines函数)
CountMines(char board[][COL], int x, int y){ //统计周围雷的个数
return board[x - 1][y - 1] + board[x - 1][y] + board[x - 1][y + 1] + \
board[x][y + 1] + board[x + 1][y + 1] + board[x + 1][y] + \
board[x + 1][y - 1] + board[x][y - 1] - 7 * '0';//本来减八个零,但是整形转字符加一个‘0'
}
由于数组中存放的是字符'0',周围是8个数字,所以-8*'0'才能返回雷数的int值,为了把数字也能打印出来,所以+‘0',否则打印的是数字作为的ASCLL码的值,最终的结果为-7*‘0'.
6.mine函数
int main()
{
int quit = 0;
int select = 0;
while (!quit){
Menu();
printf("请输入 ");
scanf("%d", &select);
switch (select){
case 1:
Game();
break;
case 0:
quit = 1;
break;
default:
printf("输入错误,请重试!\n");
break;
}
}
printf("byebye!\n");
system("pause");
return 0;
}
四、总代码
#ifndef __Test_H__
#define __Test_H__
#include<stdio.h>
#include<Windows.h>
#include <stdlib.h>
#include <time.h>
#define WHAT '*'
#define NUM 20
#define COL 10
#define ROW 10
void Game();
#pragma warning(disable:4996)
#endif //以上都是头文件
int main()
{
int quit = 0;
int select = 0;
while (!quit){
Menu();
printf("请输入 ");
scanf("%d", &select);
switch (select){
case 1:
Game();
break;
case 0:
quit = 1;
break;
default:
printf("输入错误,请重试!\n");
break;
}
}
printf("byebye!\n");
system("pause");
return 0;
}
void Game()
{
srand((unsigned long)time(NULL)); //生成随机数种子
char show_board[ROW][COL];
char mines_board[ROW][COL];
memset(show_board, WHAT, sizeof(show_board));
memset(mines_board, '0', sizeof(mines_board));
SetMines(mines_board, ROW, COL);
int count = (ROW - 2)*(COL - 2) - NUM; //若扫完这些次 不触雷则胜利
while (count){
system("cls");
ShowBoard(show_board, ROW, COL);
printf("请选择你要扫描的区域坐标 ");
int x = 0;
int y = 0;
scanf("%d %d", &x, &y);
if (x < 1 || x > ROW-2 || y < 1 || y > COL-2){ //非法性输入判断
printf("输入错误!\n");
continue;
}
if (show_board[x][y] != WHAT){
printf("此处已经被扫过了,请从新输出\n");
continue;
}
if (mines_board[x][y] == '1'){
system("cls");
ShowBoard(mines_board, ROW, COL);
printf("踩雷了!游戏结束!\n");
break;
}
show_board[x][y] = CountMines(mines_board, x, y);
count--;
}
}
CountMines(char board[][COL], int x, int y){ //统计周围雷的个数
return board[x - 1][y - 1] + board[x - 1][y] + board[x - 1][y + 1] + \
board[x][y + 1] + board[x + 1][y + 1] + board[x + 1][y] + \
board[x + 1][y - 1] + board[x][y - 1] - 7 * '0';//本来减八个零,但是整形转字符加一个‘0'
}
void ShowBoard(char board[][COL], int row, int col){//扫雷展示面板
printf(" ");
for (int i = 1; i <= (col - 2); i++){
printf("%d ", i);
}
printf("\n");
ShowLine(col);//显示行线
for (int i = 1; i <= (row - 2); i++){
printf("%-3d|", i);
for (int j = 1; j <= (col - 2); j++){
printf(" %c |", board[i][j]);
}
printf("\n");
ShowLine(col);
}
}
oid SetMines(char board[][COL], int row, int col){ //放雷函数
int count = NUM;
while (count){
int x = rand() % (row - 2) + 1;
int y = rand() % (col - 2) + 1;
if (board[x][y] == '0'){
board[x][y] = '1';
count--;
}
}
}
void ShowLine(int col){
for (int i = 0; i <= (col - 2); i++){
printf("----");
}
printf("\n");
}
Menu(){ //用户交互函数
printf("########################\n");
printf("# 1. Play 0.Exit #\n");
printf("########################\n");
}
来源:https://blog.csdn.net/weixin_50302770/article/details/117574675


猜你喜欢
- 一.SQLite的介绍1.SQLite简介SQLite是一款轻型的数据库,是遵守ACID的关联式数据库管理系统,它的设计目标是嵌入 
- 有时候需要根据条件查询得出的数据较多,需要分页显示到页面上。这时点击下一页就不方便每次带查询条件在数据库中分页。可以在list中进行分页。p
- 1,编写一个程序,读取文件test.txt的内容并在控制台输出。如果源文件不存在,则显示相应的错误信息。 package src;impor
- java 二叉查找树实例代码1.左边<中间<右边2.前序遍历 左中右3.中序遍历 中左右4.后序遍历 左右中public cla
- 部署到webapps目录启动本文使用的Spring版本为Spring6,SpringBoot版本为3,JDK为17,可能会和之前有细微不同,
- 发现了google的gson,因为之前对于protocolbuf有一些了解,带着一些好奇心,我开始使用了gson。GitHub主页:http
- 这里简单介绍了一些常用的属性,以及一些术语的解释和举例说明,不太全面,希望读者多多补充。1.重载:函数名相同,参数的个数或参数类型不同; p
- 本文实例为大家分享了android实现蓝牙app的具体代码,供大家参考,具体内容如下private BluetoothGatt blueto
- 一、输入映射parameterType指定输入参数的Java类型,可以使用别名或者类的全限定名。它可以接收简单类型、POJO、H
- 一、项目简述本系统主要实现的功能有:社区疫情流动人员管理系统,住户管理,出入管理,访客管理,体温录入,高风险警示等等。二、项目运行环境配置:
- 本文实例讲述了DevExpress中ChartControl实现柱状图演示的方法。分享给大家供大家参考。具体实现方法如下:关键代码如下:us
- 最近在开发的过程中,一个列表的查询,涉及到了多表的关联查询,由于持久层使用的是mongodb,对这个非关系型数据使用的不是很多,所以在实现此
- Spring多配置文件有什么好处? 按照目的、功能去拆分配置文件,可以提高配置文件的可读性与维护性,如将配置事务管理、数据源等少改动的配置与
- 程序思路:动态加载V4和V2的mscorlib.dll程序集,通过反射进行比较。之所以加载mscorlib.dll 是因为framework
- 消息发送过程消息的发送可能会经过 * 、序列化、分区器等过程。消息发送的主要涉及两个线程,分别为main线程和sender线程。如图所示,主
- java模拟实现图书检索系统 (基础版),供大家参考,具体内容如下练习实现3个简单的功能,没有优化,可以根据需求,自行添加想要实现的功能。B
- Android 1.5之后将调节亮度的api隐藏了,不过android的源码中依然有方法可以实现,如下:IPowerManager powe
- springboot环境切换失效概述最近在使用-Dspring.profiles.active=te 来切换spring-boot的环境时,
- 前言上篇博客我们介绍了如何创建一个spring项目,并且如何的存、取对象,介绍了相关方法,那么本篇博客将接着上篇博客的内容介绍如何更加简单的
- 一、概述1、XMLReader为抽象类,其派生类有:XmlDictionaryReaderXmlNodeReaderXmlTextReade