Minesweeper game in C language

content

1. Overview of Mine Sweeping Models

2. Text--->Logical Analysis

        2.1 Generate menu

        2.2 Create a chessboard

        2.3 Initialize the board

        2.4 Printing the chessboard

        2.5 Mine placement

        2.6 Troubleshoot mines

3. Total code

      3.1 test.c file

      3.2 game.c file

      3.3 game.h file


1. Overview of Mine Sweeping Models

This picture is a mine-sweeping template that you can find on the web page, and in C language, we can also write simple code to achieve the above picture. as the picture shows:

 How to implement this interface, I will give you a detailed explanation later:

2. Text--->Logical Analysis

From the above simple minesweeper style, we can see that first, a directory must be generated to tell the player to play or exit, and secondly, when the player starts to play the game, a chessboard will be displayed in front of the player. At this time, a chessboard needs to be created. And assign characters to it to initialize, then we need to set the corresponding number of mines inside the chessboard, and finally check whether the coordinates are mines one by one through the user's input of coordinate values.

In order to make the internal code of the program Minesweeper look organized, we need to set up corresponding files to manage our code and make it look more neat. as the picture shows:

First: use the test.c file to test the logic of the game. Second: use the game.c file to implement the logic of the game. Third: use the game.h file to declare the game implementation function. In the following content, we will continue to use these three files

        2.1 Generate menu

 The most important step is to present a menu in front of the player, telling the player whether to choose to play the game or quit the game, you need to implement such code in the test.c file:

#include"game.h"  //引用总头文件,此做法简洁明了
void menu()
{
	printf("****************************************\n");
	printf("*******           1.play         *******\n");
	printf("*******           0.exit         *******\n");
	printf("****************************************\n");
}
void test()
{
	
	int input = 0;
	do
	{
		menu();
		printf("请输入:>");
		scanf("%d", &input);
		switch (input)  //用switch语句来处理玩家输入的信息
		{
		case 1:
			game();  //当玩家输入1时进入游戏,此时需要调用game()函数,后续会讲到
			break;
		case 0:
			printf("退出游戏\n");
			break;
		default:
			printf("非法输入,请重新输入!\n");
			break;
		}
			
	} while (input);
}
int main()
{
	test();
	return 0;
}

Before implementing this code content, there is an important premise: refer to the header file. In the first line of this code, #include"game.h" refers to the header file of game.h. In the game.h file, you need to complete such code:

When the code of the above two files is completed, let's run it:

 

 The menu was successfully generated.

        2.2 Create a chessboard

Before writing the code, let's analyze what the chessboard really looks like

In theory, the real chessboard should be all the content with * in it, which can be achieved by creating a two-dimensional array of 9*9, but we assume a situation that when the player checks the * in the upper left corner, there will be out-of-bounds Access, because when checking whether there is a mine at the location, and there are several mines, we count the 8 adjacent elements around the coordinate. When visiting the top left corner*, there are only three elements around that can be accessed, and the remaining 5 elements are available for access. In order to avoid this, when creating an array, 11*11 should be created to avoid the situation of out-of-bounds access. As shown in the following code:

#include"game.h"

void game()
{
	//创建数组
	char mine[ROWS][COLS] = { 0 };   //存放布置好的雷的信息
	char show[ROWS][COLS] = { 0 };   //存放排查出的雷的信息
//此时此刻ROWS代表行数,COLS代表列数。
//ROWS和COLS并未直接赋值是为了方便以后改变棋盘大小更为便捷



}

Careful students here may find that I have created two arrays here, the mine array and the show array. In fact, it is very necessary to create an array in this way, because after the entire code is completed, when we run, the chessboard that really appears in front of the player should be the show array, the mine array is just for laying mines later, and the show array is us Where the player is really going to demining. 

Of course, this code is not enough, because ROWS and COLS have not been defined. At this point, we need to define it in the game.h file to achieve this: as shown in the code below:

        2.3 Initialize the board

