C语言扫雷最新 递归展开 超详解(附源码)

一、前言

什么!写C语言扫雷游戏?只需要100行代码、只需要C语言基础?没错!对新手超级友好、超详细的教程来了,通过这个小项目的练习你的编程能力又能得到更大的提升。太简单还是不够过瘾?
C语言写俄罗斯方块在这里 :https://blog.csdn.net/qq_41796226/article/details/125818224

游戏说明

1.输入对应的横纵坐标 x y (含输入合法性检查)
2.坐标为(x , y)的点显示周围地雷的数量
3.如果为周围地雷数量为 0,程序自动点开 0 位置周围各点(递归算法)
4.游戏界面显示剩余不确定的位置个数,和已知的地雷数量
5.可自定义界面大小和地雷数量
6.快去拓展更多功能吧

游戏效果

在这里插入图片描述

二、实现步骤

1、头文件、宏定义、全局变量及函数声明
#include<stdio.h>
#include<stdlib.h>
#include<time.h>

#define HEIGHT 10	//行
#define WIDTH 10	//列
#define BOOM_NUM 10
int count_last = HEIGHT*HEIGHT;
char user_map[HEIGHT][WIDTH];	//玩家界面
char mine_map[HEIGHT][WIDTH];	//设计者界面

void initial_map();
void put_map(char (*p)[WIDTH]);
void set_bom();
void sweep(int x,int y);
int check();
int count_here(int m,int n);
2、初始化游戏界面

在这里插入图片描述

全局变量:
char user_map[HEIGHT][WIDTH];
char mine_map[HEIGHT][WIDTH];

/*
功能:给全局变量两个二维数组赋初始值
*/
void initial_map()
{
	int i,j;
	for(i=0;i<HEIGHT;i++)
	{
		for(j=0;j<WIDTH;j++)
		{
			user_map[i][j] = '*';//玩家界面的点
			mine_map[i][j] = '-';//开发者界面的点
		}
	}
}
/*
功能:打印游戏界面
参数:传入mine_map或者user_map
*/
void put_map(char (*p)[WIDTH])			//对数组指针不太了解的可以分成put_minemap和put_usermap两个函数写
{
	check();				//函数中计算user_map剩余'*'的数量count_last
	printf("  Remain: %2d     Boom: %2d\n",count_last,BOOM_NUM);
	int i,j;
	for(i=0;i<2;i++)			//界面前两行打印辅助标示
	{
		printf("    ");
		for(j=0;j<WIDTH;j++)
		{
			if(i==0)
				printf("%2d",j);
			else
				printf(" v");
		}
		printf("\n");
	}
	for(i=0;i<HEIGHT;i++)
	{
		printf("%2d >",i); 		//界面前两列打印辅助标示
		for(j=0;j<WIDTH;j++)
		{
			printf(" %c",p[i][j]);
		}
		printf("\n");
	}
}
3、布置地雷

#include<stdlib.h>
#include<time.h>
#define BOOM_NUM 10

/*
功能:给mine_map坐标系中随机布置BOM_NUM个地雷
*/
void set_bom()
{
	srand(time(0));				//随机时间种子
	int x,y;
	int bom_num = BOOM_NUM;
	while(bom_num)
	{
		x = rand()%HEIGHT;		//随机出一个数 0~HEIGHT-1
		y = rand()%WIDTH;		//随机出一个数 0~WIDTH-1
		if(mine_map[x][y]=='@')	//避免一个位置重复布雷
			continue;
		mine_map[x][y] = '@';
		bom_num--;				//每布下一个雷,自减一次
	}
}
4、扫雷
/*
功能:计算user_map[y][x]周围地雷数量
参数:玩家输入的横坐标x,纵坐标y
返回值:(x,y)周围地雷的数量
*/
int count_here(int x,int y) 
{
	int count = 0;
	int i,j;
	for(i=(y==0?0:y-1);i<=(y==HEIGHT-1?HEIGHT-1:y+1);i++)
	{
		for(j=(x==0?0:x-1);j<=(x==WIDTH-1?WIDTH:x+1);j++)//考虑越界问题,下图详解
		{
			if(mine_map[i][j]=='@')		//通过mine_map[i][j]来映射user_map[i][j]
				count++;
		}
	}
	return count;
}

