【C语言】扫雷游戏(超详细)

扫雷

  • 前言
  • 一、扫雷整体框架分析
    • 1.整体框架搭建
    • 2.菜单实现
    • 3.游戏实现
      • 1.棋盘初始化
      • 2.棋盘打印
      • 3.布置雷
      • 4.扫雷
  • 二、源代码展示
    • 1.test.c
    • 2.game.c
    • 3.game.h


前言

之前基于二维数组写过一个三子棋的小游戏,现在又可以完成一个小游戏——扫雷(9阶)。
大概思路如下:

1.首先创建一个菜单选项,选择 ‘1’ 进入游戏,选择 ‘0’ 退出游戏;
2.初始化两个相同的棋盘,一个为mine棋盘,一个为show棋盘(两棋盘同为十一行十一列);mine 棋盘是有关雷的棋盘,有雷的位置初始化为 ‘1’,没有雷的位置初始化为 ‘0’,玩家不可见;show棋盘属于打印棋盘,最初全部初始化为 ‘*’,在排雷的过程中打印出来的show棋盘上的数字表示该点周围雷的总数。
3.对mine棋盘布置雷,通过 srand 函数获取随机数,并使用(x = rand() % row + 1 ; y = rand() % col + 1)生成九个雷布置的位置,然后将其布置在mine棋盘的中间九行九列上(不是初始化了十一行十一列的棋盘吗,而此时又选择九行九列是因为在排查雷的时候对于棋盘边界有更好的计算,要不然存在越界访问的可能)
4.布置雷完成后就开始扫雷阶段,每当选择一个安全的点后就会在mine棋盘上对该点的周围八个位置统计雷的总数,并将雷的总数赋值到show棋盘与mine棋盘对应的位置上,并对玩家进行展示,若踩中雷则会将第一个棋盘雷的分布给玩家展示。

一、扫雷整体框架分析

在进入主函数内部后,首先执行菜单打印,根据菜单选项选择是玩游戏还是退出,在选择玩游戏选项后,第一步先初始化两个棋盘,第二步对棋盘布置雷,第三步就要开始排雷,当然中间还有打印棋盘的功能。

1.整体框架搭建

int main()
{
	system("color 5E");
	int input = 0;
	srand((unsigned int)time(NULL));
	do
	{
		menu();
		printf("\t\t\t请选择:");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			printf("\n\n\t\t\t退出成功!\n");
			break;
		default:
			printf("\n\n\t\t\t选择错误,请重新输入!\n");
			Sleep(2000);
			system("cls");
		}

	} while (input);
	return 0;
}

这里边包含一个 srand 函数和一个time时间戳函数,将time函数的返回值转化为unsigned int类型并通过srand函数生成一个随机数以备后续的布置雷所用。

2.菜单实现

void menu()
{
	printf("\n\n\t\t\t-------------欢迎使用------------\n\n");
	printf("\t\t\t☆☆           扫雷          ☆☆\n\n");
	printf("\t\t\t☆☆          1.play         ☆☆\n\n");
	printf("\t\t\t☆☆          0.exit         ☆☆\n\n");
	printf("\t\t\t---------------------------------\n\n");
}

根据菜单的提示玩家可以进行选择是继续玩游戏还是退出游戏,当选择1后便会进入玩游戏界面。

3.游戏实现

#define ROWS 11  //初始化的行列
#define COLS 11
#define ROW 9  //打印的行列
#define COL 9
#define easy_count 9 //雷的数量

1.棋盘初始化

首先得初始化两个棋盘,mine棋盘内部布置雷的分布,玩家不可见,mine棋盘会将非雷处的周围八处有多少个雷进行统计再赋值到show棋盘中给玩家进行打印,玩家可见。

char mine[ROWS][COLS] = { 0 };
char show[ROWS][COLS] = { 0 };
Init_board(mine, ROWS, COLS, '0');
Init_board(show, ROWS, COLS, '*');
void Init_board(char board[ROWS][ROWS], int rows, int cols, char s)
{
	for (int i = 0; i < rows; i++)
	{
		for (int j = 0; j < cols; j++)
		{
			board[i][j] = s;
		}
	}
}

此函数对十一行十一列的棋盘通过参数 ‘s’ 进行初始化,对第一个棋盘全部初始化为 0,对第二个棋盘全部初始化为 *。

2.棋盘打印

Display_board(show, ROW, COL);
void Display_board(char board[ROWS][COLS], int row, int col)
{
	printf("\t\t-------------------------------------\n\n\t\t\t");
	for (int i = 0; i <= row; i++)
	{
		printf("%d ", i);
	}
	printf("\n");
	for (int i = 1; i <= row; i++)
	{
		printf("\t\t\t");
		printf("%d ", i);
		for (int j = 1; j <= col; j++)
		{
			printf("%c ", board[i][j]);
		}
		printf("\n");
	}
	printf("\n\t\t-------------------------------------\n\n");
}

此函数是将十一行十一列棋盘的中间九行九列打印出来。

3.布置雷

Set_mine(mine, ROW, COL);
void Set_mine(char mine[ROWS][COLS], int row, int col)
{
	int count = easy_count;
	while (count)
	{
		int x = rand() % row + 1;//随机生成布置雷的位置
		int y = rand() % col + 1; 
		if (mine[x][y] != '1')
		{
			mine[x][y] = '1';
			count --;
		}
		
	}
}

此函数只针对于mine棋盘,对整个棋盘布置9个雷。

4.扫雷