After the chessboard is created with a two-dimensional array, we need to initialize the chessboard. The following code needs to be completed in the test.c file:

#include"game.h"

void game()
{
	//创建数组
	char mine[ROWS][COLS] = { 0 };   //存放布置好的雷的信息
	char show[ROWS][COLS] = { 0 };   //存放排查出的雷的信息

	//初始化数组mine全为‘0’
	InitBoard(mine, ROWS, COLS, '0');
	//初始化数组show全为‘*’
	InitBoard(show, ROWS, COLS, '*');
}

In order to implement the entire process of the InitBoard function, we need to complete the following code in the game.c file:

#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循环来初始化棋盘每一个元素为相应的字符

Before implementing the initialization of the board with the InitBoard function, this function needs to be declared:

        2.4 Printing the chessboard

When we initialize the content on the chessboard, we need to print the chessboard to detect what kind of situation it is. At this moment, we need to call the DisplayBoard function to print the chessboard. Then you need to complete the following code in the test.c file:



#define _CRT_SECURE_NO_WARNINGS 1
#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 };   //存放排查出的雷的信息

	//初始化数组mine全为‘0’
	InitBoard(mine, ROWS, COLS, '0');
	//初始化数组show全为‘*’
	InitBoard(show, ROWS, COLS, '*');
	//打印棋盘
	DisplayBoard(mine, ROW, COL);
	DisplayBoard(show, ROW, COL);
}

In the game.c file, the entire process of printing the chessboard with the DisplayBoard function is implemented. As shown in the following code:

void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
	int i = 0;
	int j = 0;

	//列号数字的打印
	for (i = 0; i <= col; i++)
	{
		printf("%d ", i);
	}
	printf("\n");
	for (i = 1; i <= row; i++)
	{
		printf("%d ", i);  //打印行号
		for (j = 1; j <= col; j++)
		{
			printf("%c ", board[i][j]);  //打印棋盘
		}
		printf("\n");
	}
}

In order to make it easier for players to know the coordinates of which rows and columns they want to check when they see the chessboard, we can output the row number and column number in front of the player. This is also done using a for loop statement. After that, the board still doesn't work properly because we haven't declared the DisplayBoard function in the game.h header file. We can do it like this:

 When the above operations are completed, we can run the code normally to observe the situation of the chessboard: we will print both the show array and the mine array to see:

        2.5 Mine placement

When we print the chessboard, we need to install mines on the mine array. At this time, we need the computer to automatically generate a certain number of mines and distribute them in random positions of the coordinates. We need to use an important function srand((unsigned int )time(NULL)); and correspond the mines on the mine array to the show array, at this time, the printing of the mine array can be blocked, and only the printing of the show array is generated for the player to clear the mines.

Then on the test.c file, we need to complete this code:

#include"game.h"

void game()
{
	//创建数组
	char mine[ROWS][COLS] = { 0 };   //存放布置好的雷的信息
	char show[ROWS][COLS] = { 0 };   //存放排查出的雷的信息

	//初始化数组mine全为‘0’
	InitBoard(mine, ROWS, COLS, '0');
	//初始化数组show全为‘*’
	InitBoard(show, ROWS, COLS, '*');
	//打印棋盘
	//DisplayBoard(mine, ROW, COL);
	//DisplayBoard(show, ROW, COL);

	//布置雷
	SetMine(mine, ROW, COL);

	DisplayBoard(show, ROW, COL);

	
}


void test()
{
	srand((unsigned int)time(NULL));
	
}

Similarly, we also need to use the SetMine function on the game.c file to implement the whole process of arranging mines: the code is as follows:

void SetMine(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] == '0')
		{
			mine[x][y] = '1';  //随机自动生成雷
			count--;
		}
	}

}

At the same time, you also need to declare the function in the game.h file:

 After completing the above operations, let's run it and see:

 You can see that the mine array is below, and the show array is above. The mine array has automatically generated mine and is represented by the character 1.

        2.6 Troubleshoot mines

