C语言小项目 -- 扫雷游戏完整代码(递归展开 + 选择标记)

这篇具有很好参考价值的文章主要介绍了C语言小项目 -- 扫雷游戏完整代码(递归展开 + 选择标记)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

C语言小项目 -- 扫雷游戏完整代码(递归展开 + 选择标记)大家好,今天我们将一起用C语言实现一个经典小游戏 – 扫雷,Let is go !
C语言小项目 -- 扫雷游戏完整代码(递归展开 + 选择标记)

🏡游戏介绍

C语言小项目 -- 扫雷游戏完整代码(递归展开 + 选择标记)

扫雷游戏相信大家都玩过,上图就是一个网页版的扫雷,它的规则是玩家选择一个方格,若此方格没有地雷,那么该方格会显示与它相邻的八个方格中雷的个数,若此方格有地雷,那么游戏失败,当玩家把除了有地雷的方格外的其他方格都成功翻开时,游戏胜利。


🏡游戏整体框架

对于一个代码量还算可以的小游戏我们还是利用多文件来进行编程,养成良好习惯,为以后在公司团队合作编程打下基础,因此我们把扫雷游戏分成三个文件来编写:

test.c:游戏逻辑的测试,包含游戏菜单的打印,游戏设计的基本逻辑的展示。

game.c:游戏功能的具体实现,这部分是整个游戏的核心代码,一般不会展示给用户。

game.h:相关头文件的包含、符号的声明以及函数的声明。

🏡游戏具体功能及实现

🪁1、雷盘的定义

对于扫雷游戏,我们遇到的第一个问题就是:应该如何表示扫雷的雷盘及如何存放布雷、排雷的数据;我们发现,二维数组可以很好的解决这个问题。

C语言小项目 -- 扫雷游戏完整代码(递归展开 + 选择标记)

C语言小项目 -- 扫雷游戏完整代码(递归展开 + 选择标记)

如上图:我们定义了两个棋盘,分别用来保存布置雷的信息和排查雷的信息,这样就可以避免二者相互干扰或者相互覆盖

同时,我们使用宏来定义雷盘的大小以及雷的个数,这样做的好处是当我们以后想使用更大的雷盘或者想增加扫雷的难度的时候,我们只需要改动这里一次即可,增加了代码的可维护性

另外,很多小伙伴可能会疑惑为什么我这里会定义两个不同ROW和COL,这其实是为后面的排雷做铺垫:

C语言小项目 -- 扫雷游戏完整代码(递归展开 + 选择标记)

如图:当我们排查1位置时,如果1处不是雷,那么我们就会依次检查1周围8个坐标是否有地雷,如果有,就会把地雷的数量显示在1位置处;但是当我们排查2位置时,我们发现, 数组排查雷时会发生越界,所以为了避免数组越界,我们就需要增加一系列限制条件,这样做无疑是比较麻烦的,所以有的大佬就想出了这样一种办法:在定义数组长度时我们直接在上下左右四个方向各多给一行的空间,并把这些空间中的数据初始化为非雷,这样,就轻松解决了数组越界的问题,不得不说,这种方法实在巧妙!

C语言小项目 -- 扫雷游戏完整代码(递归展开 + 选择标记)


🪁2、雷盘的初始化

最开始的时候我们把mine数组元素全部初始化为字符0,把show数组元素全部初始化为字符*(给用户一种神秘的感觉)。

C语言小项目 -- 扫雷游戏完整代码(递归展开 + 选择标记)


🪁3、布置雷

对于布置雷我们有两个需要注意的地方:

第一是用于随机生成坐标的rand函数的种子srand函数只需要在main函数中声明一次即可。

第二是我们在布置雷的时候需要检查该位置是否已经有雷,避免重复布置。

C语言小项目 -- 扫雷游戏完整代码(递归展开 + 选择标记)


🪁4、排查雷

排查雷的时候我们首先需要让用户输入需要排查的坐标,然后判断坐标的合法性及该坐标是否已被排查,其次再判断该坐标是否有雷,如果没有,就递归检查它周围的坐标,直到遇到有雷的坐标才停止递归,再让用户选择是否需要标记雷的信息,最后检查是否满足游戏胜利的条件。

C语言小项目 -- 扫雷游戏完整代码(递归展开 + 选择标记)

🪁5、递归式展开一片

C语言小项目 -- 扫雷游戏完整代码(递归展开 + 选择标记)

观察网页版的扫雷我们可以发现,当用户点击一个坐标,如果该坐标及其周围的坐标都没有雷,那么雷盘就会一次性展开一片,而这样设计也是比较合理的,因为如果每一个非雷坐标都需要玩家排查的话十分影响游戏体验;所以,这里我们就利用递归的实现模拟实现了这个功能。

