[mine sweeping game] simple simulation implementation explanation

Posted by 00tank on Tue, 25 Jan 2022 21:28:49 +0100

preface

  • 🚄 Input is the essence of learning and output is the means of learning.
  • 🔖 Share every learning and expect you and me to gain.
  • 🎇 welcome 🔎 follow 👍 give the thumbs-up ⭐ Collection ✉ Comments, common progress!
  • 🌊 "Be good enough to catch the surprises and opportunities given by God"
  • 💬 The blogger's level is limited. If there is any error, please correct it. Thank you very much!

Mainly talk about ideas and some points for attention.
I'm sure you haven't played and heard about what minesweeping is. I'll just go over it.
This is a minesweeping interface.

To achieve mine clearance, the following steps are required:

  • Create such a chessboard
  • Lay thunder
  • mine clearance

☁️ 1. Create a chessboard. Suppose we need a 9 * 9 chessboard.

When we select a position, if the position is not thunder, the game should give us a feedback and tell us how many thunder there are in eight positions around us.
Like this:

This indicates that there are three mines in the surrounding circle. If it happens that the position we choose is ray, then we will be killed and the game will end directly.

There is a problem here. If I choose the middle position, there are 8 positions around to feed back. What if I choose the edge?

Obviously, this is beyond the range of the array. Therefore, we might as well expand the scope when we create such a chessboard again.

For example, if we want a 9 * 9 chessboard, we will expand the range to 11 * 11 (one row and one column will be added at the top, bottom, left and right respectively. Green is the expanded range). As long as mines are not buried in the expanded part, the displayed number will only be the number of mines in the interval of 9 * 9, as shown in the figure:
(assuming * indicates thunder)

  • Create array - size determination
//It is more convenient to adjust the size of the game board with define

//Actual game range
#define ROW 9  
#define COL 9  


//Expanded scope
#define ROWS 11
#define COLS 11

☁️ 2. How to set thunder and feedback?

Some old fellow feel that they can be in a chessboard.
Use 1 and 0 to represent mine and non mine respectively
It's like this: (1 for thunder, 0 for non thunder)

However, this will produce ambiguity with the 1 of the thunder number around the feedback, so it is not appropriate.

Some old fellow think that they can use Lei to express thunder, but they say it is not thunder, but it is not convenient enough. It is not convenient to use 0 and 1. Why is it not convenient enough? I'll know in a moment. Of course, if you have to do so, it's OK. It's just a little more complicated when judging.

Since we want to use 1 and 0 to represent thunder and non thunder, and we can't have ambiguity with the number of feedback, we might as well open another equally large chessboard. In this way, one chessboard is used to arrange thunder, but it is not displayed to the player, and the other chessboard is displayed to the player as the chessboard of feedback information.

At the beginning, we initialize the checkerboard for laying mines, set it all to 0 (non mines), and then bury mines randomly.
Set all the chessboards displayed to the player as *, which is a chessboard that has not been moved

//Initialize chessboard
void InitBoard(char board[ROWS][COLS], int row, int col, char set)
{
	for (int i = 0; i < row; i++)
	{
		for (int j = 0; j < col; j++)
		{
			board[i][j] = set;
		}
	}
}
	char mine[ROWS][COLS]; //Leipan
	char show[ROWS][COLS];//Feedback disk

	//Initialize chessboard
	InitBoard(mine, ROWS, COLS, '0');  //0 Non mine 
	InitBoard(show, ROWS, COLS, '*');  //Full set*

The effects are as follows (comparison):


Then lay out the thunder:

#define Count 10 / / arrange 10 mines

//Lay thunder
void SetMine(char mine[ROWS][COLS], int row, int col)
{
	int count = Count;
	while (count)
	{
		int x = rand() % 9 + 1;
		int y = rand() % 9 + 1;
		if (mine[x][y] == '0') //If this position is not mine
		{
			mine[x][y] = '1';
			count--;
		}
		//If this position is already mine, the layout will not be repeated.
	}

}

After arranging the thunder, we can see the effect:

  • Layout of thunder disk and feedback disk

☁️ 3. When to finish mine clearance and how to feed back.

