[c language] implementation of minesweeping logic [including extension]~

1. Introduction to the game rules:

Minesweeper game, when you select a coordinate, check if there are mines in the surrounding 8 coordinates, the number of mines will be displayed, and if there are no mines, it will expand outward until you check that there are mines in the 8 surrounding coordinates, and the place without mines will be blank. Until all the positions without mines are excluded, the game wins, otherwise the game will end if you step on mines!

As shown in the picture: the number in the picture means how many mines are in the surrounding 8 coordinates

2. Code implementation process

1. First, we use vs to create three files

test.c–Test of minesweeper game

game.c–Implementation of game functions

game.h–declaration of game functions

test.c main logic:

#include “game.h”
void menu()
{
printf(“********************\
“);
printf(“***** 1. Play *****\
“);
printf(“***** 0.exit *****\
“);
printf(“********************\
“);

}
void game()
{
system(“cls”);
char mine[ROWS][COLS] = { 0 };//store the information of mines arranged
char show[ROWS][COLS] = { 0 };//store the information of mines detected
//Initialize the chessboard
InitBoard(mine, ROWS, COLS, ‘0’);
InitBoard(show, ROWS, COLS, ‘*’);
Printboard(show, ROW, COL);
//Set the function of mine
SetMine(mine, ROW, COL);
//Function to check mine
ShowMine(mine, show, ROW, COL);

}
int main()
{
srand((unsigned int)time(NULL));
int input;
do
{
menu();
scanf(“%d”, &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf(“Exit the game\
“);
break;
default:
printf(“Wrong selection, please re-select!\
“);
break;
}
} while (input);
}

1. Arrange thunder

Ray should be stored in a two-dimensional array, so there must be a board for storing mine

Because it needs to be stored, and the board is 9*9, so use a two-dimensional array

Use the character ‘1’ to indicate lightning, and the character ‘0’ to indicate non-electric

2. Troubleshooting

If there are mines around, the number of mines will be displayed, so when there is only one mine around, is 1 the mine or the number of mines? This will cause ambiguity, so another array is created to store the information of the detected mines

Overall

The mine array stores mine information

The show array stores the information of detecting and detecting mines

3. How to check mine?

When checking a coordinate, it is to see if there are mines in the 8 surrounding coordinates, but when this coordinate is the border of the board, checking the coordinates around it will cause the array to go out of bounds, so we can set the mine array to 11*11 Yes, when placing mines, they will only be placed in the middle 9*9 space. The space we added is just to make it easier to check for mines, to prevent the problem of array out of bounds, and just to maintain correspondence and reduce repeated operations, so put The show array is also set to 11*11

4. Initialize the chessboard

In order to make the initial condition of the chessboard have a mine-sweeping structure, the mine array is initialized to ‘0’ (the state of no mines at the beginning)

Initialize the show array to ‘*’ (a sense of mystery), we can write an initialization function, but the two arrays need to be initialized to different things, we need one more parameter in the Initboard array, which is also The show array is also set to reflect the advantages of 11*11, avoiding repeated operations

void InitBoard(char board[][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;
}
}
}

5. Set the function of Lei

You need to know that the range of a number in rand()% is 0 ~ this number -1, for example, the range of rand()%9 is 0~8, if it is rand()%9 + 1, the range is 1~9, the coordinates Just set the range to 1~9 and set up mines

void SetMine(char mine[][COLS], int row, int col)
{
int count = 10;
while (count)
{
int x = rand() % row + 1;
int y = rand() % col + 1;
if (mine[x][y] == ‘0’)
{
mine[x][y] = ‘1’;
count–;
}
}
}

6. The function of printing the chessboard

Double-layer for loop printing is fine, you can add a certain format

void Printboard(char board[][COLS], int row, int col)
{
printf(“————Minesweeper Game———–\
“);
int i = 0;
int j = 0;
for (i = 0; i <= col; i ++ )
{
printf(“%d “, i);
}
printf(“\
“);
for (i = 1; i <= row; i ++ )
{
printf(“%d “, i);
for (j = 1; j <= col; j ++ )
{
printf(“%c “, board[i][j]);
}
printf(“\
“);
}
printf(“————Minesweeper Game———–\
“);
}

7. Thoughts on mine detection

How to check how many mines are in the 8 coordinates around a coordinate?

Corresponding addition, but this is the addition of characters, because I want to count how many mines there are, so I should subtract 8*’0′ (the asc binary code value of 0 is 48), and the conversion of characters and numbers only needs + – ‘0’ is enough