C语言小项目 -- 扫雷游戏完整代码(递归展开 + 选择标记)


🪁6、获取周围雷的个数

C语言小项目 -- 扫雷游戏完整代码(递归展开 + 选择标记)


🪁7、标记特定位置

C语言小项目 -- 扫雷游戏完整代码(递归展开 + 选择标记)

同样:在网页版的扫雷中,如果我们确定某一位置一定是雷时,我们可以利用标记功能来标识该坐标,方便我们后面的判断。

本代码中,我们用字符 ! 来标识雷。

C语言小项目 -- 扫雷游戏完整代码(递归展开 + 选择标记)


🪁8、打印雷盘

C语言小项目 -- 扫雷游戏完整代码(递归展开 + 选择标记)


🏡游戏完整代码

🗝️1、test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"

void menu()
{
	printf("*****************************************\n");
	printf("*********  1.play      0.exit   *********\n");
	printf("*****************************************\n");
}

void game()
{
	//定义用于存放雷和显示雷的数组
	char mine[ROWS][COLS];
	char show[ROWS][COLS];
	//数组初始化
	BoardInit(mine, ROWS, COLS, '0');
	BoardInit(show, ROWS, COLS, '*');
	//埋雷
	SetMine(mine, ROW, COL);
	system("cls");   //清除菜单,美观整洁
	//打印雷盘
	//BoardPrint(mine, ROW, COL);   //用于自己调试观察,在发布时注释掉
	BoardPrint(show, ROW, COL);
	//排雷
	FindMine(mine, 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;
}

🗝️2、game.h

#pragma once

#include<stdio.h>
#include<windows.h>
#include<time.h>
#include<stdlib.h>

#define ROW 9
#define COL 9
#define ROWS ROW + 2
#define COLS COL + 2
#define MINE_COUNT 10

//数组初始化
void BoardInit(char board[ROWS][COLS], int rows, int cols, char set);
//埋雷
void SetMine(char board[ROWS][COLS], int row, int col);
//排雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
//打印雷盘
void BoardPrint(char board[ROWS][COLS], int row, int col);

🗝️3、game.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"

//数组初始化
void BoardInit(char board[ROWS][COLS], int rows, int cols, char set)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < rows; i++)
	{
		for (j = 0; j < cols; j++)
		{
			board[i][j] = set;   //set表示要初识化的字符
		}
	}
}

//埋雷
void SetMine(char board[ROWS][COLS], int row, int col)
{
	int count = MINE_COUNT;
	while (count)
	{
		int x = rand() % row + 1;      //随机生成雷的坐标
		int y = rand() % col + 1;
		if (board[x][y] == '0')        //检查该位置是否已经有雷
		{
			board[x][y] = '1';
			count--;
		}
	}
}

//打印雷盘
void BoardPrint(char board[ROWS][COLS], int row, int col)
{
	int i = 0;
	int j = 0;
	printf("------扫雷游戏------\n");
	for (i = 0; i <= row; 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");
	}
	printf("------扫雷游戏------\n");
}

//标记雷的位置
void MarkMine(char board[ROWS][COLS], int row, int col)
{
	int x = 0;
	int y = 0;
	while (1)
	{
		printf("请输入你想要标记位置的坐标->");
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col)    //判断该坐标是否合法
		{
			if (board[x][y] == '*')        //判断该坐标是否被排查
			{
				board[x][y] = '!';
				break;
			}
			else
			{
				printf("该位置不能被标记,请重新输入!\n");
			}
		}
		else
		{
			printf("输入错误,请重新输入!\n");
		}
	}
}

//获取坐标周围雷的个数
int GetMineCount(char board[ROWS][COLS], int x, int y)
{
	int i = 0;
	int j = 0;
	int count = 0;
	for (i = x - 1; i <= x + 1; i++)
	{
		for (j = y - 1; j <= y + 1; j++)
		{
			if (board[i][j] == '1')
			{
				count++;
			}
		}
	}
	return count;
}

//递归爆炸式展开一片
void ExplosionSpread(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col, int x, int y, int* pw)
{
	if (x >= 1 && x <= row && y >= 1 && y <= col)  //判断坐标是否为排查范围内
	{
		int num = GetMineCount(mine, x, y);   //获取坐标周围雷的个数
		if (num == 0)
		{
			(*pw)++;
			show[x][y] = ' ';   //如果该坐标周围没有雷,就把该坐标置成空格,并向周围八个坐标展开
			int i = 0;
			int j = 0;
			for (i = x - 1; i <= x + 1; i++)
			{
				for (j = y - 1; j <= y + 1; j++)
				{
					if (show[i][j] == '*')    //限制递归条件,防止已经排查过的坐标再次递归,从而造成死递归
						ExplosionSpread(mine, show, row, col, i, j, pw);
				}
			}
		}
		else
		{
			(*pw)++;
			show[x][y] = num + '0';
		}
	}
}

