Minesweeper (C language version)

content

1. Demand analysis

2. Program Architecture

3. Code implementation (sub-function presentation)

(1) Implementation of the main function code

analyze:

Exception handling:

(2) Implementation of the main function of the game

analyze:

(3) Implementation of the initialization function

analyze:

(4) Display the implementation of the function

analyze:

(5) Implementation of the mine-buried function

analyze:

(6) Implementation of mine sweeping function

analyze:

(7) Introduction of header files, function declarations, and improvement of difficulty

analyze:

4. Code implementation (sub-file presentation)

test.c code

game.h code

game.c code


1. Demand analysis

A simple mine-sweeping game is implemented through C language. Due to the limited level of the creator, a graphical interface has not been implemented in the game. At the same time, in a real mine-sweeping game, the function of successfully sweeping multiple coordinates by clicking on a location has not been implemented. The function is relatively simple. Please forgive me!

2. Program Architecture

The program is divided into two source files test.c, game.c and a header file game.h.

test.c: The main function interface is introduced.

game.c: Implementation of related functions of the game.

game.h: header file introduction, function declaration.

3. Code implementation (sub-function presentation)


(1) Implementation of the main function code

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;
		}
	} while (input);

}
int main()
{
	test();
	return 0;
}

analyze:

1. A random seed is introduced in the main function to generate random numbers to facilitate the generation of subsequent mines

2. After the menu is presented through the menu(), the interface is accessed through the switch. When the user enters 1, the game can be played, and when the user enters 0, the game is exited.

3. The overall implementation is achieved through the do while loop, but it is cleverly used to fill in the data entered by the user into the parentheses after the while, that is, when the user enters 0, the while condition judgment fails, and the game terminates.

Exception handling:

Although there is no default for exception handling in switch, when the user inputs data that is not 0, the loop will still automatically proceed. After inputting data that is not 0 or 1, the program will require the player to re-input, and will again Entering the loop is actually equivalent to alternative exception handling.

(2) Implementation of the main function of the game

void game()
{
	char mine[ROWS][COLS] = { 0 };//存取放置好雷的信息的雷盘
	char show[ROWS][COLS] = { 0 };//存取展示给用户的信息的雷盘
	Init_board(mine, ROWS, COLS, '0');//初始化雷盘
	Init_board(show, ROWS, COLS, '*');//初始化展示的雷盘
	Set_mine(mine, ROW, COL,EASY_COUNT);//埋雷
	Display_board(show, ROW, COL);//展示想要展示雷盘
	Find_mine(mine, show, ROWS, COLS);//排雷游戏开始
}

analyze:

1. Why build two thunder disks? The first mine disk is what we use to initialize mines, that is, to bury mines, and the second mine disk is used to display to the player, that is, to show where the player has cleared mines, and 3*3 centered on this position How many mines are in the grid, maybe you will ask, is a mine plate bad? Of course, there is no problem with one thunder disk, but two thunder disks can better handle subsequent operations, especially when we calculate how many mines there are in a 3*3 range centered on the grid we want to sweep, the first We initialize a mine disk to 1*11, so that we can better calculate how many mines there are around the location we want to sweep.

Let me show you two thunder disks:

 The thunder disk on the left is the thunder disk with the mine buried, and the thunder disk on the right is the thunder disk presented to the player.

2. For the first lightning disk (11*11) initialized, we initialize all of them to 0. In the subsequent process of burying the mine, assign the data of the position of the mine to 1. The lightning disk displayed by initialization is to The data of all the positions is initialized as the character '*', and later we assign it to the number of mines around the place where we platoon.

3. The display mine plate is different from the initial mine plate. The display mine plate only needs to use 9*9. It is not necessary to display all 11*11. 11*11 is just for us to better calculate the location around the mine clearance. The number of mines.

(3) Implementation of the initialization function

void Init_board(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;
		}
	}
}

analyze:

The lightning disk initialization function is not complicated, just use the for loop. It should be noted that we need to fill in different characters in the position of the last parameter of the function according to the different lightning disks to be initialized.

(4) Display the implementation of the function

void Display_board(char board[ROWS][COLS], int row, int col)
{
	int i = 0;
	int j = 0;
	for (i = 0; i <=row; 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");
	}
}

analyze:

1. In the display function, the first for loop is to display the coordinates of the column, which is convenient for the player to output the coordinates of the minesweeper in the future.

2. The printf("%d",i) in front of the inner for loop is to display the abscissa and the coordinates.

3. It should be noted that don't forget the line break operation!

4. The display function can be displayed from 1 to 9, because there is no need to display the 0 subscript and the 10 subscript, these two subscripts are only for us to calculate the number of surrounding mines conveniently, because we do not need to consider the particularity of the edge position.

(5) Implementation of the mine-buried function

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

analyze:

1. The count in this function is the number of mines we want to lay. Every time a mine is successfully buried, the count will decrease by 1. When the count is 0, all the mines will end, and the loop will also be jumped out.

2. The reason why we need +1 when generating the mine position in this function is because we opened a 11*11 mine disk in the front. The corresponding mine locations are 1 to 9, and the result obtained by taking the modulo of 8 ranges from 0 to 8, and after adding 1, it is 1 to 9.

3. Why do you assign the data of the location of the mine to 1? It is to calculate the number of surrounding mines later, that is, adding up the data of surrounding coordinates to get the sum of the number of surrounding mines.

(6) Implementation of mine sweeping function

