C语言扫雷

博主学的还不到家,如有问题,请大家指出,博主会多多学习。

首先要创建两个数组,数组的大小最好是比展示出来的数组要大两格,展示出来的数组是比实际的要小两格,这样就可以防止我们判断排查雷的时候不用去做,数组访问是否越界判断,第一个数组用来存放雷的信息,第二个用来打印出来显示给用户看的,通过用户输入的坐标,来判断,如果是雷则游戏失败,如果不是雷,则显示这个坐标周边的雷的数量信息,并展开他周边八个格子,如果不是雷则展开,是雷则不展开,并且雷的上一格和下一格也不展开,保持游戏难度。

 

首先是test.c的主函数代码内容

#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
void menu()
{
	printf("******************************
");
	printf("********* 1.游戏开始 *********
");
	printf("********* 0.退出游戏 *********
");
	printf("******************************
");
}
void game()
{
	char show[ROWS][COLS]={0};//存放展示出来的数据
	char mine[ROWS][COLS]={0};//存放雷放置的信息
	InitBoard(show, ROWS, COLS, '*');//定义一个初始化函数 把需要初始化的数组地址传过去,还有行和列,和要初始化的内容
	InitBoard(mine, ROWS, COLS, '0');//定义一个初始化函数 把需要初始化的数组地址传过去,还有行和列,和要初始化的内容
	//布置雷
	SetMine(mine, ROW, COL);
	//定义一个打印函数
	DisPlayBoard(show, ROW, COL);
	//DisPlayBoard(mine, ROW, COL);//测试用的,用来显示雷的信息
	FineMine(mine, show, ROW, COL);
}
int main()
{
	srand((unsigned int)time(NULL));//这个是随机生成雷的时间传递,时间是变动的,所以传递时间永远都是随机的
	int input = 0;
	do
	{
		menu();//菜单页面函数
		printf("请选择:");
		scanf("%d", &input);
		switch (input)//通过switch的逻辑判断 是否继续游戏,或退出游戏
		{
		case 1:
			game();
			break;
		case 0:
			printf("退出成功");
			break;
		default :
			printf("输入错误 请重新输入:");
			break;
		}
	} while (input);
	return 0;
}

这是game.h头文件的函数定义

#pragma once
#include <stdio.h>
#include <time.h>


#define ROW 9 //预设一个游戏页面大小 方便修改
#define COL 9//预设一个游戏页面大小 方便修改

#define ROWS ROW+2 //预设一个游戏页面大小 方便修改
#define COLS COL+2 //预设一个游戏页面大小 方便修改

#define EASE_COUNT 10// 这个是雷的分布数量


void InitBoard(char board[ROWS][COLS], int rows, int cols, char set);//初始化函数的定义
void DisPlayBoard(char board[ROWS][COLS], int row, int col);//打印数组显示
void SetMine(char mine[ROWS][COLS], int row, int col);//布置雷的函数
void FineMine(char mine[ROWS][COLS],char show[ROWS][COLS], int row,int col);//排查雷的函数

这是game.c函数的实现代码  下面一个一个来说明

首先定义一个数组接收,我们之前也说过,实际的数组大小要比展示出来的大两格,所以我们接收要接收全部,不能单独一部份接收,通过 两个for的嵌套,遍历整个数组,初始为想要的字符。

 

#define _CRT_SECURE_NO_WARNINGS 1
#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;
		}
	}
}



这是打印数组的代码实现,也是通过for的嵌套,不过这里我们只需要打印出来展示给用户看的页面,所以对数组的打印是从1开始,到9结束

void DisPlayBoard(char board[ROWS][COLS], int row, int col)
{
	int i = 0;
	int j = 0;
	printf("****** 扫雷游戏 ******
");
	for (j = 0; j <= col; j++)//打印数组内容之前先打印坐标
	{
		printf("%d ", j);
	}
	printf("
");
	for (i = 1; i <= row; i++)
	{
		printf("%d ", i);//打印数组内容之前先打印坐标
		for (j = 1; j <= col; j++)
		{
			printf("%c ", board[i][j]);
		}
		printf("
");
	}
}

这是布置雷的代码实现,主要是通过rand来实现,创建一个计数的,达到要布置雷的数量时停止循环,

void SetMine(char mine[ROWS][COLS], int row, int col)
{
	int x = 0;
	int y = 0;
	int count = EASE_COUNT;//雷的数量
	while (count)//每布置一个雷count--,直到布置完 结束循环
	{
		x = rand() % row + 1;
		y = rand() % col + 1;
		if (mine[x][y] == '0')//随机生成的坐标要判断一下,是否布置过雷了
		{
			mine[x][y] = '1';
			count--;
		}
	}
}

最麻烦的来了,就是排查雷的代码实现,首先对用户输入的坐标进行判断,是否合法,合法后再判断是否排查过,合法并未排查过的话,我们才执行对该坐标是否雷的判断,是雷则游戏结束,不是雷就显示该坐标周边八个格子的雷信息,之前我们把mine数组初始化成字符‘0’了,布置雷的信息初始化为字符‘1’,通过对坐标的周边八个格子相加,再减掉8乘以字符‘0’的ascll码值,这里8乘以字符'0'是计算ascll码,最后再把得到的数值加上一个字符‘0’就是一个数字字符了。

int get_count(char board[ROWS][COLS], 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][y + 1] + board[x + 1][y - 1] + 
	board[x + 1][y] + board[x + 1][y + 1] - 8 * '0';
}
void Is_Nomine(char show[ROWS][COLS],char mine[ROWS][COLS], int x, int y)//这是对用户输入的坐标来判断,以达到提示周边雷的信息
{
	for (int i = -1; i < 2; i++)
	{
		for (int j = -1; j < 2; j++)
		{
			if (mine[x + i][y + j] != '1')
			{
				if (show[x + i][y + j] == '*'&&mine[x + i][y-1]!='1' && mine[x + i][y]!='1')
				{
					//int count = get_count(mine, x, y);
					show[x + i][j + y] = ' ';
				}
			}
		}
	}
}
void FineMine(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-EASE_COUNT)
	{
		printf("请输入要排查的坐标:");
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col)//检测坐标的合法性
		{
			if (show[x][y] != '*')
			{
				printf("该坐标已被排查过,请重新输入:");
			}
			else
			{
				if (mine[x][y] == '1')//如果是雷
				{
					printf("很遗憾,游戏失败");
					DisPlayBoard(mine, ROW, COL);
					break;
				}
				else //如果不是雷
				{
					int count = get_count(mine, x, y);
					show[x][y] = count + '0';//+'0'是为了把get_count返回的int型数据转换成数字字符
					Is_Nomine(show,mine, x, y);
					//Set_Forth(show, mine, x, y);
					DisPlayBoard(show, ROW, COL);
				}
			}
		}
		else
		{
			printf("输入坐标非法,请重新输入");
		}
		for (int i = 1; i <= row; i++)
		{
			for (int j = 1; j <= col; j++)
			{
				if (show[i][j] != '*')
				{
					win++;
				}
			}
		}

	    if (win == row * col - EASE_COUNT)
	    {
		    printf("恭喜你,扫雷成功
");
		    DisPlayBoard(mine, ROW, COL);
	    }
	}

	if (win == EASE_COUNT)
	{
		printf("恭喜你,扫雷成功");
		DisPlayBoard(mine, ROW, COL);
	}
}

游戏过程,首先打印一个菜单

6ba0f6114f284ee8a3110fa3b3a056c3.png

选择1开始游戏,这是游戏的界面,

47cbf061693d403da9afe4cb76f88533.png

对于用递归来判断是否展开一片,博主暂时没有这个能力,只能通过对坐标周边八个格子判断,是否要展示出来

 16adbd5eeebc4b5ea6063126371c009a.png

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值