C语言实现简单扫雷游戏

基本思路:

  1. 创建一个布置雷的数组,和一个展示雷附近雷数的数组
  2. 随机数方式布置雷

  3. 输入数组坐标来进行扫雷,是雷则游戏结束,不是则在这个坐标显示附近雷的个数

  4. 循环直至游戏结

关键:

  1. 扫雷为9*9的方阵,但是要将实际雷的数组定义为11*11的二维数组,以便对一个坐标附近雷数进行计算
  2. 布雷、扫雷和打印都只是对11*11中间的那9*9数组进行操作

首先是先创建game.c,test.c两个源文件和自定义头文件game.h,游戏函数写在game.c里,在test.c中实现整体游戏逻辑


主体函数如下

数组初始化

传入arr字符数组,行列分别为rows和cols,初始化值为‘set’

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

打印

这里打印的是整体游戏界面,包含数组的参考坐标和扫雷区:C语言实现简单扫雷游戏

 传入的数组为11*11的数组,此函数只打印其中间的9*9元素

void display(char arr[ROWS][COLS], int row, int col)  
{
	printf("------SEEKMINE------\n");
	for (int i = 0; i <= row; i++)     //打印参考列
	{
		printf("%d ", i);
	}
	printf("\n");
	for (int i = 1; i <= row; i++)       //打印扫雷界面
	{
		printf("%d ", i);             //打印参考行
		for (int j = 1; j <= col; j++)   
		{
			printf("%c ", arr[i][j]);  //打印11*11数组中间的9*9数组
		}
		printf("\n");
	} 
	printf("------SEEKMINE------\n");
}

随机布雷

注意在使用rand函数前要在主函数中调用srand函数

这里传入的参数是mine[ROWS][COLS]数组,一个定义为11*11的字符数组,布雷函数将雷随机布置在此数组中间的9*9元素中

//设置n个雷
void set_mine(char arr[ROWS][COLS], int row, int col,int n)  //传入为11*11的数组,但是雷要赋给其中间的9*9数组
{
	for (int i = 0; i < n; i++)  //循环次数为n
	{
		int x = 0, y = 0;
		do  
		{
			x = rand() % row;  //生成0-8的随机数
			y = rand() % col;
		} while (arr[x + 1][y + 1] != '0');  //判断此坐标是否有雷,有则再次随机取坐标
		arr[x+1][y+1] = '1';  //将雷赋值为‘1’
	}
}

判断周围雷数

因为在初始化时mine数组中的值为‘0’,布雷时雷的值为‘1’,所以‘1’-‘0’的ASCII码值为1,所以可以将传入的数组坐标其周围8个数组的元素读出来,再相加,减去8*‘0’,即可得到此坐标周围8个坐标中的雷数,再将此数作为返回值返回

这里就体现出了将雷区数组设置为11*11的好处了,再其中间的9*9数组中,无论哪一个元素的周围都会有8个元素,都可以实现此函数的判断且不会越界

//判断周围雷数
int get_mine(char arr[ROWS][COLS],int x,int y)
{
	return arr[x - 1][y - 1] +   //读取周围8个格子中的数组元素,减‘0’得到雷的个数
		arr[x - 1][y] + 
		arr[x - 1][y + 1] + 
		arr[x][y - 1] +
		arr[x][y + 1] + 
		arr[x + 1][y - 1] +
		arr[x + 1][y] + 
		arr[x + 1][y + 1] - 8 * '0';
}

扫雷

此函数传入了两个数组,一个是mine数组,一个时show数组,mine数组里储存了已经布置好的雷的信息,show是用于打印展示的数组,输入坐标,判断mine数组在此坐标没有雷后,调用get_mine函数得到附近雷数,将此值赋值给show数组

int find_mine(char arr1[ROWS][COLS],char arr2[ROWS][COLS],int row,int col)
{
	int x = 0, y = 0;
	int count = 0;
	while (count < row * col - EASYMINE)  //判断扫雷是否结束
	{
		printf("请输入扫雷坐标:");
		scanf("%d %d", &x, &y);  //x,y为1~9的数
		if (arr1[x][y] == '1')   //是雷
		{
			printf("你被炸死了\n");
			display(arr1, ROW, COL);
			return -1;
		}
		else if (arr1[x][y] == '0')        //不是雷
		{
			count++;                       //计数加一
			if (get_mine(arr1, x, y) > 0)  //如果附近雷数不为0
			{
				arr2[x][y] = '0' + get_mine(arr1, x, y);  //将附近雷数赋给show数组,因为数字的ASCII码值是递增的,所以+n就可以表示对应数字了
			}
			else arr2[x][y] = ' ';        //如果附近雷数为0,则赋值为空格
		}
		else
		{
			printf("错误,请重新输入:\n");
		}
		display(arr2, ROW, COL);
	}
	if (count == row * col - EASYMINE)
	{
		printf("扫雷成功\n");
	}
	return 0;
}

完整代码:

game.h

#define _CRT_SECURE_NO_WARNINGS 1

#define ROW 9
#define COL 9
#define ROWS 11
#define COLS 11
#define EASYMINE 10 //雷数

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

