天天看点

c语言实现简易版扫雷

今天给大家带来的c语言实现的简易版扫雷,和上次的大体框架基本一样。接下来就开始实现扫雷游戏。

首先,还是一样先打开我们的编译器,创建一个空项目,在这个项目里面,我们添加三个文件,game2.h头文件,game2.c和test.c的源文件。这样分模块去写代码,项目的整体框架,思路,逻辑可以很好的展现出来,我们将所有你需要使用的头文件以及函数的声明都包含在game2.h中,在game2.c中去实现各类函数的功能,在test.c中去测试整个2代码。

c语言实现简易版扫雷

 和上次写的三子棋的游戏界面的选择是基本相同的,还是通过do while和switch语句实现。

void munu()
{

	printf("*******************\n");
	printf("**** 1.play *******\n");
	printf("**** 0.exit *******\n");
	printf("*******************\n");

}

int main()
{
	int input = 0;
	
	do
	{
		munu();
		printf("请选择:\n");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			printf("扫雷游戏开始!\n");
			game();
			break;
		case 0:
			printf("退出游戏!\n");
			break;
		default:
			printf("选择有误,请重新选择!\n");
			break;

		}


	} while (input);

	return 0;
}
           

这个游戏的界面的选择设计好之后,我们要设计扫雷的实现,这次给大家展示9*9版的简易扫雷。

c语言实现简易版扫雷

这是个9*9的一个棋盘,我们可以很容易想到将其抽象成一个二维数组来实现,我们来分析这个游戏,玩家在选择一个位置,如果这个位置是雷,那么就会显示”你被雷炸死了“, 如果不是雷,你选择的位置将会显示一个数字,这个数字代表了你所选择的位置的周围8个位置有几个雷,就这样一直排雷直到到最后你将所有不是雷的地方找出来,你就获胜了。游戏的大概就是这样的逻辑,那么我们怎么样去实现呢?

首先是棋盘的设计,为了让逻辑更清晰,我们可以设计两个相同的二维数组,其中一个数组来初始化棋盘将雷布置好,另一个数组中的相同位置存放排除雷的信息。接下来就是创建两个二维数组,那么这两个数组应该创建多大呢?(注意:我们可以想到在遍历最外层的位置时,如果我们设计的是9*9的数组,那么会出现数组越界的情况,这是不行的,那我们可以在9*9的基础上在外围加上一圈,这些位置在初始化时候不防雷,那么问题就解决了)

接下来就是创建二维数组

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


char mine[ROWS][COLS] = { 0 };//存放雷的信息
char show[ROWS][COLS] = { 0 };//存放排出的雷的信息
           

虽然我们设计了11*11的数组,但是我们在使用时候还是用到它的9*9的位置,为了方便,我定义了这些宏。

数组创建完成后就是对它初始化,设计函数InItBoard()对两个二维数组初始化,将存放雷的数组初始化全为‘0’,存放排雷信息的数组初始化为‘*’;

char mine[ROWS][COLS] = { 0 };//存放雷的信息
char show[ROWS][COLS] = { 0 };//存放排出的雷的信息
	//初始化棋盘
InItBoard(mine,ROWS,COLS,'0');
InItBoard(show, ROWS, COLS,'*');
void InItBoard(char board[ROWS][COLS], int rows, int cols,char set) //函数的设计
{
	int i = 0;
	for (i = 0; i < rows; i++)
	{
		int j = 0;
		for (j = 0; j < cols; j++)
		{
			board[i][j] =set;
		}
	}

}
           

接下来是实现打印棋盘的功能,设计函数DisplayBoard()这个函数要打印棋盘的行标和列标,如下

void DisplayBoard(char board[ROWS][COLS], int row, int col)
{

	int i = 0;
	printf("  ");
	for (i = 1; i <= 9; i++)
	{
		printf("%d ", i);
	}
	printf("\n");

	for (i = 1; i <= row; i++)
	{
		int j = 0;
		printf("%d ", i);
		for (j = 1; j <= col; j++)
		{
			printf("%c ", board[i][j]);
		}
		printf("\n");
	}
	printf("-------------------------------\n");

}
           