The last step is to check the mine. When the player enters the coordinates he wants to check, the system will determine whether the changed position is a mine, and use an if statement to achieve it. If so, the challenge will fail. Several mines are displayed, and the output is displayed on the screen for the player's reference. When all the mines have been checked, the player's mine clearance is successful.

In the test.c file, we need to complete the following code:

#include"game.h"
void game()
{
	//创建数组
	char mine[ROWS][COLS] = { 0 };   //存放布置好的雷的信息
	char show[ROWS][COLS] = { 0 };   //存放排查出的雷的信息

	//初始化数组mine全为‘0’
	InitBoard(mine, ROWS, COLS, '0');
	//初始化数组show全为‘*’
	InitBoard(show, ROWS, COLS, '*');
	//打印棋盘
	//DisplayBoard(mine, ROW, COL);
	//DisplayBoard(show, ROW, COL);

	//布置雷
	SetMine(mine, ROW, COL);
	//DisplayBoard(show, ROW, COL);
	DisplayBoard(show, ROW, COL);


	//排雷
	FindMine(mine,show, ROW, COL);


}

We need to implement the whole process of checking mine in the game.c file:

#include"game.h"
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 - 1] +
		mine[x + 1][y] +
		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)
		{
			if (mine[x][y] == '1')
			{
				printf("很遗憾你被炸死了\n");
				DisplayBoard(mine, row, col);
				break;

			}
			else
			{
				//计算x,y坐标周围有几个雷
				int n = get_mine_count(mine, x, y);
				show[x][y] = n + '0';
				DisplayBoard(show, row, col);
				win++;
			}
		}
		else
		{
			printf("输入坐标非法,请重新输入\n");
		}
	}
	if (win == row * col - EASY_COUNT)
	{
		printf("恭喜你,排雷成功\n");
		DisplayBoard(mine, row, col);

	}
	
	
}

Again, we need to make a function declaration in the game.h file

When the entire code has run, let's take a look:

3. Total code

      3.1 test.c file

#define _CRT_SECURE_NO_WARNINGS 1
#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 };   //存放排查出的雷的信息

	//初始化数组mine全为‘0’
	InitBoard(mine, ROWS, COLS, '0');
	//初始化数组show全为‘*’
	InitBoard(show, ROWS, COLS, '*');
	//打印棋盘
	//DisplayBoard(mine, ROW, COL);
	//DisplayBoard(show, ROW, COL);

	//布置雷
	SetMine(mine, ROW, COL);
	DisplayBoard(mine, ROW, COL);
	DisplayBoard(show, ROW, COL);


	//排雷
	FindMine(mine,show, ROW, COL);


}
void test()
{
	srand((unsigned int)time(NULL));
	int input = 0;
	do
	{
		menu();
		printf("请输入:>");
		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;
}

      3.2 game.c file

#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;   //初始化对应的数组
		}
	}
}

void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
	int i = 0;
	int j = 0;

	//列号数字的打印
	for (i = 0; i <= col; i++)
	{
		printf("%d ", i);
	}
	printf("\n");
	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 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] == '0')
		{
			mine[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 - 1] +
		mine[x + 1][y] +
		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)
		{
			if (mine[x][y] == '1')
			{
				printf("很遗憾你被炸死了\n");
				DisplayBoard(mine, row, col);
				break;

			}
			else
			{
				//计算x,y坐标周围有几个雷
				int n = get_mine_count(mine, x, y);
				show[x][y] = n + '0';
				DisplayBoard(show, row, col);
				win++;
			}
		}
		else
		{
			printf("输入坐标非法,请重新输入\n");
		}
	}
	if (win == row * col - EASY_COUNT)
	{
		printf("恭喜你,排雷成功\n");
		DisplayBoard(mine, row, col);

	}
	
	
}

      3.3 game.h file

#pragma once
//头文件的包含
#include<stdio.h>
#include<time.h>
#include<stdlib.h>

//符号的声明
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
#define EASY_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 FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);

Guess you like

Origin blog.csdn.net/bit_zyx/article/details/121259261