C language to implement minesweeping (expand, mark, revoke, judge victory, etc., with source code)

Table of Contents

  • 1. Game ideas
  • 2. Implementation steps
  • 1. Build menu
  • 2. Defining the Minesweeper Zone
  • 3. Board initialization
  • 4. Checkerboard printing
  • 5. Thunder
  • 6. Find Thunder
  • 7. Determine the number of mines around the selected coordinates and expand the mines
  • 8. Mark Ray, Undo Ray
  • 9. Determine win conditions
  • 3. Source code
  • 1.test.c
  • 2.game.h
  • 3. game.c

1. Game ideas

1. Create a menu interface function
2. Store Lei’s information
3. Initialize the minesweeper board and print the displayed minesweeper board
4. Information about laying out mines
5. Enter the coordinates of the mine to be checked.
6. Check out whether the coordinates are mines. Arranged mines store characters (1) and not place characters (0)
7. There are 3 situations when inputting coordinates: Unfortunately, you were killed by the bomb! , This location has already been viewed! , illegal coordinates, please re-enter
8. Whether to mark mine and whether to revoke mine
9. Determine whether all the marked mines coincide with minefields, if so, win

2. Implementation steps

1. Build menu

void menu()
{<!-- -->
printf("-----------------------------\\
");
printf("| 1. Minesweeper |\\
");
printf("| 0. exit |\\
");
printf("-----------------------------\\
");
}

2. Define the minesweeping area

#define ROW 9
#define COL 9
#define ROWS ROW + 2
#define COLS COL + 2

1. Use macros to define rows and columns
2. Print out the chessboard of ROWxCOL, but initialize the chessboard of ROWSxCOLS, which is convenient for judging whether there are mines in the 8 grids around the side rows and columns
3. It is beneficial to change the size of the chessboard

Support multiple rows and columns

3. Chessboard initialization

char mine[ROWS][COLS]; //Define mine array
char show[ROWS][COLS]; //Definition view array
//Initialize the array
Initboard(mine,ROWS,COLS,'0'); //Initialize the minefield to 0
Initboard(show, ROWS, COLS, '*');//Initialize the viewing area to *
void Initboard(char board[ROWS][COLS], int rows, int cols, char set)
{<!-- -->
int i = 0;
for (i = 0; i < rows; i ++ ) // less initialization or more printing will result in error overflow
{<!-- -->
int j = 0;
for (j = 0; j < cols; j ++ )
{<!-- -->
board[i][j] = set;
}
}
}
  1. Define two 2D arrays
    2. One for mine storage and one for mine clearance
    3. According to the coordinates of the viewing array, it is implanted into the minesweeping array, and the two are connected

4. Checkerboard printing

The array of mines can be printed during the test
Here only print view array
Note that only boards of size ROWxCOL are printed! !

//Display(mine, ROW, COL);//Print it out to see
Display(show, ROW, COL);//Print it out to see
void Display(char board[ROWS][COLS], int row, int col)
{<!-- -->
int i = 0;
int j = 0;
for (j = 1; j <= col; j ++ )
{<!-- -->
if (j < 10)
{<!-- -->
printf("|(%d)", j);
}
else
{<!-- -->
printf("| %d", j);
}

}
printf("|");
printf("\\
");
for (i = 1; i <= row; i ++ )
{<!-- -->
for (j = 1; j <= col; j ++ )
{<!-- -->
printf("|---");
}
printf("|");
printf("\\
");
for (j = 1; j <= col; j ++ )
{<!-- -->
printf("| %c ",board[i][j]);
}
printf("|");
printf("(%d)", i);
printf("\\
");
}
for (j = 1; j <= col; j ++ )
{<!-- -->
printf("|---");
}
printf("|");
printf("\\
");
}

renderings

5. Thunderbolt

#define EASY_COUNT 10

1. Define the number of mines (simple)
2. Multiple setting branches can be selected to achieve the effect of multiple difficulties
3. Provide judgment conditions for judging victory

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

1. Use random numbers to change the grid with the character ‘0’ in the minefield array into the grid with the character ‘1’
2. Remember to set a timestamp when using random numbers

6. Find Thunder

void Find_Mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{<!-- -->
int x = 0;
int y = 0;
int c = 0;
while (c != EASY_COUNT) // loop end condition
{<!-- -->
printf("Please enter the coordinates to be viewed:> ");
scanf("%d%d", &x, &y);
if (x >= 1 & amp; & amp; x <= row & amp; & amp; y >= 1 & amp; & amp; y <= col)
{<!-- -->
if (show[x][y] != '*')
{<!-- -->
printf("This location has been viewed!\\
");
continue;
}
if (mine[x][y] == '1')
{<!-- -->
printf("Unfortunately you were killed!!\\
");
Display(mine, ROW, COL);//Print out the minefield board after the explosion to let players see the distribution of minefields
break;
}
else
{<!-- -->
None_mine(mine, show, x, y);//Expand no minefield
Display(show, row, col); //print the expanded array
Define_mine(mine, show, ROW, COL);//mark mine
system("cls");//clear screen
Display(show, row, col); //print the array with marked mine after clearing the screen
c = Iswin(mine, show, row, col);//judging victory
}
}
else
printf("The coordinates are illegal, please re-enter!\\
");
}
printf("Congratulations on your victory!!\\
");
}

1. Generally, our input coordinates start from (1, 1), so it is necessary to judge whether the input coordinates are legal
if (x >= 1 & amp; & amp; x <= row & amp; & amp; y >= 1 & amp; & amp; y <= col)
2. Determine the end condition of the loop, which is the victory sign
while (c != EASY_COUNT)
Here, c is the return value of the Iswin function. For details, see the following judging victory conditions
3. If the input coordinates are legal and not mines, judge the number of mines around and determine whether to expand
Implemented with None_mine(mine, show, x, y); function

7. Determine the number of mines around the selected coordinates and expand the mines

int get_mine(char mine[ROWS][COLS], int x, int y)
{<!-- -->
int i = 0;
int count = 0;
for (i = x - 1; i <= x + 1; i + + )
{<!-- -->
int j = 0;
for (j = y - 1; j <= y + 1; j + + )
{<!-- -->
if (mine[i][j] == '1')
{<!-- -->
count + + ;//Judging the surrounding 9 grids, + 1 if there is thunder
}
}
}
return count; //Important! ! ! , if you don’t write here, there will be problems, you can try it yourself
}
void None_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
{<!-- -->
if (x >= 1 & amp; & amp; x <= ROW & amp; & amp; y >= 1 & amp; & amp; y <= COL)//judging the legality of coordinates
{<!-- -->
int count = get_mine(mine, x, y);
if (count != 0)//indicates that there is thunder
{<!-- -->
show[x][y] = count + '0';//quantity + '0' can get the character 'quantity', see the online ASCII code table
}
else if (show[x][y] != ' ')//There are no mines around, and if there are grids around! =' ', execute
{<!-- -->
show[x][y] = ' '; //Convert the grid without thunder into ' ';
int i = 0;
for (i = x - 1; i <= x + 1; i + + )
{<!-- -->
int j = 0;
for (j = y - 1; j <= y + 1; j + + )
{<!-- -->
None_mine(mine, show, i, j);//Recursively, judge the 8 grids around the grid to be expanded until there are mines around the expanded grid
}
}
}
else
{<!-- -->
return;
}
}
}

8. Mark mine, undo mine

1. If there is a definite mine coordinate, input it to mark it
2. If the mark is wrong, it can be undone in the next mark

void Define_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{<!-- -->
int x = 0;
int y = 0;
char ch = 0;
while (1)
{<!-- -->
printf("Is there a definite one that needs to be marked? (y/n/undo: d):-> ");
while (ch = getchar() != '\\
');
{<!-- -->
;
}
ch = getchar();
switch(ch)
{<!-- -->
case 'y':
while (1)
{<!-- -->
printf("Please enter the coordinates to be marked: -> ");
scanf("%d%d", &x, &y);
{<!-- -->
if (x >= 1 & amp; & amp; x <= row & amp; & amp; y >= 1 & amp; & amp; y <= col)
{<!-- -->
if (show[x][y] == '*')
{<!-- -->
show[x][y] = '!';//There is another layer
printf("Is there any coordinates that need to be marked? (y/n ");
while (ch = getchar() != '\\
');
{<!-- -->
;
}
ch = getchar();
switch (ch)
{<!-- -->
case 'y':
while (1)
{<!-- -->
printf("Please enter the coordinates to be marked: -> ");
scanf("%d%d", &x, &y);
{<!-- -->
if (x >= 1 & amp; & amp; x <= row & amp; & amp; y >= 1 & amp; & amp; y <= col)
{<!-- -->
if (show[x][y] == '*')
{<!-- -->
show[x][y] = '!';
goto end;
}
else
{<!-- -->
printf("The coordinate has been judged, please try again!!\\
");
}
}
else
{<!-- -->
printf("The coordinates are illegal, please re-enter!\\
");
}
}
}
break;
case 'n':
goto end;
break;
default:
printf("Input error, please re-enter!\\
");
break;
}
}
else
{<!-- -->
printf("The coordinate has been judged, please try again!!\\
");
}
}
else
{<!-- -->
printf("The coordinates are illegal, please re-enter!\\
");
}
}
}
break;
case 'n':
goto end;
break;
case 'd':
printf("Is there a certain mine that needs to be undone? (y/n):-> ");
while (ch = getchar() != '\\
');
{<!-- -->
;
}
ch = getchar();
switch (ch)
{<!-- -->
case 'y':
while (1)
{<!-- -->
printf("Please enter the coordinates to cancel: -> ");
scanf("%d%d", &x, &y);
{<!-- -->
if (x >= 1 & amp; & amp; x <= row & amp; & amp; y >= 1 & amp; & amp; y <= col)
{<!-- -->
if (show[x][y] == '!')
{<!-- -->
show[x][y] = '*';
printf("Is there any confirmation that needs to be revoked? (y/n):-> ");
while (ch = getchar() != '\\
');
{<!-- -->
;
}
ch = getchar();
switch (ch)
{<!-- -->
case 'y':
while (1)
{<!-- -->
printf("Please enter the coordinates to cancel: -> ");
scanf("%d%d", &x, &y);
{<!-- -->
if (x >= 1 & amp; & amp; x <= row & amp; & amp; y >= 1 & amp; & amp; y <= col)
{<!-- -->
if (show[x][y] == '!')
{<!-- -->
show[x][y] = '*';
}
else
{<!-- -->
printf("The coordinate has been judged, please try again!!\\
");
}
}
else
{<!-- -->
printf("The coordinates are illegal, please re-enter!\\
");
}
}
}
break;
case 'n':
goto end;
break;
default:
printf("Input error, please re-enter!\\
");
break;
}

}
else
{<!-- -->
printf("The coordinate has been judged, please try again!!\\
");
}
}
else
{<!-- -->
printf("The coordinates are illegal, please re-enter!\\
");
}
}
}
break;
case 'n':
goto end;
break;
default:
printf("Input error, please re-enter!\\
");
break;
}
default:
printf("Input error, please re-enter!\\
");
break;
}
}
end:
return;
}

1. Here is nested while with switch. Since both of them contain break, I used a bad code-goto to break out of the loop.
2. My code as a whole is not concise at all, and it is nested twice, and can only be marked/undone twice. Maybe it will be simpler and more concise to use a loop here. Readers can try it by themselves
3. Replace 'asterisk' with '! ’ to mark Lei, maybe it can be replaced with a character you are satisfied with!
4. Revocation of Lei is nothing more than putting '! ’ in replace with (asterisk’)
5. It is very important to judge the legality of the coordinates when marking or canceling
6. Or you can write mark mine and undo mine as multiple functions nested for use, which will be more beautiful!
Look at the picture!
Marked Thunder (3, 3)

Revoked Ray (3, 3)

9. Determine the winning condition

int Iswin(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{<!-- -->
int i = 0;
int win = 0;
for (i = 1; i <= row; i ++ )
{<!-- -->
int j = 0;
for (j = 1; j <= col; j ++ )
{<!-- -->
if (show[i][j] == '!' & amp; & amp; mine[i][j] == '1')
win ++ ;
}
}
return win;
}

1. When the '! ' character is equal to the '1' character in the mine array and the coordinates are consistent, win + 1
When win is equal to EASY_COUNT, jump out of the previous loop and win
while (c != EASY_COUNT)
2. If the marked mine does not match the win, it will not be + 1. At this time, there may be a misjudged mine, and it needs to be cancelled.
3. If the show array is all marked as '! ’, that will also win, this is also a small bug, right ! ’ The character limit can solve this problem, please try it yourself, hee hee

All'! ’ Match Ray to win! !

3. Source code

1.test.c

#define _CRT_SECURE_NO_WARNINGS
#include "game.h"

void menu()
{<!-- -->
printf("-----------------------------\\
");
printf("| 1. Minesweeper |\\
");
printf("| 0. exit |\\
");
printf("-----------------------------\\
");
}
void game()
{
char mine[ROWS][COLS]; //Define mine array
char show[ROWS][COLS]; //Definition view array
//Initialize the array
Initboard(mine,ROWS,COLS,'0'); //Initialize the minefield to 0
Initboard(show, ROWS, COLS, '*');//Initialize the viewing area to *
//Display(mine, ROW, COL);//Print it out to see
Display(show, ROW, COL);//Print it out to see
// mine
Set_Mine(mine, ROW, COL);// mine
//Display(mine, ROW, COL);
Find_Mine(mine, show, ROW, COL);
//Display(show, ROW, COL);
}

void test()
{
int input = 0;
do {
srand((unsigned)time(NULL));
menu();
printf("Please select -> ");
scanf("%d", &input);
switch (input)
{
case 1:
printf("Start minesweeping\\
");
game();
break;
case 0:
printf("Exit the game\\
");
break;
default:
printf("Input error, please re-enter\\
");
break;
}
} while (input);

}


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

2.game.h

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <windows.h>


#define ROW 9
#define COL 9
#define ROWS ROW + 2
#define COLS COL + 2
#define EASY_COUNT 10

void Initboard(char board[ROWS][COLS], int rows, int cols, char set);
void Display(char board[ROWS][COLS], int row, int col);
void Set_Mine(char mine[ROWS][COLS], int row, int col);
void Find_Mine(char mine[ROWS][COLS],char show[ROWS][COLS],int row,int col);

void None_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y);
void Define_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
int Iswin(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
int get_mine(char mine[ROWS][COLS], int x, int y);

3.game.c

#define _CRT_SECURE_NO_WARNINGS
#include "game.h"

void Initboard(char board[ROWS][COLS], int rows, int cols, char set)
{<!-- -->
int i = 0;
for (i = 0; i < rows; i ++ ) // less initialization or more printing will result in error overflow
{<!-- -->
int j = 0;
for (j = 0; j < cols; j ++ )
{<!-- -->
board[i][j] = set;
}
}
}
void Display(char board[ROWS][COLS], int row, int col)
{<!-- -->
int i = 0;
int j = 0;
for (j = 1; j <= col; j ++ )
{<!-- -->
if (j < 10)
{<!-- -->
printf("|(%d)", j);
}
else
{<!-- -->
printf("| %d", j);
}

}
printf("|");
printf("\\
");
for (i = 1; i <= row; i ++ )
{<!-- -->
for (j = 1; j <= col; j ++ )
{<!-- -->
printf("|---");
}
printf("|");
printf("\\
");
for (j = 1; j <= col; j ++ )
{<!-- -->
printf("| %c ",board[i][j]);
}
printf("|");
printf("(%d)", i);
printf("\\
");
}
for (j = 1; j <= col; j ++ )
{<!-- -->
printf("|---");
}
printf("|");
printf("\\
");
}

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

int get_mine(char mine[ROWS][COLS], int x, int y)
{
int i = 0;
int count = 0;
for (i = x - 1; i <= x + 1; i + + )
{
int j = 0;
for (j = y - 1; j <= y + 1; j + + )
{
if (mine[i][j] == '1')
{
count + + ;
}
}
}
return count; //Important! ! !
}

void None_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
{
if (x >= 1 & amp; & amp; x <= ROW & amp; & amp; y >= 1 & amp; & amp; y <= COL)
{
int count = get_mine(mine, x, y);
if (count != 0)
{
show[x][y] = count + '0';
}
else if (show[x][y] != ' ')
{
show[x][y] = ' ';
int i = 0;
for (i = x - 1; i <= x + 1; i + + )
{
int j = 0;
for (j = y - 1; j <= y + 1; j + + )
{
None_mine(mine, show, i, j);
}
}
}
else
{
return;
}
}
}

void Find_Mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
int c = 0;
while (c != EASY_COUNT) // loop end condition
{
printf("Please enter the coordinates to be viewed:> ");
scanf("%d%d", &x, &y);
if (x >= 1 & amp; & amp; x <= row & amp; & amp; y >= 1 & amp; & amp; y <= col)
{
if (show[x][y] != '*')
{
printf("This location has been viewed!\\
");
continue;
}
if (mine[x][y] == '1')
{
printf("Unfortunately you were killed!!\\
");
Display(mine, ROW, COL);
break;
}
else
{
None_mine(mine, show, x, y);//Expand no minefield
Display(show, row, col); //print the expanded array
Define_mine(mine, show, ROW, COL);//mark mine
system("cls");//clear screen
Display(show, row, col); //print the array with marked mine after clearing the screen
c = Iswin(mine, show, row, col);//judging victory
}
}
else
printf("The coordinates are illegal, please re-enter!\\
");
}
printf("Congratulations on your victory!!\\
");
}

void Define_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
int x = 0;
int y = 0;
char ch = 0;
while (1)
{
printf("Is there a definite one that needs to be marked? (y/n/undo: d):-> ");
while (ch = getchar() != '\\
');
{
;
}
ch = getchar();
switch(ch)
{
case 'y':
while (1)
{
printf("Please enter the coordinates to be marked: -> ");
scanf("%d%d", &x, &y);
{
if (x >= 1 & amp; & amp; x <= row & amp; & amp; y >= 1 & amp; & amp; y <= col)
{
if (show[x][y] == '*')
{
show[x][y] = '!';//There is another layer
printf("Is there any coordinates that need to be marked? (y/n) ");
while (ch = getchar() != '\\
');
{
;
}
ch = getchar();
switch (ch)
{
case 'y':
while (1)
{
printf("Please enter the coordinates to be marked: -> ");
scanf("%d%d", &x, &y);
{
if (x >= 1 & amp; & amp; x <= row & amp; & amp; y >= 1 & amp; & amp; y <= col)
{
if (show[x][y] == '*')
{
show[x][y] = '!';
goto end;
}
else
{
printf("The coordinate has been judged, please try again!!\\
");
}
}
else
{
printf("The coordinates are illegal, please re-enter!\\
");
}
}
}
break;
case 'n':
goto end;
break;
default:
printf("Input error, please re-enter!\\
");
break;
}
}
else
{
printf("The coordinate has been judged, please try again!!\\
");
}
}
else
{
printf("The coordinates are illegal, please re-enter!\\
");
}
}
}
break;
case 'n':
goto end;
break;
case 'd':
printf("Is there a certain mine that needs to be undone? (y/n):-> ");
while (ch = getchar() != '\\
');
{
;
}
ch = getchar();
switch (ch)
{
case 'y':
while (1)
{
printf("Please enter the coordinates to cancel: -> ");
scanf("%d%d", &x, &y);
{
if (x >= 1 & amp; & amp; x <= row & amp; & amp; y >= 1 & amp; & amp; y <= col)
{
if (show[x][y] == '!')
{
show[x][y] = '*';
printf("Is there any confirmation that needs to be revoked? (y/n):-> ");
while (ch = getchar() != '\\
');
{
;
}
ch = getchar();
switch (ch)
{
case 'y':
while (1)
{
printf("Please enter the coordinates to cancel: -> ");
scanf("%d%d", &x, &y);
{
if (x >= 1 & amp; & amp; x <= row & amp; & amp; y >= 1 & amp; & amp; y <= col)
{
if (show[x][y] == '!')
{
show[x][y] = '*';
}
else
{
printf("The coordinate has been judged, please try again!!\\
");
}
}
else
{
printf("The coordinates are illegal, please re-enter!\\
");
}
}
}
break;
case 'n':
goto end;
break;
default:
printf("Input error, please re-enter!\\
");
break;
}

}
else
{
printf("The coordinate has been judged, please try again!!\\
");
}
}
else
{
printf("The coordinates are illegal, please re-enter!\\
");
}
}
}
break;
case 'n':
goto end;
break;
default:
printf("Input error, please re-enter!\\
");
break;
}
default:
printf("Input error, please re-enter!\\
");
break;
}
}
end:
return;
}

int Iswin(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{<!-- -->
int i = 0;
int win = 0;
for (i = 1; i <= row; i ++ )
{<!-- -->
int j = 0;
for (j = 1; j <= col; j ++ )
{<!-- -->
if (show[i][j] == '!' & amp; & amp; mine[i][j] == '1')
win ++ ;
}
}
return win;
}

Ok, this is the end of this article
If there is anything that you don’t understand and needs to be improved, please leave a message!