void init_game(char arr[ROWS][COLS], int row, int col, char set);
void display(char arr[ROWS][COLS], int row, int col);
void set_mine(char arr[ROWS][COLS], int row, int col, int n);
void show_mine(char arr[ROWS][COLS], int rows, int cols);
int find_mine(char arr1[ROWS][COLS], char arr2[ROWS][COLS], int row, int col);

game.c

#define _CRT_SECURE_NO_WARNINGS 1

#include"game.h"

//初始化
void init_game(char arr[ROWS][COLS], int rows, int cols, char set)  
{
	for (int i = 0; i < rows; i++)
	{
		for (int j = 0; j < cols; j++)
		{
			arr[i][j] = set;
		}
	}
}

//打印
void display(char arr[ROWS][COLS], int row, int col)  
{
	printf("------SEEKMINE------\n");
	for (int i = 0; i <= row; i++)     //打印参考列
	{
		printf("%d ", i);
	}
	printf("\n");
	for (int i = 1; i <= row; i++)       //打印扫雷界面
	{
		printf("%d ", i);             //打印参考行
		for (int j = 1; j <= col; j++)   
		{
			printf("%c ", arr[i][j]);  //打印11*11数组中间的9*9数组
		}
		printf("\n");
	} 
	printf("------SEEKMINE------\n");
}


//测试函数,用于检查雷是否布置成功
void show_mine(char arr[ROWS][COLS], int rows, int cols)
{
	for (int i = 0; i < rows; i++)
	{
		for (int j = 0; j < cols; j++)
		{
			printf("%c ", arr[i][j]);
		}
		printf("\n");
	}
}

//设置n个雷
void set_mine(char arr[ROWS][COLS], int row, int col,int n)  //传入为11*11的数组,但是雷要赋给其中间的9*9数组
{
	for (int i = 0; i < n; i++)  //循环次数为n
	{
		int x = 0, y = 0;
		do  
		{
			x = rand() % row;  //生成0-8的随机数
			y = rand() % col;
		} while (arr[x + 1][y + 1] != '0');  //判断此坐标是否有雷,有则再次随机取坐标
		arr[x+1][y+1] = '1';  //将雷赋值为‘1’
	}
}

//判断周围雷数
int get_mine(char arr[ROWS][COLS],int x,int y)
{
	return arr[x - 1][y - 1] +   //读取周围8个格子中的数组元素,减‘0’得到雷的个数
		arr[x - 1][y] + 
		arr[x - 1][y + 1] + 
		arr[x][y - 1] +
		arr[x][y + 1] + 
		arr[x + 1][y - 1] +
		arr[x + 1][y] + 
		arr[x + 1][y + 1] - 8 * '0';
}

//扫雷
int find_mine(char arr1[ROWS][COLS],char arr2[ROWS][COLS],int row,int col)
{
	int x = 0, y = 0;
	int count = 0;
	while (count < row * col - EASYMINE)  
	{
		printf("请输入扫雷坐标:");
		scanf("%d %d", &x, &y);  //x,y为1~9的数
		if (arr1[x][y] == '1')   //是雷
		{
			printf("你被炸死了\n");
			display(arr1, ROW, COL);
			return -1;
		}
		else if (arr1[x][y] == '0')        //不是雷
		{
			count++;                       //计数加一
			if (get_mine(arr1, x, y) > 0)  //如果附近雷数不为0
			{
				arr2[x][y] = '0' + get_mine(arr1, x, y);  //将附近雷数赋给show数组,因为数字的ASCII码值是递增的,所以+n就可以表示对应数字了
			}
			else arr2[x][y] = ' ';        //如果附近雷数为0,则赋值为空格
		}
		else
		{
			printf("错误,请重新输入:\n");
		}
		display(arr2, ROW, COL);
	}
	if (count == row * col - EASYMINE)
	{
		printf("扫雷成功\n");
	}
	return 0;
}

test.c

#define _CRT_SECURE_NO_WARNINGS 1

#include"game.h"

void menu()
{
	printf("**************************\n");
	printf("********    扫雷   *******\n");
	printf("**************************\n");
	printf("********   1.play  *******\n");
	printf("********   0.quit  *******\n");
	printf("**************************\n");

}
void game()
{
	char mine[ROWS][COLS] = { 0 };       //储存雷位置的数组,11*11
	init_game(mine, ROWS, COLS, '0');    //初始化数组为0
	char show[ROWS][COLS] = { 0 };       //储存显示附近雷个数的数组
	init_game(show, ROWS, COLS, '*');    //初始化数组为*

	set_mine(mine, ROW, COL, EASYMINE);  //设置雷数为EASYMINE的雷
	display(show, ROW, COL);             

	find_mine(mine, show, ROW, COL);      //开始扫雷
}
int main()
{
	int input = 0;
	srand((unsigned int)time(NULL));
	do
	{
		menu();
		scanf("%d", &input);
		switch (input)    //根据输入跳选
		{
		case 1:
			game();
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("错误,请重新输入:\n");
			break;
		}
	} while (input);
	return 0;
}

上一篇:c语言实现扫雷


下一篇:C语言----扫雷