接下来就是存放雷。这里我们设计一个函数SetMine()那么这个雷的位置信息应该是随机的,所以我们想到了c语言中生成随机值的方法,生成的随机值还要让它在1到9的范围内,可以对生成的随机值进行%9的操作,这样生成的数是在范围内的了。需要注意的是:在存放雷的时候要判断所放位置是否已经是雷,如果不是,在存放雷。代码如下:

srand((unsigned int)time(NULL));//在main函数中调用一次即可
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] != '1')
		{
			board[x][y] = '1';
			count--;
		}

	}

           

雷放置好后,就是进行扫雷的步骤了。设计函数FindMine(),要实现的功能有,提示玩家输入坐标,进行坐标的判断,如果是雷,显示”你被炸死了“,如果不是,要计算它周围的雷数,在放进对应的位置,并将棋盘信息打印出来,一直重复,直到所有的不是雷的位置被找出来。

这个位置是需要注意的地方,GetMine函数返回值是整型,而数组的类型是字符型,那么怎么将整型数字转换成字符型呢,很简单,只需将字符n-字符0就是对应的n值,在将这个值赋值给数组的时候,要将其转成字符n,只要将这个n加上‘0’,就会转换成对应得字符型,我们可以看下面的ASCII表格 

c语言实现简易版扫雷

接下来实现得展开功能,如果玩家所选择得位置得周围都没有雷就会将周围得地方全部展开,以此类推,这里我们用递归来实现此功能,代码如下:

void OpenMine(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
{
	int count = 0;
	count = GetMine(mine, x, y);
	if (count == 0)
	{
		
		show[x][y] = ' ';
		if (x - 1 > 0 && y - 1 > 0 && show[x - 1][y - 1] == '*')
			OpenMine(mine, show, x - 1, y - 1);
		if (x - 1 > 0 && y > 0 && show[x - 1][y] == '*')
			OpenMine(mine, show, x - 1, y);
		if (x - 1 > 0 && y + 1 > 0 && show[x - 1][y + 1] == '*')
			OpenMine(mine, show, x - 1, y + 1);
		if (x > 0 && y - 1 > 0 && show[x][y - 1] == '*')
			OpenMine(mine, show, x, y - 1);
		if (x > 0 && y + 1 > 0 && show[x][y + 1] == '*')
			OpenMine(mine, show, x, y + 1);
		if (x + 1 > 0 && y - 1 > 0 && show[x + 1][y - 1] == '*')
			OpenMine(mine, show, x + 1, y - 1);
		if (x + 1 > 0 && y > 0 && show[x + 1][y] == '*')
			OpenMine(mine, show, x + 1, y);
		if (x + 1 > 0 && y + 1 > 0 && show[x + 1][y + 1] == '*')
			OpenMine(mine, show, x + 1, y + 1);
	}
	else
	{
		show[x][y] = count + '0';
	}


}
           

接下来,设计了一个函数来计算此时棋盘上没有展开的位置的数,如果这个数量等于雷数,那么玩家获胜。

int Count(char show[ROWS][COLS])
{
	int count = 0;
	for (int i = 1; i <= ROW; i++)
	{
		for (int j = 1; j <= COL; j++)
		{
			if (show[i][j] == '*')
			{
				count++;
			}
		}
	}
	return count;

}
           

 整个功能基本实现,我们可以看一下效果

game2.h

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
#define EASY_COUNT 3
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 board[ROWS][COLS] ,int row, int col);//设置雷
void FindMine(char mine[ROWS][COLS],char show[ROWS][COLS], int row, int col);//排查雷
           

game2.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"game2.h"