//排雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
	int x = 0;
	int y = 0;
	int win = 0;  //用来标记是否取得胜利
	int* pw = &win;
	char ch = 0;   //用来接受是否需要标记雷
	while (win < row * col - MINE_COUNT)
	{
		printf("请输入你想要排查的坐标->");
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col)   //判断坐标合法性
		{
			if (mine[x][y] == '1')
			{
				system("cls");
				printf("很遗憾,你被炸死了!\n");
				BoardPrint(mine, row, col);   //被炸死了就打印mine数组,让用户知道自己怎么死的
				break;
			}
			else
			{
				if (show[x][y] != '*')   //判断是否重复排查
				{
					printf("该坐标已被排查,请重新输入!\n");
					continue;  //直接进入下一次循环
				}
				else
				{
					ExplosionSpread(mine, show, row, col, x, y, pw);  //爆炸展开一片
					system("cls");  //清空屏幕
					BoardPrint(show, row, col);  //打印棋盘
					printf("需要标记雷的位置请输入y/Y,否则请按任意键->");
					while ((ch = getchar()) != '\n');  //清理缓冲区
					scanf("%c", &ch);
					if (ch == 'Y' || ch == 'y')
					{
						MarkMine(show, row, col);   //标记雷
						system("cls");
						BoardPrint(show, row, col);
					}
					else
					{
						continue;
					}
				}
			}
		}
		else
		{
			printf("输入错误,请重新输入!\n");
		}
	}
	if (win == row * col - MINE_COUNT)
	{
		system("cls");
		printf("恭喜你,排雷成功!\n");
		BoardPrint(show, row, col);
		return;
	}
}

🏡游戏效果展示

C语言小项目 -- 扫雷游戏完整代码(递归展开 + 选择标记)文章来源地址https://www.toymoban.com/news/detail-450189.html


到了这里,关于C语言小项目 -- 扫雷游戏完整代码(递归展开 + 选择标记)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • 入门C语言第三话:数组之实战篇——扫雷(进阶版——图形化界面,递归展开,播放音乐与音效,标记取消雷,记录雷的个数,鼠标点击,文末附有完整代码)

     不为模糊不清的未来过分担忧,只为清清楚楚的现在奋发图强。  如果思路不是特别清晰的兄弟,建议多看一下基础版扫雷:数组之实战篇——带你从0到1实现扫雷(简易版)  如果EasyX图形库不是特别明白:可以看一下这篇文章:入门EasyX图形库(带你进入不一样的程序

    2024年02月09日
    浏览(30)
  • C语言初阶之扫雷代码详解(含递归展开)

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

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

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

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

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

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

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

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

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

    2024年02月11日
    浏览(30)
  • 【C语言】万字教学,带你分步实现扫雷游戏(内含递归函数解析),剑指扫雷,一篇足矣

    君兮_的个人主页 勤时当勉励 岁月不待人 C/C++ 游戏开发 Hello,这里是君兮_,今天更新一篇关于利用C语言实现扫雷游戏的博客。对于初学者来说,这也是一个非常容易上手的小项目,看完不妨自己试试哦! 废话不多说,我们直接开始吧! 相信很多人在小时候都玩过扫雷游戏,但

    2024年02月11日
    浏览(28)
  • 童年回忆--扫雷(包括标记功能和递归展开)--万字讲解让你学会扫雷制作

    魔王的介绍:😶‍🌫️一名双非本科大一小白。 魔王的目标:🤯努力赶上周围卷王的脚步。 魔王的主页:🔥🔥🔥大魔王.🔥🔥🔥 ❤️‍🔥大魔王与你分享:人生人山人海人来人往,自己自尊自爱自由自在。 小时候我们在家里刚买电脑的时候,网络还不是很发达(两三

    2023年04月14日
    浏览(26)
  • C语言300行代码实现扫雷(可展开+可标记+可更改困难级别+内附图形界面版本)

    扫雷是一个经典的游戏,是一个益智类小游戏,在80、90年代曾风靡一时,当然现在也是十分受欢迎; 废话不多说; 让我们来了解一下如何用C语言去实现它吧!!!(❁´◡`❁) 运行环境:VS2019 图形化界面版本 先实现一个初级版本的: 1、我们得有一个9*9的棋盘; 2、我们在棋

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

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

    2024年02月05日
    浏览(26)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包