π± π Introduction to mine clearance
Minesweeper is a popular puzzle game, which was released in 1992. The goal of the game is to find out all non thunder grids according to the numbers in the click grid in the shortest time, and avoid stepping on thunder. Stepping on a thunder means losing the whole game.
Minesweeping web interface:
Implementation interface of mine sweeping VS2019 compiler:
π Content premise of this paper
- The minesweeping in the web version is realized by clicking the mouse. In this paper, it is realized by inputting coordinates. Therefore, the serial number of each row and column is added when printing the chessboard to facilitate input.
- This paper omits the functions of avoiding being killed for the first time, deployment at non mine and calculation time. It belongs to the foundation of mine sweeping and realizes the underlying logic of the foundation, but the remaining functions are not difficult to realize. If you are interested in time, you can study it in depth.
Code encapsulation:
In order to realize code encapsulation, three different files are given in the project:
- test.c file - realize basic functions such as entering the interface and simple function calls.
- game.c file - to achieve the main function of the mine clearance process, to complete the realization of the call function in the test.c file.
- game.h file - stores precompiled instructions, function declarations, and so on.
π©π¦² test.c file code analysis
test.c file implements the code process of the whole game, encapsulates each function into a function form, but does not give the function implementation logic to simplify the code.
π The game begins.
Note at the beginning of the game:
To print out the game menu at the beginning for selection.
- Input 1 - enter the game;
- Enter 0 - exit the game;
- Enter other - give a warning and let the player re-enter through a loop.
int main() { int input = 0; do { menu(); printf("Please select and enter:(0/1)"); scanf("%d", &input); switch (input) { case 1: game(); break; case 0: printf("You have quit the game\n"); break; default: printf("Selection error, please try again\n"); break; } } while (input); return 0; }
Pay attention to the details. After entering the game() function and exiting the game, break and jump out of switch.
A menu function is called here to print the menu.
π Print menu function
Since this paper introduces the minesweeping project based on C language, only a relatively simple menu is made. If you have friends who learn from the front end, you can build a more beautiful UI interface by yourself.
void menu() { printf("***********************\n"); printf("****** 1. play ******\n"); printf("****** 0. exit ******\n"); printf("***********************\n"); }
Display effect:
π Implement the game() function
Because this is the test.c file, it will not show all the function implementation codes in this file, but only the functions called for the functions to be implemented.
void game() { char mine[ROWS][COLS] = { 0 }; //Store mine information char show[ROWS][COLS] = { 0 }; //Store the information of the mine //Initialize array init_board(mine, ROWS, COLS, '0'); // 0 init_board(show, ROWS, COLS, '*'); // * //Print chessboard display_board(show, ROW, COL); //Buried mine set_mine(mine, ROW, COL); //display_board(mine, ROW, COL); //Start demining find_mine(mine, show, ROW, COL); }
The following describes the functions implemented by each function one by one:
- Initialize array
init_board(mine, ROWS, COLS, '0'); // 0 init_board(show, ROWS, COLS, '*'); // *
Since mine clearance requires two chessboards:
- An underlying chessboard for storing mines.
- A top-level chessboard displayed to users.
Therefore, it is necessary to define two two-dimensional arrays to represent two checkerboards, so the two-dimensional arrays need to be initialized respectively, but only one function is required to realize initialization. Therefore, the same function is called twice here, but the parameters are different.
Explain in advance:
Here, ROWS and COLS represent 11, and ROW and COL represent 9.
We define the chessboard as 9 β 9. However, when demining, it is necessary to check the coordinates up, down, left and right. If the coordinates are located at the boundary, the array will cross the boundary. Therefore, it is necessary to define two rows and two columns when defining the array.
The mine array represents the array of Mines stored in the background- Set all to '0' during initialization;
The show array represents the array displayed to the user- Set all to '*' during initialization;
In the chessboard, 0 means no thunder, while 1 means thunder.
Note that 0 and 1 here are characters.
Initializing the mine array to 0 means that the current chessboard is completely mine free.
- Print checkerboard functions.
display_board(show, ROW, COL);
Printing the chessboard function requires some processing and adjustment of the chessboard to make it look like what we want.
For example:
- The position of each row and column is represented by numbers.
- Separate each row with a --- dividing line.
- Separate each column with a dividing line.
Among them, when passing parameters, you only need to pass ROW and COL, but you need to pass ROWS and COLS. Because the printed chessboard should display the show array for the user, so we don't need to display the additional two ROWS and two columns.
- Set the ray function.
set_mine(mine, ROW, COL);
The function to be realized here is to bury the thunder into the mine array we have initialized, because the player uses 9 when playing the game β 9, so we only need to pass ROW and COL when passing parameters here.
Embedding Lei - that is, the character '1' into the array is to realize replacement, which will be described in detail later.
- Demining function.
find_mine(mine, show, ROW, COL);
The demining function is still the user's operation, and the coordinates of the position where you want to check the mine are input, and the object is 9 β 9 chessboard, pass parameters still only need to pass ROW and COL.
Note that two arrays need to be transmitted here, because it is necessary to judge whether there is thunder in the mine array after the user enters the coordinates. After making the corresponding response, it will be displayed on the show array and printed on the interface.
π₯ game.h file code analysis
The game.h file contains:
- Preprocessing instructions.
- The file contains.
- Global variables.
- #define identifiers, constants, and so on.
π¨ File contains
#include <stdio.h> #include <stdlib.h> #include <time.h>
Explanation:
- Standard input and output functions are used in almost any, so they are included in the game.h file, and other files only need to include the game.h file.
- "stdlib.h" will be used when setting pseudo-random values, which will be described in detail later when the game.h file is introduced.
- "time.h" is a timestamp function used when setting pseudo-random values. It needs to be used after including the file.
π² define identifier constant
#define ROW 9 #define COL 9 #define ROWS ROW + 2 #define COLS COL + 2 #define EASY_COUNT 10
ROW, COL, ROWS and COLS have been mentioned earlier:
- ROW - COL: indicates the true size of the chessboard.
- ROWS - COLS: the array size of two rows and two columns is set to prevent the array from crossing the boundary.
- The so-called EASY_COUNT is the number of mines in simple difficulty. Here, it is set to 10 mines.
π³π Function declaration
//Initialize array void init_board(char board[ROWS][COLS], int rows, int cols, char set); //Print chessboard void display_board(char board[ROWS][COLS], int row, int col); //Buried mine void set_mine(char board[ROWS][COLS], int row, int col); //Start demining void find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
Put all function declarations in the game.h file, and other files include the game.h file. It's very convenient once and for all.
Note: as like as two peas, the declaration of function is exactly the same as the definition of function!
π§· game.c file code analysis
The code stored in this file is the code that really realizes the function of minesweeping program, and realizes the implementation logic of each function to complete the corresponding function.
π© Initialization function
The initialization function initializes the two checkerboards we define to what we want.
- Initialize all elements in the mine array to 0, indicating that there is no thunder in the whole chessboard
- Initialize all elements in the show array to '*', indicating that all positions have not been checked.
We only need to traverse all the elements in the two-dimensional array through two-layer loops, and change all the elements to what we want.
void init_board(char board[ROWS][COLS], int rows, int cols, char set) { for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { board[i][j] = set; } } }
The parameter here needs one more set, that is, the content we want to initialize.
π¦Ό Print checkerboard function
First show us what the chessboard looks like:
The '*' in the chessboard is the element after the initialization of our last function, indicating that it is all to be checked.
As can be seen from the chessboard above, we need to realize the following functions:
- Print out row labels and lists for each row and column.
- Print out the contents of each element in the show array.
- Print out "-" split line and '|' split line.
void display_board(char board[ROWS][COLS], int row, int col) { //Print the column labels and split lines of the first row for (int i = 0; i <= row; i++) { printf(" %d ", i); if (i < row) { printf("|"); } } printf("\n"); //Control split line for (int i = 0; i <= row; i++) { printf("---"); if (i < row) { printf("|"); } } printf("\n"); //Print data and control separator for (int i = 1; i <= row; i++) { printf(" %d |", i); for (int j = 1; j <= col; j++) { printf(" %c ", board[i][j]); if (j < col) { printf("|"); } } printf("\n"); if (i < row) { for (int k = 0; k <= col; k++) { printf("---"); if (k < col) { printf("|"); } } } printf("\n"); } }
It should be noted that in the print data part here, in order to control the printing line label from 1, the cyclic variable control starts from 1, and the subsequent user input control also starts from 1
Just be careful when controlling!
π§βοΈ Buried lightning function
Function implementation of this function:
- Conduct random mine burial on the initialized mine chessboard, and the number of mines is determined by EASY_COUNT control.
- Random numbers are generated by srand and rand functions through time stamps, and "stdlib.h" and "time.h" header files need to be called;
- It should be noted that if the currently generated random coordinates have been released before, you need to regenerate the random coordinates again until they are placed.
void set_mine(char mine[ROWS][COLS], int row, int col) { int cnt = EASY_COUNT; while (cnt > 0) { int x = rand() % row + 1; //1-9 int y = rand() % col + 1; //1-9 if ('0' == mine[x][y]) { mine[x][y] = '1'; cnt--; } } }
As mentioned in the previous function, the coordinates of the chessboard in the user's eyes start from 1, and the chessboard we control also starts from 1. Therefore, we need to add one after taking the modules of row and col.
π΅ Anti thunder function
The mine detection function is complex and the most critical step. We need to clear the mine all the time through cyclic control;
The troubleshooting results are as follows:
- First of all, we need to define a variable win, which indicates the number of Mines successfully screened. When the number of Mines screened is equal to the total number of coordinates minus the number of mines, it will be a victory.
- If the coordinate of the investigation is the character '1', that is, our mine, it is necessary to remind the user of the failure of the game and display the buried mine, that is, print the mine array of buried mines.
- If the checked coordinate is not mine, it means that the check is successful once, so that the win variable increases by 1, and the number of mines at eight positions around the coordinate is calculated through the function, and the value is put into the show array of corresponding coordinates and provided to the player.
- If the coordinates entered by the player are not in the chessboard, the player should be reminded that the coordinates entered are illegal, and re-enter them through a cycle to increase the robustness of the code in turn.
void find_mine(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("Please enter the coordinates you want to find:>"); scanf("%d %d", &x, &y); if (x >= 1 && x <= row && y >= 1 && y <= col) { if (mine[x][y] == '0') { int count = get_mine_count(mine, x, y); show[x][y] = count + '0'; win++; display_board(show, ROW, COL); } else { printf("Sorry, you were killed\n"); display_board(mine, ROW, COL); break; } } else { printf("Illegal coordinates, please re-enter\n"); } } if (win == row * col - EASY_COUNT) { printf("Congratulations on your success.\n"); } }
Here we pay attention to get_ mine_ The return value of the count function is int, but the array we define is character type, so we need to add the character '0' to convert it into characters, such as the number 3 to the character '3'.
π€ΈβοΈ Calculate the number of mines around the coordinates
This function is used to calculate the number of mines in the upper, lower, left and right positions of the provided array coordinates. Because mines are set with the character '1', while no mines are set with the character '0', the number of characters' 1 'can be obtained by adding up the coordinate elements of 8 positions and subtracting 8 characters' 0'.
int get_mine_count(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'; }
Note that the arguments passed here are character coordinates, so the formal parameters also need to be corresponding.
And the function is called and used in the game.c file, so you only need to define the function before the called function and do not need to be declared.
ππ summary
The above is the whole content of this article. The whole game code source code will be placed in the last ps part of the full text. If there is something wrong or insufficient, I hope you can leave a message in the comment area. If you think the blogger's writing is OK, you can leave a message π give the thumbs-up π+π follow π+β Collection β Oh~
π΄PS
πΈtest.c
#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 }; //Store mine information char show[ROWS][COLS] = { 0 }; //Store the information of the mine //Initialize array init_board(mine, ROWS, COLS, '0'); // 0 init_board(show, ROWS, COLS, '*'); // * //Print chessboard display_board(show, ROW, COL); //Buried mine set_mine(mine, ROW, COL); //display_board(mine, ROW, COL); //Start demining find_mine(mine, show, ROW, COL); } int main() { srand((unsigned int)time(NULL)); int input = 0; do { menu(); printf("Please select and enter:(0/1)"); scanf("%d", &input); switch (input) { case 1: game(); break; case 0: printf("You have quit the game\n"); break; default: printf("Selection error, please try again\n"); break; } } while (input); return 0; }
πΈgame.c
#define _CRT_SECURE_NO_WARNINGS 1 #include "game.h" void init_board(char board[ROWS][COLS], int rows, int cols, char set) { for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { board[i][j] = set; } } } void display_board(char board[ROWS][COLS], int row, int col) { //Print the column labels and split lines of the first row for (int i = 0; i <= row; i++) { printf(" %d ", i); if (i < row) { printf("|"); } } printf("\n"); //Control split line for (int i = 0; i <= row; i++) { printf("---"); if (i < row) { printf("|"); } } printf("\n"); //Print data and control separator for (int i = 1; i <= row; i++) { printf(" %d |", i); for (int j = 1; j <= col; j++) { printf(" %c ", board[i][j]); if (j < col) { printf("|"); } } printf("\n"); if (i < row) { for (int k = 0; k <= col; k++) { printf("---"); if (k < col) { printf("|"); } } } printf("\n"); } } void set_mine(char mine[ROWS][COLS], int row, int col) { int cnt = EASY_COUNT; while (cnt > 0) { int x = rand() % row + 1; //1-9 int y = rand() % col + 1; //1-9 if ('0' == mine[x][y]) { mine[x][y] = '1'; cnt--; } } } int get_mine_count(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) { int x = 0; int y = 0; int win = 0; while (win < row * col - EASY_COUNT) { printf("Please enter the coordinates you want to find:>"); scanf("%d %d", &x, &y); if (x >= 1 && x <= row && y >= 1 && y <= col) { if (mine[x][y] == '0') { int count = get_mine_count(mine, x, y); show[x][y] = count + '0'; win++; display_board(show, ROW, COL); } else { printf("Sorry, you were killed\n"); display_board(mine, ROW, COL); break; } } else { printf("Illegal coordinates, please re-enter\n"); } } if (win == row * col - EASY_COUNT) { printf("Congratulations on your success.\n"); } }
πΈgame.h
#define _CRT_SECURE_NO_WARNINGS 1 #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 //Initialize array void init_board(char board[ROWS][COLS], int rows, int cols, char set); //Print chessboard void display_board(char board[ROWS][COLS], int row, int col); //Buried mine void set_mine(char board[ROWS][COLS], int row, int col); //Start demining void find_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);