在这里插入图片描述

/*
功能:给user_map[y][x]赋值为该点周围地雷数量,若为0,调用自身给0周围的点赋值,依次递归
参数:玩家输入的横坐标x,纵坐标y
*/
void sweep(int x,int y) 
{

		if(user_map[y][x]!='*')
			return;
		int count = count_here(x,y);
		user_map[y][x] = count+'0';	//把int类型转换为char类型
		system("clear");		//清屏(非linux终端注释这行代码)
		fflush(stdout);			//清理终端缓存(非linux终端注释这行代码)
		put_map(user_map);
		usleep(1000*50);		//微秒级延时(非linux终端注释这行代码)
		if(count!=0)			//若count为0,递归调用
			return;
		int i,j;
		for(i=(y==0?0:y-1);i<=(y==HEIGHT-1?HEIGHT-1:y+1);i++)//考虑越界问题,上图详解
		{
			for(j=(x==0?0:x-1);j<=(x==WIDTH-1?WIDTH-1:x+1);j++)
			{
				sweep(j,i);
			}
		}
		return;
}
5、扫雷完成判断

在这里插入图片描述

全局变量
int count_last = HEIGHT*HEIGHT;

/*
功能:通过计算user_map[y][x]中剩余的'*'的数量,对比地雷数量,实现对游戏结束的判断
返回值:扫雷完成返回 1,  未完成返回 0
*/
int check()
{	
	count_last = 0;
	int i,j;
	for(i=0;i<HEIGHT;i++)
	{
		for(j=0;j<WIDTH;j++)
		{
			if(user_map[i][j]=='*')
				count_last++;
		}
	}
	if(count_last==BOOM_NUM)
		return 1;
	else
		return 0;
}
6、主函数
int main()
{
	system("clear");		//清屏(非linux终端注释这行代码)
	initial_map();
	set_bom();
	put_map(mine_map);
	usleep(1000*2000);		//微秒级延时(非linux终端注释这行代码)
	system("clear");		//清屏(非linux终端注释这行代码)
	put_map(user_map);
	while(1)
	{
		if(check())			//扫雷完成判断(游戏结束条件1)
		{
			printf("Congratulations! You Win!\n");
			put_map(mine_map);
			break;
		}
		int x,y;
		printf("Input coordinates: x y\n");
		while(1)							//检查输入合法性
		{
			scanf("%d%d",&x,&y);
			if(x<0||x>WIDTH||y<0||y>HEIGHT)
				printf("Coordinates nagative,input again:\n");
			else		
				break;
		}
		if(mine_map[y][x]=='@')				//踩雷判断(游戏结束条件2)
		{
			printf("Oh no! You are on the Boom!\n");
			put_map(mine_map);
			break;
		}
		sweep(x,y);
	}
	return 0;
}

三、完结撒花

1.笔者因水平限制如有误导大家的地方非常抱歉哈
2.欢迎下方留言讨论,谢谢大家的支持
3.来“华清远见” http://www.hqyj.com/学习更多编程知识
在这里插入图片描述

四、完整源码

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

#define HEIGHT 10	//行
#define WIDTH 10	//列
#define BOOM_NUM 10
int count_last = HEIGHT*HEIGHT;
char user_map[HEIGHT][WIDTH];	//玩家界面
char mine_map[HEIGHT][WIDTH];	//设计者界面

void initial_map();
void put_map(char (*p)[WIDTH]);
void set_bom();
void sweep(int x,int y);
int check();
int count_here(int m,int n);

