C语言实现简易版扫雷

本文介绍了一个简单的扫雷游戏实现,包括头文件定义、函数实现和主函数。作者通过设置两个表格简化了游戏逻辑,但也指出其存在的问题,如无法递归展开雷区、体验不佳等。文章邀请读者尝试改进递归功能,提高游戏体验。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

一.头文件

二.函数实现

 三.主函数

四.函数问题

扫雷类似于笔者发布的第一篇三子棋,不过还是有诸多细节需要注意。笔者技艺拙劣,仅能完成简易版扫雷,提前说明这个扫雷是没能实现递归(即类似于真正扫雷,点一个展开一片的功能)。

一.头文件

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define Rows 11
#define Cols 11
#define Col 9
#define Row 9
#define Easy_Count 10//设置十个雷

void InitBoard(char Board[Rows][Cols], int rows, int cols, char set);
void Disboard(char Board[Rows][Cols], int row, int col);
void SetMine(char Board[Rows][Cols], int row, int col);
void FindMine(char Mine[Rows][Cols], char Show[Rows][Cols], int row, int col);

头文件主要是宏的定义和函数声明。

 这里为什么要这样定义宏呢?因为笔者设置了两个表格,而真实的表格是11*11的表格,只打印出来了9*9的玩家操作表格。这样设置是方便后续的判断胜利与失败,要是诸君有兴趣的话,可以往后继续看,笔者会做解释。

二.函数实现

先上代码:

#include"GAME.h"

void InitBoard(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;
		}
	}
}
void Disboard(char Board[Rows][Cols], int row, int col)
{
	//首先需要一个行号和列号
	int i = 0;
	for (i = 0; i <=col; i++)
	{
		printf("%d ", i);
	}
	printf("\n");
	int j = 0;
	for (i = 1; i <= row; i++)
	{
		printf("%d ", i);
		for (j = 1; j <= col; j++)
		{
			printf("%c ", Board[i][j]);
		}
		printf("\n");
	}

}
void SetMine(char Board[Rows][Cols], int row, int col)
{
	//设置地雷
	int count = Easy_Count;
	while (count)
	{
		int x = rand() % row + 1;
		int y = rand() % col + 1;
		if (Board[x][y] == '0')
		{
			Board[x][y] = '1';
			count--;
		}
	}
}
int get_mine_count(char Mine[Rows][Cols], int x, int y)
{
	return  Mine[x - 1][y] + Mine[x - 1][y - 1] + Mine[x - 1][y + 1] + Mine[x][y - 1] +
		Mine[x][y + 1] + Mine[x + 1][y] + Mine[x + 1][y + 1]+ Mine[x + 1][y - 1]-8*'0';


}
void FindMine(char Mine[Rows][Cols], char Show[Rows][Cols], int row, int col)
{
	int x = 0;
	int y = 0;
	int win = 0;
	while (win<row*col-Easy_Count)
	{
		printf("请输入排查雷的坐标:>");
		scanf("%d%d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			//坐标合法
			//1.踩雷
			if (Mine[x][y] == '1')
			{
				printf("很遗憾,你被炸死了\n");
				Disboard(Mine, row, col);
				break;
			}
			else //不是雷
			{
				//计算x,y坐标周围有几个雷
				int count = get_mine_count(Mine, x, y);
				Show[x][y] = count + '0';
				Disboard(Show, row, col);
				win++;
			}
		}
		else
		{
			printf("输入坐标非法,请重新输入\n");
		}
	}
	if (win == row * col - Easy_Count)
	{
		printf("恭喜你,排雷成功\n");
		Disboard(Mine, row, col);
	}
}

1.雷包设置:

 笔者在雷包设置时是取巧了,在初始化表格的时候,设置了两个表格,一个表格是给我们程序员看的,即Mine[][]='0',这是没有雷的地方,而给玩家看的那个表Show[][]='*'进行了遮蔽。把有雷的地方设置为字符'1'。这一步也是取巧,因为在显示所要位置处需要计算周遭8个格子(因为要计算8个格子所以如果只设置9*9的表格,那么边角的坐标在计算周遭的雷时是需要特殊处理的,会增加代码的负荷,故设置了11*11的表格而只显示9*9的表格)总共有几颗雷,而1和0无疑是极其好运算的。但是需要诸君注意的是,这里还是字符1和字符0.所以下一步

 这一步,便是计算周围有几颗雷,需要注意字符'1'-字符'0'=1,所以便有了图中的-8*'0'也有了下图的+'0'.

 三.主函数

#include"GAME.h"
void menu()
{
	printf("************************\n");
	printf("******   1.play   ******\n");
	printf("******   0.exit   ******\n");
	printf("************************\n");
}
void game()
{
	char Mine[Rows][Cols] = { 0 };
	char Show[Rows][Cols] = { 0 };
	printf("扫雷\n");
	//需要两个表格,一个表格负责展示,一个表格负责操作
	InitBoard(Mine, Rows, Cols,'0');//由于两个一个负责自己看,但玩家不能看到
	InitBoard(Show, Rows, Cols,'*');//初始化两个
	//打印棋盘
	//Disboard(Mine, Row, Col);
	Disboard(Show, Row, Col);
	SetMine(Mine, Row, Col);
	//扫雷
	//mine 数组里找信息,显示在show
	FindMine(Mine, Show, Row, Col);//该数组问题是不能展开一片

}
void test()
{
	srand((unsigned int)time(NULL));
	int input = 0;
	do
	{
		menu();
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			printf("退出成功\n");
			break;
		default:
			printf("选择错误,请重新选择\n");
			break;
		}
	} while (input);
}
int main()
{
	test();
	return 0;
}

四.函数问题

这个构造是比较取巧的,笔者认为是极其简易且失败的😂。

1.首先在设置雷包的时候便借助了字符'1'和字符'0',而非正统的雷。

2.无法实现输入一个坐标就展开一片的问题。就是说传统的扫雷游戏是输入一个坐标会对周遭8个坐标进行计算是否有雷,如果没有雷,那么会对周围8个坐标的周围8个坐标再次运算是否有雷,如此循环,便能看到传统扫雷的展开一片。而笔者所写的是简易的,坦白说是笔者技艺浅薄,无法实现这个递归。

3.不能简单只实现递归,递归后,判定条件就要发生改变。笔者的扫雷属实low,想要获胜需要输入71个坐标😂。所以这个递归的函数还是很能提升用户体验的。

如果有观者有兴趣实现这个递归,那么欢迎在评论区留言,或者私信笔者。让笔者也拜读一下。总之大家一同进步吧。🌹

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值