static int get_mine_count(char mine[][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*48;

}

8. Expand after checking

The range of extended coordinates should be limited. If the coordinates I want to check have mines, the game will end directly

If there is no thunder, it will expand to the surrounding 8 coordinates, and if there is no thunder, set this coordinate as a space. Only when it is set can it prevent repeated recursion! Then limit the range of coordinates. If you reach the boundary, there is no need to continue recursing outside the boundary, as it will cross the boundary. After recursing, you will find that there are mines around, and you can just display the number of mines

void expand(char mine[][COLS], char show[][COLS], int row, int col, int x, int y)
{
//The recursive loop condition is that there are no mines around
int count = get_mine_count(mine,x,y);
if (count == 0)
{
//If the number of mines around is 0, set this place as a space
// will prevent recursive repeated calls
show[x][y] = ‘ ‘;
int i = 0;
int j = 0;
for (i = x – 1; i <= x + 1; i + + )
{
for (j = y – 1; j <= y + 1; j + + )
{
if (show[i][j] == ‘*’ & amp; & amp; i > 0 & amp; & amp; i <= row & amp; & amp; j > 0 & amp; & amp; j < = col)
{//If this coordinate is the boundary, there is no need to call all the surrounding coordinates!
expand(mine, show, row, col, i, j);
}
}
}
}
else
{//The recursive exit is how many mines I counted around
show[x][y] = count + ‘0’;
}

}

9. Judging whether to win or lose

Because the unchecked coordinates in the show array are all ‘*’, so as long as the remaining ‘*’ = the number of mines, the game wins if it is equal

Because it is the reason for expansion, it is enough to judge from the number of remaining ‘*’!

int Iswin(char show[][COLS], int row, int col)
{
int i = 0;
int j = 0;
int c = 0;
for (i = 1; i <= row; i ++ )
{
for (j = 1; j <= col; j ++ )
{
if (show[i][j] == ‘*’)
{
c++;
//Statistics of the remaining unchecked numbers
}
}
}
return c;
}

Extension:

We can use system(“cls”); to clear the screen and look more comfortable, don’t forget to quote the windows.h header file

The complete code is as follows:

test.c

#define _CRT_SECURE_NO_WARNINGS
#include "game.h"
void menu()
{
printf("********************\
");
printf("***** 1. Play *****\
");
printf("***** 0.exit *****\
");
printf("********************\
");

}
void game()
{
system("cls");
char mine[ROWS][COLS] = { 0 };//store the information of mines arranged
char show[ROWS][COLS] = { 0 };//store the information of mines detected
//Initialize the chessboard
InitBoard(mine, ROWS, COLS, '0');
InitBoard(show, ROWS, COLS, '*');
Printboard(show, ROW, COL);
//Set the function of thunder
SetMine(mine, ROW, COL);
//Function to check mine
ShowMine(mine, show, ROW, COL);


}
int main()
{
srand((unsigned int)time(NULL));
int input;
do
{
menu();
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
case 0:
printf("Exit the game\
");
break;
default:
printf("Wrong selection, please re-select!\
");
break;
}
} while (input);
}

game.c

#define _CRT_SECURE_NO_WARNINGS
#include "game.h"
//Function to initialize the board
void InitBoard(char board[][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;
}
}
}

//Function to print the chessboard
void Printboard(char board[][COLS], int row, int col)
{
printf("------------Minesweeper Game-----------\
");
int i = 0;
int j = 0;
for (i = 0; i <= col; i ++ )
{
printf("%d ", i);
}
printf("\
");
for (i = 1; i <= row; i ++ )
{
printf("%d ", i);
for (j = 1; j <= col; j ++ )
{
printf("%c ", board[i][j]);
}
printf("\
");
}
printf("------------Minesweeper Game-----------\
");
}

// function to set mine
void SetMine(char mine[][COLS], int row, int col)
{
int count = 10;
while (count)
{
int x = rand() % row + 1;
int y = rand() % col + 1;
if (mine[x][y] == '0')
{
mine[x][y] = '1';
count--;
}
}
}

//The function to get the number of mines
static int get_mine_count(char mine[][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*48;
\t\t
\t\t
}

int Iswin(char show[][COLS], int row, int col)
{
int i = 0;
int j = 0;
int c = 0;
for (i = 1; i <= row; i ++ )
{
for (j = 1; j <= col; j ++ )
{
if (show[i][j] == '*')
{
c++;
//Statistics of the remaining unchecked numbers
}
}
}
return c;
}

//Extend Ray's function
void expand(char mine[][COLS], char show[][COLS], int row, int col, int x, int y)
{
//The recursive loop condition is that there are no mines around
int count = get_mine_count(mine,x,y);
if (count == 0)
{
//If the number of mines around is 0, set this place as a space
// will prevent recursive repeated calls
show[x][y] = ' ';
int i = 0;
int j = 0;
for (i = x - 1; i <= x + 1; i + + )
{
for (j = y - 1; j <= y + 1; j + + )
{
if (show[i][j] == '*' & amp; & amp; i > 0 & amp; & amp; i <= row & amp; & amp; j > 0 & amp; & amp; j < = col)
{//If this coordinate is the boundary, there is no need to call all the surrounding coordinates!
expand(mine, show, row, col, i, j);
}
}
}
}
else
{//The recursive exit is how many mines I counted around
show[x][y] = count + '0';
}

}

//Function to check mine
void ShowMine(char mine[][COLS], char show[][COLS], int row, int col)
{
\t
int x = 0;
int y = 0;
int c = row * col - MINE;
while (1)
{
printf("Please enter the coordinates you want to check:\
");
scanf("%d %d", &x, &y);
if (x >= 1 & amp; & amp; x <= row & amp; & amp; y >= 1 & amp; & amp; y <= col)
{
if (mine[x][y] == '0')
{
expand(mine, show, ROW, COL, x, y);
system("cls");
Printboard(show, ROW, COL);
if (Iswin(show, ROW, COL) == MINE)
{
printf("Congratulations on your successful demining!\
");
Printboard(mine, ROW, COL);
break;
}
}
else
{
printf("Unfortunately, you were killed!\
");
Printboard(mine, ROW, COL);
break;
}
}
else
{
printf("The coordinates are illegal, please re-enter!\
");
}
\t\t\t
\t\t
}
\t
}

game.h

#pragma once
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <windows.h>
#define ROW 9
#define COL 9
#define ROWS ROW + 2
#define COLS COL + 2
#define MINE 10

void InitBoard(char board[][COLS], int rows, int cols, char a);

void Printboard(char board[][COLS], int row, int col);

void SetMine(char mine[][COLS], int row, int col);

void ShowMine(char mine[][COLS], char show[][COLS], int row, int col);