int main()
{
	system("clear");			//清屏(非linux终端注释这行代码)
	initial_map();
	set_bom();
	put_map(mine_map);
	putchar('\n');
	usleep(1000*2000);			//微秒级延时(非linux终端注释这行代码)
	system("clear");
	put_map(user_map);
	while(1)
	{
		if(check())			//扫雷完成判断(游戏结束条件1)
		{
			printf("Congratulations! You Win!\n");
			put_map(mine_map);
			break;
		}
		int x,y;
		printf("Input coordinates: x y\n");
		while(1)			//检查输入合法性
		{
			scanf("%d%d",&x,&y);
			if(x<0||x>WIDTH||y<0||y>HEIGHT)
				printf("Coordinates nagative,input again:\n");
			else		
				break;
		}
		if(mine_map[y][x]=='@')		//踩雷判断(游戏结束条件2)
		{
			printf("Oh no! You are on the Boom!\n");
			put_map(mine_map);
			break;
		}
		sweep(x,y);
	}
	return 0;
}
/*
功能:给全局变量两个二维数组赋初始值
*/
void initial_map()
{
	int i,j;
	for(i=0;i<HEIGHT;i++)
	{
		for(j=0;j<WIDTH;j++)
		{
			user_map[i][j] = '*';//玩家界面的点
			mine_map[i][j] = '-';//开发者界面的点
		}
	}
}
/*
功能:打印游戏界面
参数:传入mine_map或者user_map
*/
void put_map(char (*p)[WIDTH])			//对数组指针不太了解的可以分成put_minemap和put_usermap两个函数写
{
	check();				//函数中计算user_map剩余'*'的数量count_last
	printf("  Remain: %2d     Boom: %2d\n",count_last,BOOM_NUM);
	int i,j;
	for(i=0;i<2;i++)			//界面前两行打印辅助标示
	{
		printf("    ");
		for(j=0;j<WIDTH;j++)
		{
			if(i==0)
				printf("%2d",j);
			else
				printf(" v");
		}
		printf("\n");
	}
	for(i=0;i<HEIGHT;i++)
	{
		printf("%2d >",i); 		//界面前两列打印辅助标示
		for(j=0;j<WIDTH;j++)
		{
			printf(" %c",p[i][j]);
		}
		printf("\n");
	}
}
/*
功能:给mine_map[y][x]中随机布置BOM_NUM个地雷
*/
void set_bom()
{
	srand(time(0));
	int x,y;
	int bom_num = BOOM_NUM;
	while(bom_num)
	{
		x = rand()%HEIGHT;
		y = rand()%WIDTH;
		if(mine_map[x][y]=='@')
			continue;
		mine_map[x][y] = '@';
		bom_num--;
	}
}
/*
功能:计算user_map[y][x]周围地雷数量
参数:玩家输入的横坐标x,纵坐标y
返回值:(x,y)周围地雷的数量
*/
int count_here(int x,int y) 
{
	int count = 0;
	int i,j;
	for(i=(y==0?0:y-1);i<=(y==HEIGHT-1?HEIGHT-1:y+1);i++)
	{
		for(j=(x==0?0:x-1);j<=(x==WIDTH-1?WIDTH:x+1);j++)//考虑越界问题
		{
			if(mine_map[i][j]=='@')
				count++;
		}
	}
	return count;
}
/*
功能:给user_map[y][x]赋值为该点周围地雷数量,若为0,调用自身给0周围的点赋值,依次递归
参数:玩家输入的横坐标x,纵坐标y
*/
void sweep(int x,int y) 
{

		if(user_map[y][x]!='*')
			return;
		int count = count_here(x,y);
		user_map[y][x] = count+'0';	//把int类型转换为char类型
		system("clear");		//清屏(非linux终端注释这行代码)
		fflush(stdout);			//清理终端缓存(非linux终端注释这行代码)
		put_map(user_map);
		usleep(1000*50);		//微秒级(非linux终端注释这行代码)
		if(count!=0)			//若count为0,递归调用
			return;
		int i,j;
		for(i=(y==0?0:y-1);i<=(y==HEIGHT-1?HEIGHT-1:y+1);i++)
		{
			for(j=(x==0?0:x-1);j<=(x==WIDTH-1?WIDTH-1:x+1);j++)
			{
				sweep(j,i);
			}
		}
		return;
}
/*
功能:通过计算user_map[y][x]中剩余的'*'的数量,对比地雷数量,实现对游戏结束的判断
返回值:扫雷完成返回 1,  未完成返回 0
*/
int check()
{	
	count_last = 0;
	int i,j;
	for(i=0;i<HEIGHT;i++)
	{
		for(j=0;j<WIDTH;j++)
		{
			if(user_map[i][j]=='*')
				count_last++;
		}
	}
	if(count_last==BOOM_NUM)
		return 1;
	else
		return 0;
}
  • 11
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是一个用C++实现的扫雷游戏,具体实现思路是使用二维数组来表示扫雷游戏的格子,其中0表示空格,1表示有地雷的格子,2表示已经翻开的格子,3表示标记为地雷的格子。在游戏过程中,使用归算法来实现翻开空格的效果,同时需要判断游戏是否结束。 ```cpp #include <iostream> #include <vector> #include <ctime> #include <cstdlib> using namespace std; // 定义常量 const int BOARD_SIZE = 10; // 扫雷游戏的大小 const int MINE_NUM = 15; // 地雷的数量 // 定义二维数组表示扫雷游戏的格子 int board[BOARD_SIZE][BOARD_SIZE]; // 在指定位置放置地雷 void placeMine(int x, int y) { board[x][y] = 1; } // 随机放置地雷 void placeMines() { srand(time(nullptr)); int count = 0; while (count < MINE_NUM) { int x = rand() % BOARD_SIZE; int y = rand() % BOARD_SIZE; if (board[x][y] != 1) { placeMine(x, y); count++; } } } // 计算指定位置周围地雷数量 int countMines(int x, int y) { int count = 0; for (int i = -1; i <= 1; ++i) { for (int j = -1; j <= 1; ++j) { int nx = x + i; int ny = y + j; if (nx >= 0 && nx < BOARD_SIZE && ny >= 0 && ny < BOARD_SIZE && board[nx][ny] == 1) { count++; } } } return count; } // 打印游戏面板 void printBoard(bool showMine) { for (int i = 0; i < BOARD_SIZE; ++i) { for (int j = 0; j < BOARD_SIZE; ++j) { if (board[i][j] == 2) { cout << countMines(i, j) << " "; } else if (board[i][j] == 3) { cout << "F "; } else if (showMine && board[i][j] == 1) { cout << "* "; } else { cout << "- "; } } cout << endl; } } // 翻开指定位置的格子 bool click(int x, int y) { if (board[x][y] == 1) { return false; } else if (board[x][y] == 2) { return true; } else { board[x][y] = 2; if (countMines(x, y) == 0) { for (int i = -1; i <= 1; ++i) { for (int j = -1; j <= 1; ++j) { int nx = x + i; int ny = y + j; if (nx >= 0 && nx < BOARD_SIZE && ny >= 0 && ny < BOARD_SIZE) { click(nx, ny); } } } } return true; } } // 标记指定位置的格子 void mark(int x, int y) { if (board[x][y] == 3) { board[x][y] = 0; } else { board[x][y] = 3; } } // 判断游戏是否结束 bool isGameOver() { for (int i = 0; i < BOARD_SIZE; ++i) { for (int j = 0; j < BOARD_SIZE; ++j) { if (board[i][j] == 2) { continue; } else if (board[i][j] == 1) { continue; } else { return false; } } } return true; } int main() { // 初始化游戏面板 for (int i = 0; i < BOARD_SIZE; ++i) { for (int j = 0; j < BOARD_SIZE; ++j) { board[i][j] = 0; } } placeMines(); // 开始游戏 bool gameOver = false; while (!gameOver) { printBoard(false); cout << "请输入坐标和操作(x y c/m):"; int x, y; char op; cin >> x >> y >> op; if (op == 'm') { mark(x, y); } else if (op == 'c') { if (!click(x, y)) { gameOver = true; printBoard(true); cout << "游戏结束,你输了!" << endl; } else if (isGameOver()) { gameOver = true; printBoard(true); cout << "恭喜你,你赢了!" << endl; } } } return 0; } ``` 该程序可以实现一个简单的扫雷游戏,支持放置地雷、随机放置地雷、计算周围地雷数量、打印游戏面板、翻开格子、标记格子、判断游戏是否结束等操作。需要注意的是,由于该程序使用了归算法来实现翻开空格的效果,可能会出现栈溢出的情况,因此需要设置归深度的限制。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值