int Show(char mine[ROW][COL], int x, int y)
{
	return mine[x - 1][y - 1] +
		   mine[x - 1][y] +
		   mine[x - 1][y + 1] +
		   mine[x + 1][y - 1] +
		   mine[x + 1][y] +
		   mine[x + 1][y + 1] +
		   mine[x][y - 1] +
		   mine[x][y + 1];
}
//mine clearance
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS])
{
	int x, y;
	int endcount = ROW * COL - Count; //Number of non mines, used to mark
	int count = Count;//Number of thunder

	//There are two situations when the program ends:
	//1. Killed by explosion
	//2. All non mine points have passed, leaving only mine points. Demining is successful
	do
	{
		if (endcount == 0) //Non lightning point is 0
		{
			printf("There are no mined areas\n");
			break;
		}
		printf("Please enter coordinates:\n");
		scanf("%d%d", &x, &y);
		if (x >= 1 && x <= ROW && y >= 1 && y <= COL)
		{
			{
				if (mine[x][y] == '1')
				{
					printf("You were killed\n");
					//Expand the entire diagram
					PrintBoard(mine, ROW, COL);
					break;
				}
				//Otherwise, it indicates how many mines are around the coordinate
				else
				{
					int showcount = Show(mine, x, y);

					show[x][y] = showcount + '0';//Number to character
					PrintBoard(show, ROW, COL);
				}
			}
		}

		else
		{
			printf("Coordinate error, please re-enter");
			continue;
		}
	} while (1);
}

Explain the Show function:
In the ASCII table, we can observe that,
'0' - '0' = 0 (character 0 equals digit 0)
The number can be obtained by subtracting the character 0 from any other numeric character, such as
'5'-'0'= 5

Therefore, the Show function will be surrounded by eight characters (either 0 or 1)
Add it all up and subtract eight 'zeros'. You can get a number,
This number indicates that there are several 1s around.

This explains why it is convenient to use 1 and 0 to represent thunder and non thunder.

Finally, explain this line of code:

show[x][y] = showcount + '0';//Number to character

Because the show array stores characters, it cannot fully receive the returned integer number.

Number of characters - '0' = number -- > number of characters = number + '0'

Full code:

game.h

#define _CRT_SECURE_NO_WARNINGS

#include<stdio.h>

//Actual game range
#define ROW 9  
#define COL 9  


//Expanded scope
#define ROWS 11
#define COLS 11

#define Count 10; // Number of thunder


//Initialize chessboard
void InitBoard(char board[ROWS][COLS], int row, int col, char set);

//Print chessboard
void PrintBoard(char board[ROWS][COLS], int row, int col);

//Lay thunder
void SetMine(char mine[ROWS][COLS], int row, int col);

//mine clearance
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS]);

game.c

#define _CRT_SECURE_NO_WARNINGS
#include"game.h"


//Initialize chessboard
void InitBoard(char board[ROWS][COLS], int row, int col, char set)
{
	for (int i = 0; i < row; i++)
	{
		for (int j = 0; j < col; j++)
		{
			board[i][j] = set;
		}
	}
}



//Print chessboard
void PrintBoard(char board[ROWS][COLS], int row, int col)
{
	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 ", board[i][j]);
		}
		printf("\n");
	}
}

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

}

int Show(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 + 1][y - 1] +
			mine[x + 1][y] +
			mine[x + 1][y + 1] +
			mine[x][y - 1] +
			mine[x][y + 1] - 8 * '0';
		
}



//mine clearance
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS])
{
	int x, y;
	int endcount = ROW * COL - Count; //Number of non mines, used to mark
	int count = Count;//Number of thunder

	//There are two situations when the program ends:
	//1. Killed by explosion
	//2. All non mine points have passed, leaving only mine points. Demining is successful
	do
	{
		if (endcount == 0) //Non lightning point is 0
		{
			printf("There are no mined areas\n");
			break;
		}
		printf("Please enter coordinates:\n");
		scanf("%d%d", &x, &y);
		if (x >= 1 && x <= ROW && y >= 1 && y <= COL)
		{
			{
				if (mine[x][y] == '1')
				{
					printf("You were killed\n");
					//Expand the entire diagram
					PrintBoard(mine, ROW, COL);
					break;
				}
				//Otherwise, it indicates how many mines are around the coordinate
				else
				{
					endcount--; //If a non mine point is not found, the number of non mines is reduced by one. When the number of non mines is 0, it indicates that the demining is successful and the game is over
					int showcount = Show(mine, x, y);

					show[x][y] = showcount + '0';
					PrintBoard(show, ROW, COL);
				}
			}
		}

		else
		{
			printf("Coordinate error, please re-enter");
			continue;
		}
	} while (1);
}



test.c

#define _CRT_SECURE_NO_WARNINGS

#include"game.h"
#include<time.h>


void game()
{
	srand((unsigned int)time(NULL));

	char mine[ROWS][COLS]; //Leipan
	char show[ROWS][COLS];//Feedback disk

	//Initialize chessboard
	InitBoard(mine, ROWS, COLS, '0');  //0 Non mine 
	InitBoard(show, ROWS, COLS, '*');
	//Lay thunder
	SetMine(mine, ROW, COL);
	PrintBoard(show, ROW, COL);
	//mine clearance
	int x, y;
	FindMine(mine, show);


}




int main()
{
	game();
}

Topics: C Game Development