void InItBoard(char board[ROWS][COLS], int rows, int cols,char set)
{
	int i = 0;
	for (i = 0; i < rows; i++)
	{
		int j = 0;
		for (j = 0; j < cols; j++)
		{
			board[i][j] =set;
		}
	}

}
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{

	int i = 0;
	printf("  ");
	for (i = 1; i <= 9; i++)
	{
		printf("%d ", i);
	}
	printf("\n");

	for (i = 1; i <= row; i++)
	{
		int j = 0;
		printf("%d ", i);
		for (j = 1; j <= col; j++)
		{
			printf("%c ", board[i][j]);
		}
		printf("\n");
	}
	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] != '1')
		{
			board[x][y] = '1';
			count--;
		}

	}



}
int GetMine(char mine[ROWS][COLS], int x, int y)
{

	return (mine[x - 1][y] + mine[x - 1][y - 1] + mine[x][y - 1] + mine[x + 1][y - 1] + mine[x + 1][y] + mine[x + 1][y + 1] + mine[x - 1][y + 1] + mine[x][y + 1] - 8 * '0');

}
void OpenMine(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
{
	int count = 0;
	count = GetMine(mine, x, y);
	if (count == 0)
	{
		
		show[x][y] = ' ';
		if (x - 1 > 0 && y - 1 > 0 && show[x - 1][y - 1] == '*')
			OpenMine(mine, show, x - 1, y - 1);
		if (x - 1 > 0 && y > 0 && show[x - 1][y] == '*')
			OpenMine(mine, show, x - 1, y);
		if (x - 1 > 0 && y + 1 > 0 && show[x - 1][y + 1] == '*')
			OpenMine(mine, show, x - 1, y + 1);
		if (x > 0 && y - 1 > 0 && show[x][y - 1] == '*')
			OpenMine(mine, show, x, y - 1);
		if (x > 0 && y + 1 > 0 && show[x][y + 1] == '*')
			OpenMine(mine, show, x, y + 1);
		if (x + 1 > 0 && y - 1 > 0 && show[x + 1][y - 1] == '*')
			OpenMine(mine, show, x + 1, y - 1);
		if (x + 1 > 0 && y > 0 && show[x + 1][y] == '*')
			OpenMine(mine, show, x + 1, y);
		if (x + 1 > 0 && y + 1 > 0 && show[x + 1][y + 1] == '*')
			OpenMine(mine, show, x + 1, y + 1);
	}
	else
	{
		show[x][y] = count + '0';
	}


}
int Count(char show[ROWS][COLS])
{
	int count = 0;
	for (int i = 1; i <= ROW; i++)
	{
		for (int j = 1; j <= COL; j++)
		{
			if (show[i][j] == '*')
			{
				count++;
			}
		}
	}
	return count;

}
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
	int x = 0;
	int y = 0;
	int win = Count(show);
	while (win > EASY_COUNT)
	{
		printf("请输入你要排查的坐标:\n");
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			if (mine[x][y] == '1')
			{
				printf("你被炸死了!\n");
				DisplayBoard(mine, ROW, COL);
				break;
			}
			else
			{
				if (show[x][y] == '*')
				{
					OpenMine(mine, show, x, y);
					DisplayBoard(show, ROW, COL);
					win=Count(show);
				
				}
			}
		}
		else
		{
			printf("坐标非法,请重新输入:\n");
		}
	}
	if (win == EASY_COUNT)
	{
		printf("恭喜你,成功通关!\n");
		DisplayBoard(mine, ROW, COL);
	}
}
           

test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"game2.h"
void munu()
{

	printf("*******************\n");
	printf("**** 1.play *******\n");
	printf("**** 0.exit *******\n");
	printf("*******************\n");

}

void game()
{
	char mine[ROWS][COLS] = { 0 };//存放雷的信息
	char show[ROWS][COLS] = { 0 };//存放排出的雷的信息
	//初始化棋盘
	InItBoard(mine,ROWS,COLS,'0');
	InItBoard(show, ROWS, COLS,'*');
	/*DisplayBoard(mine, ROW, COL);*/
	DisplayBoard(show, ROW, COL);//展示玩家所看到的存放雷信息的棋盘
	SetMine(mine,ROW,COL);//设置雷
	/*DisplayBoard(mine, ROW, COL);*/
	FindMine(mine,show,ROW,COL);//扫雷


}

int main()
{
	int input = 0;
	srand((unsigned int)time(NULL));
	do
	{
		munu();
		printf("请选择:\n");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			printf("扫雷游戏开始!\n");
			game();
			break;
		case 0:
			printf("退出游戏!\n");
			break;
		default:
			printf("选择有误,请重新选择!\n");
			break;

		}


	} while (input);

	return 0;
}
           

 运行效果,为了方便测试,这里我设置了3个雷

c语言实现简易版扫雷

由于作者还是初学,有些其他得功能还没有实现,在未来我会将功能及文章继续改进,感谢大家支持! 

继续阅读