Minesweeper - C language [detailed + full code source]

Foreword: Today we are learning another well-known small game in C language - Minesweeper, let's
start our learning now!

The overall idea of ​​the game

Let's take a look at how to play the minesweeper game online

  • Need to print a checkerboard to store mine

insert image description here

  • Set mine and check mine
    insert image description here

Here we need to set up two arrays, one is used to mark mines, and the other is used to check mines
(when checking mines, the number tells us how many mines there are in the eight surrounding chess pieces, which is convenient for checking)

  • Hit Ray and you lose
    insert image description here

First we need three files

test.c - test game logic
game.c - function implementation
game.h - function declaration

game flow

1. Build the game menu
2. Create an array and initialize it
3. Arrange mines
4. Check mines

Printing of game menus

To enter the game, there is a menu first, let us choose whether to enter the game
Here we directly put the header file in game.h, directly#include “game.h”Just include it and
look at the code:

#include "game.h"
void menu()
{
    
    
	printf("********************************\n");
	printf("******      1. play       ******\n");
	printf("******      0. exit       ******\n");
	printf("********************************\n");
}
int main()
{
    
    
	int input = 0;
	do
	{
    
    
		menu();
		printf("请选择:> ");
		scanf("%d", &input);
		switch (input)
		{
    
    
		case 1:
				printf("扫雷\n");
				break;
		case 0:
				printf("退出游戏\n");
				break;
		default:
			    printf("选择错误,请重新选择\n");
			    break;
		}
	} while (input);
	return 0;
}

create array and initialize

To set mine we use an arraychar main[ ] [ ]
To troubleshoot, we use an arraychar show[ ] [ ]
insert image description here

When we counted the mines, we found that if the mines are in the corners, there is a situation that the access is out of bounds.
For example: as
insert image description here
shown in the figure, how do we solve this problem?
You only need to make the range of the array larger than the range of the chessboard (that is, print two arrays, one 9 * 9, one 11 * 11)
as shown in the figure:
insert image description here
to initialize the chessboard, we useinitBoard()function, to print the chessboard we useDisplayBoard()Function, here is similar to the explanation in the previous issue of three-piece chess.
Look at the code:

//初始化棋盘
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;
	printf("******* 扫雷 *******\n");
	for (j = 0; j <= col; j++)
	{
    
    
		printf("%d ", j);
	}
	printf("\n");
	for (i = 1; i <= row; i++)
	{
    
    
		printf("%d ", i);
		for (j = 1; j <= col; j++)
		{
    
    
			printf("%c ", board[i][j]);
		}
		printf("\n");
	}
}

The result of the operation is as follows
insert image description here

layout mine

Here we useSetMine()Function to lay out mine
notes:

  1. When setting mines, we create them in a 9*9 array
  2. In the header file define a#define EASY_COUNT 10To arrange 10 mines
  3. Arrange mines randomlyrand()function to set the random number
  4. userand() % row + 1andrand() % col + 1to get random coordinates
  5. Use the rand() function to usesrand((unsigned int)time(NULL))Call it and include#include <time.h>and#include <stdlib.h>
    Implementation of the header file code:
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--;
		}
	}
}

operation result
insert image description here

Troubleshooting

Here we useFindMine()To check
if the check coordinates are not mines, we need to count how many mines are around the coordinates, here we useGetMineCount()function to check the surrounding coordinates

Because 1+'0'=1+48=49, 1+'0'='1',
and so on, '0'-'0'=0, '1'-'0'=1,
so judge the surrounding coordinates Is it thunder? After summing the values ​​​​of the surrounding 8 coordinates (-8 * '0'), see if the result is 0 or 1 to judge whether it is thunder

Look at the code:

int GetMineCount(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][y + 1] +
		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 (show[x][y] == '*')
			{
    
    
				if (mine[x][y] == '1')
				{
    
    
					printf("很遗憾,你被炸死\n");
					DisplayBoard(mine, ROW, COL);
					break;
				}
				else
				{
    
    
					//如果该坐标不是雷,就要统计这个坐标周围有几个雷
					int count = GetMineCount(mine, x, y);
					show[x][y] = count + '0';
					DisplayBoard(show, ROW, COL);
					win++;
				}
			}
			else
			{
    
    
				printf("该位置已经被排查\n");
			}
		}
		else
		{
    
    
			printf("排查的坐标非法,请重新输入\n");
		}
	}
	if (win == row * col - EASY_COUNT)
	{
    
    
		printf("恭喜你,排雷成功\n");
		DisplayBoard(mine, ROW, COL);
	}
}

full code

game.h

#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 10
//初始化棋盘
void IntBoard(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);

game.c

#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;
	printf("******* 扫雷 *******\n");
	for (j = 0; j <= col; j++)
	{
    
    
		printf("%d ", j);
	}
	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)
	{
    
    
		//rand()生成的随机值是0~32767
		//所以%row生成的范围是0~8
		int x = rand() % row + 1;
		int y = rand() % col + 1;
		if (mine[x][y] == '0')
		{
    
    
			mine[x][y] = '1';
			count--;
		}
	}
}
int GetMineCount(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][y + 1] +
		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 (show[x][y] == '*')
			{
    
    
				if (mine[x][y] == '1')
				{
    
    
					printf("很遗憾,你被炸死\n");
					DisplayBoard(mine, ROW, COL);
					break;
				}
				else
				{
    
    
					//如果该坐标不是雷,就要统计这个坐标周围有几个雷
					int count = GetMineCount(mine, x, y);
					show[x][y] = count + '0';
					DisplayBoard(show, ROW, COL);
					win++;
				}
			}
			else
			{
    
    
				printf("该位置已经被排查\n");
			}
		}
		else
		{
    
    
			printf("排查的坐标非法,请重新输入\n");
		}
	}
	if (win == row * col - EASY_COUNT)
	{
    
    
		printf("恭喜你,排雷成功\n");
		DisplayBoard(mine, ROW, COL);
	}
}

test.c

#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 };
	//初始化棋盘
	InitBoard(mine, ROWS, COLS, '0');
	InitBoard(show, ROWS, COLS, '*');
	//打印棋盘
	 DisplayBoard(show, ROW, COL);
	//布置雷
	SetMine(mine, ROW, COL);
	//排查雷
	FindMine(mine, show, ROW, COL);
}
int main()
{
    
    
	int input = 0;
	srand((unsigned int)time(NULL));
	do
	{
    
    
		menu();
		printf("请选择:> ");
		scanf("%d", &input);
		switch (input)
		{
    
    
		case 1:
			game();
				break;
		case 0:
				printf("退出游戏\n");
				break;
		default:
			    printf("选择错误,请重新选择\n");
			    break;
		}
	} while (input);
	return 0;
}

The result of the operation, it is a pity that Qiqi was bombed by thunder here
insert image description here

Postscript:
Qiqi’s minesweeper game still has a lot of things that can be optimized,
such as: click one to expand a piece, mark the position of mines, set a countdown, etc.
I will not explain here, interested friends can study it yourself
insert image description here

Guess you like

Origin blog.csdn.net/2201_75366661/article/details/128959086