C语言300行代码实现扫雷(可展开+可标记+可更改困难级别+内附图形界面版本)

这篇具有很好参考价值的文章主要介绍了C语言300行代码实现扫雷(可展开+可标记+可更改困难级别+内附图形界面版本)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


前言

扫雷是一个经典的游戏,是一个益智类小游戏,在80、90年代曾风靡一时,当然现在也是十分受欢迎;
废话不多说;
让我们来了解一下如何用C语言去实现它吧!!!(❁´◡`❁)


运行环境:VS2019
图形化界面版本

一、主要思路?

先实现一个初级版本的:
C语言300行代码实现扫雷(可展开+可标记+可更改困难级别+内附图形界面版本),C语言,c语言,开发语言,算法
1、我们得有一个9*9的棋盘;
2、我们在棋盘上布置10颗雷;
3、搜索周围的雷,并且排查雷;
4、判断输赢;
这便是主要的大体思路;接下来我们来依次解决它!!!

二、生成棋盘

首先既然要生成99的棋盘,二维数组没跑了!!!
虽说看起来我们要生成一个9
9的棋盘,但是实际上我们如果真的生成了99的棋盘真的方便吗?
其实是并不是那么方便;
假设我们生成了一个9
9的棋盘,那我们每次去判断一个位置周围的雷的情况的时候很复杂,如果我们要排的位置比较靠近中间还好,不用担心数组越界的问题;但是我们要排的位置不靠近中心,相反它处于边缘位置,那我们每次去搜索它周围的雷的时候是不是每次都得先判断数组越没越界,再才进行雷的统计,实属相当之麻烦。那么有没有什么好办法既可以解决数组越界的问题又能方便雷的统计呢?
既然不能真的生成一个99的棋盘,那我们就生成一个伪的,我们生成一个1111的可好?
C语言300行代码实现扫雷(可展开+可标记+可更改困难级别+内附图形界面版本),C语言,c语言,开发语言,算法
我们把真正的棋盘套在里面;我们把外面留着,方便后面统计雷的个数;
这样对于边缘角落的雷的统计我们就能轻易的完成,又不用担心越界,多美事一件;
C语言300行代码实现扫雷(可展开+可标记+可更改困难级别+内附图形界面版本),C语言,c语言,开发语言,算法
那么好现在棋盘有了,我们得展示给玩家看啊!我们直接将雷盘展示给玩家?当然不是?我们带另外再开一个棋盘,专门给玩家看的;如果我们不在开一个棋盘的话,给玩家看到的肯定不能是雷盘对不对?那我们是不是就得给棋盘上一层”锁“来隐藏地雷对不对?可是如果我们真的像这样操作了的话,我们的雷就会被我们的“锁”给弄没了,雷都没了还扫个屁的雷啊!既然如此,我们应该开辟一个与雷盘一模一样大小的“锁盘”,来与雷盘映射起来,我们的锁盘上可以用来记录“锁”,排查位置周围雷的情况、和做标记;
C语言300行代码实现扫雷(可展开+可标记+可更改困难级别+内附图形界面版本),C语言,c语言,开发语言,算法
类似于这样;
那我们就定义两个棋盘出来呗:
char mine[ROWS][COLS] = { 0 };
char show[ROWS][COLS] = { 0 };
为了后续的方便我们将行和列都定义成宏,方便后期代码的维护和级别的选择;
既然棋盘都有了,那肯定要初始化嘛;
mine数组(不展示给玩家)没有地雷的时候,全部初始化为空格,有雷时将空格改为# 就行了;
show数组(展示给玩家)再给玩家看第一次的时候应该全部初始化为 * 来为雷盘上锁;后面根据排雷的情况我们依次进行替换;

初始化函数:

void init_board(char a[][COLS], int r, int c, char set)//要初始化成的set初始化的字符
{
	int i = 1;
	int j = 1;
	for (i = 1; i <= r; i++)
	{
		for (j = 1; j <= c; j++)
		{
			a[i][j] = set;
		}
	}
}

既然初始化都完成了:那我们还得打印出来看看:
于是我们在写给打印棋盘的函数:

C语言300行代码实现扫雷(可展开+可标记+可更改困难级别+内附图形界面版本),C语言,c语言,开发语言,算法

效果图:
C语言300行代码实现扫雷(可展开+可标记+可更改困难级别+内附图形界面版本),C语言,c语言,开发语言,算法

三、布置地雷

既然展示给玩家看到和存放地雷的棋盘都准备好了,那我们就应该往雷盘里面防雷了不是;
防雷肯定是随机放的,我们也不知道:那么肯定得用到rand()来产生随机数了,于是我们放雷的函数就可以写出:

C语言300行代码实现扫雷(可展开+可标记+可更改困难级别+内附图形界面版本),C语言,c语言,开发语言,算法

当然为了后续方便我们选择将地雷的数量也定义成宏的形式:
C语言300行代码实现扫雷(可展开+可标记+可更改困难级别+内附图形界面版本),C语言,c语言,开发语言,算法
我们来运行看看是不是真有10颗地雷:
C语言300行代码实现扫雷(可展开+可标记+可更改困难级别+内附图形界面版本),C语言,c语言,开发语言,算法
数了数没问题,程序还没有处bug,接着往下写;

四、排查地雷

既然地雷也布置好了,那我们就应该排查地雷了不是;
我们怎么排查呢?
我们对应的点应该输入合法坐标>
我们输入的坐标应该未被排查过>
如果上述都满足,我们再来判断是否需要标记,如果我们输入Y表示我们需要对该坐标进行标记,输入其它字符默认不需要标记>
如果我们上述都满足,我们也标记过来,而接下来这个位置刚好是地雷,那么游戏直接结束;如果这个位置不是地雷,则这个位置将会被替换成该位置周围地雷存在的数量(不包含该位置),当然如果再此等情况下,该位置的周围地雷的数量为0,则我们可以将此位置周围一片都展示出来,如果该位置的周围位置含满足上述情况,则继续展开,直至不能展开为止(因此像这种情况我们可以用递归来描写);(类似于下图)
C语言300行代码实现扫雷(可展开+可标记+可更改困难级别+内附图形界面版本),C语言,c语言,开发语言,算法
由此我们的代码可以这样写:

C语言300行代码实现扫雷(可展开+可标记+可更改困难级别+内附图形界面版本),C语言,c语言,开发语言,算法

剩余其他功能:
C语言300行代码实现扫雷(可展开+可标记+可更改困难级别+内附图形界面版本),C语言,c语言,开发语言,算法

五、判断输赢

为了判断输赢我定义了两个全局变量来表示:
C语言300行代码实现扫雷(可展开+可标记+可更改困难级别+内附图形界面版本),C语言,c语言,开发语言,算法
因此判断输赢的代码我们可以这样写:

C语言300行代码实现扫雷(可展开+可标记+可更改困难级别+内附图形界面版本),C语言,c语言,开发语言,算法

至此游戏至此已经全部完成:
我们最后敲个main函数让游戏活起来:

C语言300行代码实现扫雷(可展开+可标记+可更改困难级别+内附图形界面版本),C语言,c语言,开发语言,算法

六、最终代码

头文件和声明:

//为该模块单独建立一个game.h的文件,然后将该文件的所有内容全部放进去
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<string.h>
#include<stdbool.h>
#define MINE_COUNT 10//地雷数量
#define ROW 9//更改棋盘行大小
#define COL 9//更改棋盘列大小
#define ROWS ROW+2
#define COLS COL+2
#define MINE_FLAG '$'//地雷标记
#define INIT_FLAG '*'//初始化标价
enum CHOOSE
{
	EXIT,
	PLAY,
};
extern int flag;
extern int setp;
void init_board(char a[][COLS], int r, int c, char set);//初始化棋盘
void display_board(char a[][COLS], int r, int c);//打印棋盘
void set_mine(char mine[][COLS], int r, int c, int count);//布置雷
void find_mine(char show[][COLS], char mine[][COLS], int r, int c);//排查雷;
int get_mine(char show[][COLS], char mine[][COLS], int r, int c);//得到雷的数量
bool is_mine(char mine[][COLS], int x, int y);//判断下x,y是否为雷;
bool is_find(char show[][COLS], int x, int y);//判断是否被排查过
void surprise(char mine[][COLS], char show[][COLS], int r, int c, int x, int y);//展开一片

主要函数的实现:

//为该模块单独建立一个.c的源文件
#define  _CRT_SECURE_NO_WARNINGS 0
#include "game.h"
#pragma warning (disable:6031)
void init_board(char a[][COLS], int r, int c, char set)
{
	int i = 1;
	int j = 1;
	for (i = 1; i <= r; i++)
	{
		for (j = 1; j <= c; j++)
		{
			a[i][j] = set;
		}
	}
}
void display_board(char a[][COLS], int r, int c)
{
	int i = 1;
	int j = 1;
	printf(" ");
	for (j = 0; j <= c; j++)
	{
		if (j < 10)
			printf("%d ", j);
		else
		{
			printf("%c ", 'A' + j - 10);
		}
	}
	putchar('\n');
	putchar(' ');
	putchar(' ');
	for (j = 2; j <= c+1; j++)
	{
		printf("--");
	}
	putchar('\n');
	for (i = 1; i <= r; i++)
	{
		if (i < 10)
			printf("%d| ", i);
		else
		{
			printf("%c| ", 'A' + i - 10);
		}
		for (j = 1; j <= c; j++)
		{
			if (a[i][j] == MINE_FLAG)
				printf("\033[1;31m%c \033[0m",MINE_FLAG);
			else
			printf("%c ", a[i][j]);
		}
		printf("\n");
	}
}
void set_mine(char mine[][COLS], int r, int c, int count)
{
	int x = 0;
	int y = 0;
	while (count)
	{
		x = rand() % r + 1;
		y = rand() % c + 1;
		if (mine[x][y] == ' ')
		{
			mine[x][y] = MINE_FLAG;
			count--;
		}
	}
}
void find_mine(char show[][COLS], char mine[][COLS], int r, int c)//看看能不能在优化;
{
	int x = 0;
	int y = 0;
	char ch = 0;
	while (1)
	{
		printf("请输入你要排查的位置,并选择是否对该点进行标识(Y\\其它默认不标记)>");//对同一个点多次标记会取消标记;
		scanf("%d %d %c", &x, &y, &ch);
		if (x >= 1 && x <= r && y >= 1 && y <= c)//坐标合法
		{
			if (!is_find(show, x, y))//未被排查过
			{
				if (show[x][y] == 'M' && 'Y' == ch)
				{
					show[x][y] = INIT_FLAG;
					printf("取消标记成功\n");
					system("cls");
					display_board(show, r, c);
					break;
				}
				if ('Y' == ch)//判断一下是否需要标记;
				{
					show[x][y] = 'M';
					printf("标记成功\n");
					system("cls");
					display_board(show, r, c);
					break;
				}
				else
				{
					if (is_mine(mine, x, y))//该位置是地雷
					{
						printf("你被雷炸死了\n\a\a\a");
						show[x][y] = MINE_FLAG;//将炸死的回访展示出来
						flag = 0;
						system("cls");
						display_board(mine, r, c);
						break;
					}
					else//不是雷
					{
						surprise(mine, show, r, c, x, y);//进一步判断该位置周围雷的数量,若为0,进行进一步展开
						system("cls");
						display_board(show, r, c);
						break;
					}
				}
			}
			else
			{
				printf("坐标已排查过,请重新输入:>\n");
			}

		}
		else
			printf("坐标非法,请重新输入\n");
	}
}
int get_mine(char show[][COLS], char mine[][COLS], int x, int y)
{
	int count = 0;
	if (mine[x - 1][y - 1] == MINE_FLAG)
		count++;
	if (mine[x - 1][y] == MINE_FLAG)
		count++;
	if (mine[x - 1][y + 1] == MINE_FLAG)
		count++;
	if (mine[x][y - 1] == MINE_FLAG)
		count++;
	if (mine[x][y + 1] == MINE_FLAG)
		count++;
	if (mine[x + 1][y - 1] == MINE_FLAG)
		count++;
	if (mine[x + 1][y] == MINE_FLAG)
		count++;
	if (mine[x + 1][y + 1] == MINE_FLAG)
		count++;
	return count;
}
bool is_mine(char mine[][COLS], int x, int y)
{
	if (mine[x][y] == ' ')
		return false;
	return true;
}
bool is_find(char show[][COLS], int x, int y)
{
	if (show[x][y] == INIT_FLAG || show[x][y] == 'M')
		return false;
	return true;
}
void surprise(char mine[][COLS], char show[][COLS], int r, int c, int x, int y)
{
	if (!(x >= 1 && x <= r && y >= 1 && y <= c))//防止越界;
		return;
	if (is_mine(mine, x, y) || is_find(show, x, y))//能展开的条件:1、没被排查过;2、排查位置不是雷
		return;
	setp--;
	int count = get_mine(show, mine, x, y);//3、排查位置周围没有雷;
	show[x][y] = count + '0';
	if (count == 0)
	{
		surprise(mine, show, r, c, x - 1, y - 1);
		surprise(mine, show, r, c, x - 1, y);
		surprise(mine, show, r, c, x - 1, y + 1);
		surprise(mine, show, r, c, x, y - 1);
		surprise(mine, show, r, c, x, y + 1);
		surprise(mine, show, r, c, x + 1, y - 1);
		surprise(mine, show, r, c, x + 1, y);
		surprise(mine, show, r, c, x + 1, y + 1);
	}
}

main函数:


#define  _CRT_SECURE_NO_WARNINGS 0
#include"game.h"
#pragma warning (disable:6031)
//1、雷盘,展示盘
//2、初始化雷盘和展示盘//空格表示没雷#表示雷;*初始化展示盘
//3、打印一下棋盘;
//4、布置雷;
//5、排查雷;(注意触发惊喜)
int setp = ROW * COL - MINE_COUNT;//记录排雷最多步数;当setp等于0是表示安全位置已经排完,挑战成功
int flag = 1;//表示未被地雷炸死而结束游戏,地雷炸死而结束游戏的flag=0,挑战失败;
void game()
{
	char mine[ROWS][COLS] = { 0 };
	char show[ROWS][COLS] = { 0 };
	init_board(mine, ROW, COL, ' ');//初始化
	init_board(show, ROW, COL, INIT_FLAG);//初始化
	set_mine(mine, ROW, COL, MINE_COUNT);//布置雷
	//display_board(mine, ROW, COL);//开透视
	display_board(show, ROW, COL);//展示棋盘(给玩家看);
	setp = ROW * COL - MINE_COUNT;
	flag = 1;//重置一下,开始新的游戏
	while (setp && flag)
	{
		find_mine(show, mine, ROW, COL);
	}
	if (!setp)
	{
		system("cls");
		printf("挑战成功\a\a\a\a\n");
	}
	else if (!flag)
	{
		system("cls");
		printf("挑战失败\a\a\a\n");
	}
	printf("死亡回放:\n");
	display_board(show, ROW, COL);//展示棋盘(给玩家看);
	for (int j = 0; j <= COL; j++)
	{
		printf("--");
	}
	putchar('\n');
	printf("雷盘如下:\n");
	display_board(mine, ROW, COL);
}

void menu()
{
	printf("**********  扫雷小游戏  ********* "); printf("             游戏介绍\n");
	printf("********      1. play    ******** "); printf("1.两次对同一个点标记,可取消标记.\n");
	printf("********      0. exit    ******** "); printf("2.最后一次输入位置若是地雷,则该位置将会被标为\033[1;31m%c\033[0m以此告诉玩家死亡原因.\n",MINE_FLAG);
	printf("********************************* "); printf("3.若在坐标后面输入Y则表示对该点进行标记,其它默认不标记.\n");
}

int main()
{
	srand((unsigned int)time(NULL));
	int input = 0;
	do
	{
		menu();
		printf("请选择:>");
		scanf("%d", &input);
		switch (input)
		{
		case PLAY:
			system("cls");
			game(); break;
		case EXIT:
			system("cls"); printf("退出游戏\n"); break;
		default:
			system("cls"); printf("输入有误,重新输入:>\n"); break;
		}
	} while (input);
	return 0;
}

至于大家所说的头文件无法引用的问题,大概率可能是大家没有建立game.h这个头文件,而是将头文件里面的内容全部直接包含进源文件里面了,为了解决这个问题,我们只需要建立一个game.h文件即可,建立如下:
C语言300行代码实现扫雷(可展开+可标记+可更改困难级别+内附图形界面版本),C语言,c语言,开发语言,算法
C语言300行代码实现扫雷(可展开+可标记+可更改困难级别+内附图形界面版本),C语言,c语言,开发语言,算法
游戏截图:
C语言300行代码实现扫雷(可展开+可标记+可更改困难级别+内附图形界面版本),C语言,c语言,开发语言,算法
C语言300行代码实现扫雷(可展开+可标记+可更改困难级别+内附图形界面版本),C语言,c语言,开发语言,算法

C语言300行代码实现扫雷(可展开+可标记+可更改困难级别+内附图形界面版本),C语言,c语言,开发语言,算法

C语言300行代码实现扫雷(可展开+可标记+可更改困难级别+内附图形界面版本),C语言,c语言,开发语言,算法文章来源地址https://www.toymoban.com/news/detail-823890.html

到了这里,关于C语言300行代码实现扫雷(可展开+可标记+可更改困难级别+内附图形界面版本)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C语言初阶之扫雷代码详解(含递归展开)

    主要分为下面几个过程: 1、建立棋盘 2、初始化棋盘 3、设置棋盘雷数 4、打印棋盘 5、玩家找雷 6、判定胜负 文件名:game.h 代码如下: 在game头文件中,首先包含会使用到的库头文件,这里的ROW以及COL是雷区的行和列大小,也就是说这是玩家实际能看到的行数及列数,而RO

    2024年02月03日
    浏览(35)
  • C语言实现扫雷(包含递归展开)

    目录 一:扫雷游戏的基础逻辑 二:关于扫雷相关的信息存储 三:游戏大体实现逻辑 四:具体实现 (1)初始化 (2)打印 (3)布置雷 (4)查雷 五:全部代码 (1)game.h (2)game.c (3)test.c 六:实际效果演示 扫雷游戏逻辑如下: 1. 游戏开始时,玩家将看到一个方格棋盘,每个方格上有一个数

    2024年02月05日
    浏览(41)
  • C语言之扫雷小游戏的实现【含递归展开】

    扫雷游戏是1992年发行的一款大众类益智游戏,对于许多80后、90后来说都是童年的回忆。如今三十年过去了,这款游戏依旧受到很多网友的喜爱,今天我们一起来模拟实现一下扫雷游戏。 本文所用的编译器是VS2022 这里我们使用模块化设计,模块化设计就是把各个模块的代码分

    2024年02月02日
    浏览(49)
  • 【C语言】扫雷游戏(可展开)——超细教学

    🚩 纸上得来终觉浅, 绝知此事要躬行。 🌟主页:June-Frost 🚀专栏:C语言 🔥该篇将运用数组来实现 扫雷游戏。 通过迭代保证每次玩完游戏后可以再来一局或者退出。 说明: 1 .   实现扫雷,首先需要布置雷,通过一个二维数组就可以很容易的将雷的信息存储下来。 只需

    2024年02月11日
    浏览(38)
  • 【C语言】扫雷小游戏(递归展开版)

    哈喽,大家好,上次我们已经学习了三子棋小游戏,今天我们来学习扫雷小游戏了。 目录 1.游戏介绍 2.函数部分 2.1菜单 2.2game()函数 2.3mian()函数 2.4初始化棋盘 2.5打印棋盘 2.6布置雷 2.7排查雷 2.8统计雷 2.9递归,展开一片区域 3.完整代码展示  想必大家都玩过扫雷这款小游戏吧

    2024年02月12日
    浏览(47)
  • C语言——扫雷小游戏(递归展开版)

    哈喽,大家好,上次我们已经学习了三子棋小游戏,今天我们来学习扫雷小游戏了。 目录 1.游戏介绍 2.函数部分 2.1菜单 2.2game()函数 2.3mian()函数 2.4初始化棋盘 2.5打印棋盘 2.6布置雷 2.7排查雷 2.8统计雷 2.9递归,展开一片区域 3.完整代码展示  想必大家都玩过扫雷这款小游戏吧

    2024年02月03日
    浏览(54)
  • “纯C”实现——扫雷游戏(递归实现展开功能)

    📺游戏动画演示 🚀扫雷实现思路 🚀棋盘实现 🚀布置雷实现 🚀玩家扫雷实现 🚀带展开功能的扫雷 🚀小结语 🚗text.c文件 🚗game.h文件 🚗game.c文件 游戏实现完成的模样: 实现扫雷游戏的前提是要知道: 扫雷游戏的玩法 (会玩的跳过这步) 扫雷游戏也就是排雷,让玩家点

    2024年02月03日
    浏览(43)
  • 【C语言】扫雷游戏完整代码实现

    目录 1.game.h 2.game.c 3.progress.c 4.运行结果

    2024年02月21日
    浏览(43)
  • C语言两百行代码实现简易扫雷

    扫雷应该是我们接触到的第一个电脑游戏,用c语言实现扫雷对初学者来说是一个不错的锻炼 编写扫雷只需要用到数组、函数和生成随机数的知识,所以比较适合成为编程学习者编写的第一个小游戏。 如果不熟悉生成随机数的知识,可以去我的上一篇文章看看《C生成随机数》

    2024年02月05日
    浏览(46)
  • C语言实现扫雷完整算法详解~(附完整代码~)

    扫雷是一个常见小游戏,那么如何用C语言实现扫雷呢?学习了二维数组之后,我们可将扫雷的网格区域存储为二维数组,从而使用C语言实现扫雷。 目录 1.算法基本思路 2.算法详解 1.初始化数组与打印数组 2.设置雷 3.排查与标记 4.CountMine函数计算周围雷的个数  5.ExpandMine函数

    2024年02月05日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包