Find_mine(mine, show, ROW, COL);
//获取mine棋盘中非雷处的周围八处有多少个雷
int get_mine_num(char mine[ROWS][COLS],int x,int y)
{
	return mine[x - 1][y - 1]
		+ mine[x - 1][y]
		+ mine[x - 1][y + 1]
		+ mine[x][y - 1]
		+ mine[x][y + 1]
		+ mine[x + 1][y - 1]
		+ mine[x + 1][y]
		+ mine[x + 1][y + 1] - 8 * '0';
}
//排雷
void Find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
	Display_board(show, ROW, COL);
	int x, y = 0;
	int win = 0;
	while (win < (row*col-easy_count))//已获取非雷处的数量
	{
		printf("\n\t\t\t请输入选择的位置:");
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			if (show[x][y] == '*')//表示此处是否已经被排过 *代表还未排过
			{
				if (mine[x][y] != '1')//判断此处是否是雷 1代表雷
				{
					int num = get_mine_num(mine, x, y);
					show[x][y] = num + '0';
					win++;
				}
				else //踩中雷
				{
					system("cls");
					printf("\n\n\t\t\t--- Game Over! ---\n");
					Sleep(1000);
					Display_board(mine, ROW, COL);
					break;
				}
			}
			else
			{
				printf("\n\n\t\t\t该坐标已被排查过,请重新选择!\n");
				Sleep(1000);
			}
		}
		else
		{
			printf("\n\n\t\t\t输入错误,请重新选择!\n");
			Sleep(1000);
		}
		system("cls");
		Display_board(show, ROW, COL);
	}
	if (win == (row*col - easy_count))//当所有的非雷处都被您找出
	{
		printf("\t\t\t恭喜您,排雷成功!\n");
	}
	printf("\t\t\t3秒后自动退出至主页面\n");
	Sleep(3000);
	system("cls");
}

二、源代码展示

1.test.c

#include "game.h"

void menu()
{
	printf("\n\n\t\t\t-------------欢迎使用------------\n\n");
	printf("\t\t\t☆☆           扫雷          ☆☆\n\n");
	printf("\t\t\t☆☆          1.play         ☆☆\n\n");
	printf("\t\t\t☆☆          0.exit         ☆☆\n\n");
	printf("\t\t\t---------------------------------\n\n");
}

void game()
{
	//初始化棋盘
	char mine[ROWS][COLS] = { 0 };
	char show[ROWS][COLS] = { 0 };
	//初始化棋盘
	Init_board(mine, ROWS, COLS, '0');
	Init_board(show, ROWS, COLS, '*');
	printf("\n\n\t\t\t2秒后进入游戏界面!\n");
	Sleep(2000);
	system("cls");
	//打印棋盘
	//Display_board(mine, ROW, COL);
	//Display_board(show, ROW, COL);
	//布置雷
	Set_mine(mine, ROW, COL);
	//Display_board(mine, ROW, COL);
	//排查雷
	Find_mine(mine, show, ROW, COL);
}



int main()
{
	system("color 5E");
	int input = 0;
	srand((unsigned int)time(NULL));
	do
	{
		menu();
		printf("\t\t\t请选择:");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			printf("\n\n\t\t\t退出成功!\n");
			break;
		default:
			printf("\n\n\t\t\t选择错误,请重新输入!\n");
			Sleep(2000);
			system("cls");
		}

	} while (input);
	return 0;
}

2.game.c

#include "game.h"


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


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


void Set_mine(char mine[ROWS][COLS], int row, int col)
{
	int count = easy_count;
	while (count)
	{
		int x = rand() % row + 1;
		int y = rand() % col + 1; 
		if (mine[x][y] != '1')
		{
			mine[x][y] = '1';
			count --;
		}
		
	}
}

int get_mine_num(char mine[ROWS][COLS],int x,int y)
{
	return mine[x - 1][y - 1]
		+ mine[x - 1][y]
		+ mine[x - 1][y + 1]
		+ mine[x][y - 1]
		+ mine[x][y + 1]
		+ mine[x + 1][y - 1]
		+ mine[x + 1][y]
		+ mine[x + 1][y + 1] - 8 * '0';
}
void Find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
	Display_board(show, ROW, COL);
	int x, y = 0;
	int win = 0;
	while (win < (row*col-easy_count))
	{
		printf("\n\t\t\t请输入选择的位置:");
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			if (show[x][y] == '*')
			{
				if (mine[x][y] != '1')
				{
					int num = get_mine_num(mine, x, y);
					show[x][y] = num + '0';
					//Display_board(show, ROW, COL);
					win++;
				}
				else
				{
					system("cls");
					printf("\n\n\t\t\t--- Game Over! ---\n");
					Sleep(1000);
					Display_board(mine, ROW, COL);
					break;
				}
			}
			else
			{
				printf("\n\n\t\t\t该坐标已被排查过,请重新选择!\n");
				Sleep(1000);
			}
		}
		else
		{
			printf("\n\n\t\t\t输入错误,请重新选择!\n");
			Sleep(1000);
		}
		system("cls");
		Display_board(show, ROW, COL);
	}
	if (win == (row*col - easy_count))
	{
		printf("\t\t\t恭喜您,排雷成功!\n");
	}
	printf("\t\t\t3秒后自动退出至主页面\n");
	Sleep(3000);
	system("cls");
}

3.game.h

#include 
#include 
#include 
#include 

#define ROWS 11
#define COLS 11
#define ROW 9
#define COL 9
#define easy_count 9


void Init_board(char board[ROWS][ROWS], int rows, int cols, char s);

void Display_board(char board[ROWS][COLS], int row, int col);

void Set_mine(char mine[ROWS][COLS], int row, int col);

void Find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);

你可能感兴趣的:(C语言,c语言,游戏,算法)