void Find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int rows, int cols)
{
	int x = 0;
	int y = 0;
	int win = 0;
	while (win < (rows - 2) * (cols - 2) - EASY_COUNT)
	{
		printf("请输入你要排查的坐标:");
		scanf("%d %d", &x, &y);
		if (x > ROW || x<0 || y>COL || y < 0)
		{
			printf("输入错误,请重新输入!\n");
		}
		else
		{
			if (mine[x][y] == '1')
			{
				printf("很遗憾,你被炸死了!\n");
				Display_board(mine, ROW, COL);
				break;
			}
			else
			{
				show[x][y] = count_num(mine, x, y)+'0';
				Display_board(show, ROW, COL);
				win++;
			}
		}
	}
	if (win == (rows - 2) * (cols - 2) - EASY_COUNT)
	{
		printf("排雷成功!\n");
	}
}
static int count_num(char mine[ROWS][COLS], int x, int y)
{
	return mine[x - 1][y - 1] + mine[x - 1][y] + mine[x + 1][y] +
		mine[x + 1][y - 1] + mine[x + 1][y + 1] + mine[x - 1][y + 1] + mine[x][y + 1] +
		mine[x][y - 1]-8*'0';
}

analyze:

1. The meaning of the brackets after while: that is, when we sweep all the mines, we will jump out of the loop and judge whether the mines are completely swept through the following if condition.

2. After entering the coordinates, there are two branches. The first branch is that if the position corresponding to the coordinate is 1, that is, mine, it will show that the mine sweeping failed. If it is not a mine, it will jump to the defined count_num() to calculate the The number of mines around the coordinates. The implementation of this function is to add the values ​​stored in the surrounding coordinates and subtract 8*'0'. As for why the character 0 needs to be subtracted? Because the data type we defined when developing the Leipan is character type, the data obtained by calculation here is an integer type, and the data obtained after subtracting '0' is the integer corresponding to the character type, which is stored later to be displayed. When adding '0' to the thunder disk, it is also to convert it from an integer to a character type, which is convenient to store in the thunder disk.

(7) Introduction of header files, function declarations, and improvement of difficulty

#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 menu();//菜单函数声明
void game();//游戏主初始化函数声明
void Init_board(char board[ROWS][COLS], int rows, int cols, char ch);//初始化函数声明
void Set_mine(char mine[ROWS][COLS], int row, int col,int count);//埋雷函数声明
void Display_board(char board[ROWS][COLS], int row, int col);//展示函数声明
void Find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int rows, int cols);//扫雷函数声明

analyze:

ROW is the real number of rows of the thunder disk, COL is the real number of columns of the thunder disk, EASY_COUNT is the number of thunders, if you want to increase the difficulty of the game, you can change ROW, COL, EASY_COUNT.

4. Code implementation (sub-file presentation)

test.c code

#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
//游戏函数
void game()
{
	char mine[ROWS][COLS] = { 0 };//存取放置好雷的信息的雷盘
	char show[ROWS][COLS] = { 0 };//存取展示给用户的信息的雷盘
	Init_board(mine, ROWS, COLS, '0');//初始化雷盘
	Init_board(show, ROWS, COLS, '*');//初始化展示的雷盘
	Set_mine(mine, ROW, COL,EASY_COUNT);//埋雷
	Display_board(show, ROW, COL);//展示想要展示雷盘
	Find_mine(mine, show, ROWS, COLS);//排雷游戏开始
}
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;
		}
	} while (input);

}
int main()
{
	test();
	return 0;
}

game.h code

#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 menu();//菜单函数声明
void game();//游戏主初始化函数声明
void Init_board(char board[ROWS][COLS], int rows, int cols, char ch);//初始化函数声明
void Set_mine(char mine[ROWS][COLS], int row, int col,int count);//埋雷函数声明
void Display_board(char board[ROWS][COLS], int row, int col);//展示函数声明
void Find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int rows, int cols);//扫雷函数声明

game.c code

#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
//菜单
void menu()
{   
	printf("***********************\n");
	printf("*******  1.play  ******\n");	
	printf("*******  0.exit  ******\n");
	printf("***********************\n");
}
//初始化函数
void Init_board(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 Display_board(char board[ROWS][COLS], int row, int col)
{
	int i = 0;
	int j = 0;
	for (i = 0; i <=row; 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 Set_mine(char mine[ROWS][COLS], int row, int col,int count)
{
	while (count)
	{
		int x = rand() % 9 + 1;
		int y = rand() % 9 + 1;
		if (mine[x][y] == '0')
		{
			mine[x][y] = '1';
			count--;
		}
	}
}
//扫雷函数
void Find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int rows, int cols)
{
	int x = 0;
	int y = 0;
	int win = 0;
	while (win < (rows - 2) * (cols - 2) - EASY_COUNT)
	{
		printf("请输入你要排查的坐标:");
		scanf("%d %d", &x, &y);
		if (x > ROW || x<0 || y>COL || y < 0)
		{
			printf("输入错误,请重新输入!\n");
		}
		else
		{
			if (mine[x][y] == '1')
			{
				printf("很遗憾,你被炸死了!\n");
				Display_board(mine, ROW, COL);
				break;
			}
			else
			{
				show[x][y] = count_num(mine, x, y)+'0';
				Display_board(show, ROW, COL);
				win++;
			}
		}
	}
	if (win == (rows - 2) * (cols - 2) - EASY_COUNT)
	{
		printf("排雷成功!\n");
	}
}
static int count_num(char mine[ROWS][COLS], int x, int y)
{
	return mine[x - 1][y - 1] + mine[x - 1][y] + mine[x + 1][y] +
		mine[x + 1][y - 1] + mine[x + 1][y + 1] + mine[x - 1][y + 1] + mine[x][y + 1] +
		mine[x][y - 1]-8*'0';
}

Guess you like

Origin blog.csdn.net/m0_57304511/article/details/121252613