
Function description of the Minesweeper game:
• Implement the classic Minesweeper game using the console
• The game can continue or exit through the menu
• The Minesweeper board is a 9*9 grid
• By default, 10 mines are randomly placed
• Mines can be checked:
◦ If the position is not a mine, it shows how many mines are around
◦ If the position is a mine, the game ends with an explosion
◦ Successfully find all non-mine cells except for the 10 mines, the game ends
test.c // File containing the game's test logic
game.c // File containing the implementation of game functions
game.h // File containing the data types and function declarations needed for the game
Logic starts:
1. Menu
- Input 1 to enter the game, input 0 to exit the game, input other numbers to show input error and re-enter
test.c#include "game.h"
int main(){
menu();
{
regain:
printf("Please enter your choice:");
int input1;
scanf("%d", &input1);
switch (input1)
{
case 1:
{
printf("Entering the game\n");
game();
break;
}
case 0:
{
printf("Exiting the game\n");
break;
}
default:
{
printf("Input error, please re-enter:");
goto regain;
}
}
}
return 0;
}
game.c#include "game.h"
void menu(){
printf("****************\n");
printf("**** 1.Play ****\n");
printf("**** 0.Quit ****\n");
printf("****************\n");
}
game.h#pragma once
#include <stdio.h>
#include "game.h"
// Menu
void menu();
2. Generate a 9X9 game interface
- Use a two-dimensional array to implement
- Use two boards, one for display and one for setting mines, write a function to initialize the board
- Initialize the displayed board
<span>char show</span>to all<span>'*'</span>, and initialize the mine board<span>char mine</span>to all<span>0</span> - For convenience in later testing, write the function to print the board first
Added the following code to the test.c file
test.c#include "game.h"
void game(){
// Two-dimensional array for placing mines
char mine[ROWS][COLS] = { 0 };
// Two-dimensional array for the game interface
char show[ROWS][COLS] = { 0 };
// Initialize the game interface array to '*'
set_keyboard(show, ROWS, COLS, '*');
// Initialize the mine array to '0'
set_keyboard(mine, ROWS, COLS, '0');
// Print function
printf_keyboard(show, ROW, COL);
printf_keyboard(mine, ROW, COL);
}
Added the following code to the
game.c#include "game.h"
// Initialize the board
void set_keyboard(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;
}
}
}
// Display the board
void printf_keyboard(char board[ROWS][COLS], int row, int col){
printf("-------Minesweeper--------\n");
for (int r = 0; r <= row; r++)
{
printf("%d ", r);
}
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");
}
}
3. Randomly place mines
Use srand((unsigned int) time(NULL)) and rand()
Set mines to 1, mines can only be placed where char mine[x][y] == ‘0’
Added the following to the game.h
#include <time.h>
#include “stdlib.h”
#define MINE 10
void set_mine(char board[ROWS][COLS], int row, int col, int mine);
game.h#pragma once
#include <stdio.h>
#include "game.h"
#include <time.h>
#include "stdlib.h"
#define ROW 9
#define COL 9
#define ROWS ROW+3
#define COLS COL+2
#define MINE 10
// Menu
void menu();
// Initialize the board
void set_keyboard(char board[ROWS][COLS], int rows, int cols, char set);
// Display the board
void printf_keyboard(char board[ROWS][COLS], int row, int col);
// Randomly place mines
void set_mine(char board[ROWS][COLS], int row, int col, int mine);
game.c // Add the following code
// Randomly place mines
void set_mine(char board[ROWS][COLS], int row, int col, int mine){
srand((unsigned int) time(NULL));
while (mine)
{
int x = (rand() % row) + 1;
int y = (rand() % col) + 1;
if (board[x][y] == '0')
{
board[x][y] = '1';
mine--;
}
}
}
Added the following code to the test.c file
test.c
// Randomly place mines
set_mine(mine, ROW, COL, MINE);
4. Mine clearance
- Pay attention to the input coordinates, both horizontal and vertical coordinates can only be
<span>0~9</span>, other numbers will<span>report an error and re-enter</span> - The cleared coordinates should display the number of surrounding mines, if it is
<span>0</span>, expand the surrounding board (using recursion) - If the cleared coordinates are a mine, display
<span>Game Over</span> - If the input coordinates have already been checked, display
<span>This coordinate has already been cleared</span> - Determine if the game is won,
<span>The number of cleared coordinates equals the number of cells minus the mines</span>
Changed the layout of the test.c file to the following
test.cvoid game(){
// Two-dimensional array for placing mines
char mine[ROWS][COLS] = { 0 };
// Two-dimensional array for the game interface
char show[ROWS][COLS] = { 0 };
// Initialize the game interface array to '*'
set_keyboard(show, ROWS, COLS, '*');
// Initialize the mine array to '0'
set_keyboard(mine, ROWS, COLS, '0');
// Randomly place mines
set_mine(mine, ROW, COL, MINE);
// Print function
printf_keyboard(show, ROW, COL);
// printf_keyboard(mine, ROW, COL);
// Mine clearance
move_mine(show, mine, ROW, COL);
}
Added the following code to the game.c file
game.c// Calculate the number of surrounding mines
int Count_mine(char mine[ROWS][COLS], int x, int y){
return mine[x][y] - '0';
}
// Expand the board----recursion
void Open_keyboard(char show[ROWS][COLS], char mine[ROWS][COLS], int x, int y){
// Write recursion first write the end condition
// Out of bounds, return
if ((x > (ROWS - 2)) || (x < 1) || (y > (COLS - 2)) || (y < 1))
{
return;
}
// If the coordinate has been cleared, return
if (show[x][y] != '*')
{
return;
}
// Calculate the number of mines
int count = 0;
for (int i = -1; i <= 1; i++)
{
for (int j = -1; j <= 1; j++)
{
count += Count_mine(mine, x + i, y + j);
}
}
show[x][y] = count + '0';
// According to the game rules, if the coordinate shows the number of mines is not zero, return
if (show[x][y] != '0')
{
return;
}
// Expand mines
for (int i = -1; i <= 1; i++)
{
for (int j = -1; j <= 1; j++)
{
Open_keyboard(show, mine, x + i, y + j);
}
}
}
// Mine clearance
void move_mine(char show[ROWS][COLS], char mine[ROWS][COLS], int row, int col){
int x, y;
while (1)
{
printf("Please enter the coordinates to check:");
regain2:
scanf("%d %d", &x, &y);
if ((x >= 1 && x <= 9) && (y >= 1 && y <= 9))
{
if (show[x][y] == '*')
{
if (mine[x][y] == '0')
{
Open_keyboard(show,mine,x,y);
printf_keyboard(show, ROW, COL);
}
else
{
printf("Unfortunately, you hit a mine, game over\nThe positions of the mines are:");
printf_keyboard(mine, ROW, COL);
break;
}
}
else
{
printf("This coordinate has already been checked, please enter another coordinate:");
goto regain2;
}
}
else
{
printf("Input error, please re-enter:");
goto regain2;
}
// Determine win
int Remove_mine_count = 0;
for (int i = 1; i <= row; i++)
{
for (int j = 1; j <= col; j++)
{
if (show[i][j] != '*')
{
Remove_mine_count++;
}
}
}
if (Remove_mine_count == ((ROW * COL) - MINE))
{
printf("Congratulations, you have cleared all the mines, you win the game\n");
printf_keyboard(mine, ROW, COL);
break;
}
}
}
The code in the game.h file remains unchanged
game.h#pragma once
#include <stdio.h>
#include "game.h"
#include <time.h>
#include "stdlib.h"
#define ROW 9
#define COL 9
#define ROWS ROW+3
#define COLS COL+2
#define MINE 10
// Menu
void menu();
// Initialize the board
void set_keyboard(char board[ROWS][COLS], int rows, int cols, char set);
// Display the board
void printf_keyboard(char board[ROWS][COLS], int row, int col);
// Randomly place mines
void set_mine(char board[ROWS][COLS], int row, int col, int mine);
// Mine clearance
void move_mine(char show[ROWS][COLS], char mine[ROWS][COLS], int row, int col);
5. Complete code for the Minesweeper game
test.c
#include "game.h" // Include the header file required for the Minesweeper game (function declarations, macro definitions, etc.)
// Core logic function of the game, responsible for initializing game data, placing mines, and handling the mine clearance process
void game(){
// Define a two-dimensional array mine to store the position information of mines ('1' means there is a mine, '0' means no mine)
// ROWS and COLS are macro definitions, usually larger than the actual game area by 2 (to handle boundary checks and avoid out-of-bounds)
char mine[ROWS][COLS] = { 0 };
// Define a two-dimensional array show to display the interface to the player (initially '*', shows surrounding mine count or mines after clearance)
char show[ROWS][COLS] = { 0 };
// Initialize the show array, all elements set to '*' (indicating unexplored cells)
// set_keyboard is a custom function for batch initializing a two-dimensional array
set_keyboard(show, ROWS, COLS, '*');
// Initialize the mine array, all elements set to '0' (assume all cells have no mines, later randomly place mines)
set_keyboard(mine, ROWS, COLS, '0');
// Randomly place mines in the mine array, MINE is a macro definition (total number of mines)
// ROW and COL are macro definitions representing the number of rows and columns in the actual game area (smaller than ROWS and COLS by 2)
set_mine(mine, ROW, COL, MINE);
// Print the player interface (show array), showing the current unexplored cells (all '*')
printf_keyboard(show, ROW, COL);
// Debugging: print the positions of the mines (mine array), will not be shown to the player in the actual game
// printf_keyboard(mine, ROW, COL);
// Enter the mine clearance logic, player inputs coordinates, handle the clearance results (show surrounding mine count, hit mine ends, etc.)
move_mine(show, mine, ROW, COL);
}
// Main function, program entry, responsible for displaying the menu and handling user choices
int main(){
menu(); // Call the menu function to print the game menu (e.g., "1. Start Game 0. Exit Game")
{
// Local scope, isolate internal variables
regain1: // Jump label for re-entering input when input error occurs
printf("Please enter your choice:"); // Prompt user to input option (1 or 0)
int input1; // Store user input option
scanf("%d", &input1); // Read user input
// Execute corresponding operation based on user input option
switch (input1)
{
case 1: // User selects "Start Game"
{
printf("Entering the game\n"); // Prompt entering the game
game(); // Call the game function to start the Minesweeper game logic
break; // Exit switch branch
}
case 0: // User selects "Exit Game"
{
printf("Exiting the game\n"); // Prompt exiting the game
break; // Exit switch branch
}
default: // User input invalid option (not 1 or 0)
{
printf("Input error, please re-enter:"); // Prompt input error
goto regain1; // Jump to regain1 label, waiting for user input again
}
}
}
return 0; // Program ends normally
}
game.c
#include "game.h" // Include the header file required for the Minesweeper game (macro definitions, function declarations, etc.)
// Print the game menu
void menu(){
printf("****************\n");
printf("**** 1.Play ****\n"); // 1 means start game
printf("**** 0.Quit ****\n"); // 0 means exit game
printf("****************\n");
}
// Initialize the board (two-dimensional array)
// board: the two-dimensional array to be initialized
// rows, cols: the number of rows and columns of the array
// set: the character to fill for initialization (e.g., '*' or '0')
void set_keyboard(char board[ROWS][COLS], int rows, int cols, char set){
// Traverse each element of the array, set to the specified character set
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
board[i][j] = set;
}
}
}
// Display the board (print to console)
// board: the two-dimensional array to be displayed (player interface or minefield)
// row, col: the number of rows and columns in the actual game area (excluding boundaries)
void printf_keyboard(char board[ROWS][COLS], int row, int col){
printf("-------Minesweeper--------\n");
// Print column numbers (0 to col), convenient for players to locate coordinates
for (int r = 0; r <= row; r++)
{
printf("%d ", r);
}
printf("\n");
// Print each row content (including row number and corresponding cell character)
for (int i = 1; i <= row; i++)
{
printf("%d ", i); // Print row number (1 to row)
// Print each cell of the current row (from the 1st column to the col)
for (int j = 1; j <= col; j++)
{
printf("%c ", board[i][j]);
}
printf("\n"); // New line after each row ends
}
}
// Randomly place mines in the minefield array
// board: the two-dimensional array storing minefield information ('1' means there is a mine, '0' means no mine)
// row, col: the number of rows and columns in the actual game area
// mine: the total number of mines to be placed
void set_mine(char board[ROWS][COLS], int row, int col, int mine){
srand((unsigned int)time(NULL)); // Initialize random seed to ensure different mine positions each time
// Loop to place mines until the number of mines is 0
while (mine)
{
// Generate random row coordinate x from 1 to row
int x = (rand() % row) + 1;
// Generate random column coordinate y from 1 to col
int y = (rand() % col) + 1;
// If the current position has no mine (is '0'), place a mine (set to '1')
if (board[x][y] == '0') // Note: the original code had an extra semicolon here, which may be a typo, should actually be removed
{
board[x][y] = '1';
mine--; // Decrease the number of mines by 1
}
}
}
// Calculate the total number of mines in the 8 surrounding directions
// mine: minefield array
// x, y: the coordinates to check
int Count_mine(char mine[ROWS][COLS], int x, int y){
// Calculate the total number of mines in the 8 adjacent cells around the coordinate (x,y)
// Principle: Convert the character values of the surrounding 8 cells ('0' means no mine, '1' means there is a mine) to numbers and sum them up
return ( mine[x - 1][y] + // Upper cell
mine[x - 1][y - 1] + // Upper left cell
mine[x][y - 1] + // Left cell
mine[x + 1][y - 1] + // Lower left cell
mine[x + 1][y] + // Lower cell
mine[x + 1][y + 1] + // Lower right cell
mine[x][y + 1] + // Right cell
mine[x - 1][y + 1] - // Upper right cell
8 * '0' // Subtract the ASCII value of 8 '0's (convert character to number: '0'→0, '1'→1)
);
}
// Recursively expand the area without mines (when a cell has no surrounding mines, automatically expand all surrounding non-mine cells)
// show: player interface array
// mine: minefield array
// x, y: current coordinates to expand
void Open_keyboard(char show[ROWS][COLS], char mine[ROWS][COLS], int x, int y){
// Recursion end condition 1: Out of bounds (exceeding the actual game area)
if ((x > (ROWS - 2)) || (x < 1) || (y > (COLS - 2)) || (y < 1))
{
return;
}
// Recursion end condition 2: This coordinate has been explored (not '*')
if (show[x][y] != '*')
{
return;
}
// Calculate the total number of mines around the current coordinate
int count = 0;
for (int i = -1; i <= 1; i++) // Row direction: -1 (up), 0 (current), 1 (down)
{
for (int j = -1; j <= 1; j++) // Column direction: -1 (left), 0 (current), 1 (right)
{
count += Count_mine(mine, x + i, y + j); // Accumulate the number of mines in each surrounding cell
}
}
// Display the number of surrounding mines in the current cell on the player interface (character form, e.g., '0' means no mine)
show[x][y] = count + '0';
// Recursion end condition 3: If there are surrounding mines (count≠0), stop expanding
if (show[x][y] != '0')
{
return;
}
// If there are no surrounding mines (count=0), recursively expand the surrounding 8 directions
for (int i = -1; i <= 1; i++)
{
for (int j = -1; j <= 1; j++)
{
Open_keyboard(show, mine, x + i, y + j);
}
}
}
// Core logic of mine clearance
// show: player interface array
// mine: minefield array
// row, col: the number of rows and columns in the actual game area
void move_mine(char show[ROWS][COLS], char mine[ROWS][COLS], int row, int col){
int x, y; // Store the coordinates input by the player
while (1) // Loop to handle mine clearance operations until the game ends
{
printf("Please enter the coordinates to check:");
regain2: // Jump label for re-entering input when input error occurs
scanf("%d %d", &x, &y); // Read player input coordinates (x for row, y for column)
// Check if the coordinates are within valid range (1 to row, 1 to col)
if ((x >= 1 && x <= 9) && (y >= 1 && y <= 9)) // Assume row=col=9, can change to x<=row && y<=col
{
// Check if the coordinate has not been cleared (still '*')
if (show[x][y] == '*')
{
// If there is no mine at this position (mine[x][y] is '0')
if (mine[x][y] == '0')
{
Open_keyboard(show, mine, x, y); // Expand surrounding non-mine area
printf_keyboard(show, ROW, COL); // Refresh and display player interface
}
// If there is a mine at this position (mine[x][y] is '1')
else
{
printf("Unfortunately, you hit a mine, game over\nThe positions of the mines are:");
printf_keyboard(mine, ROW, COL); // Display all mine positions
break; // Exit loop, game ends
}
}
// This coordinate has already been checked
else
{
printf("This coordinate has already been checked, please enter another coordinate:");
goto regain2; // Jump to regain2, re-enter coordinates
}
}
// Invalid coordinate input (out of range)
else
{
printf("Input error, please re-enter:");
goto regain2; // Jump to regain2, re-enter coordinates
}
// Determine if the player has won (all non-mine cells have been cleared)
int Remove_mine_count = 0; // Record the number of cleared non-mine cells
for (int i = 1; i <= row; i++)
{
for (int j = 1; j <= col; j++)
{
if (show[i][j] != '*') // Non '*' means cleared
{
Remove_mine_count++;
}
}
}
// Winning condition: number of cleared cells = total cells - total mines
if (Remove_mine_count == ((ROW * COL) - MINE))
{
printf("Congratulations, you have cleared all the mines, you win the game\n");
printf_keyboard(mine, ROW, COL); // Display all mine positions
break; // Exit loop, game ends
}
}
}
game.h
#pragma once // Prevent the header file from being included multiple times (compile only once)
// Include the required standard library header files
#include <stdio.h> // Provides input and output functions (e.g., printf, scanf)
#include "game.h" // Include other game-related declarations (note: there may be circular inclusion here, should actually be avoided)
#include <time.h> // Provides time-related functions (e.g., time, used to initialize random seed)
#include "stdlib.h" // Provides standard library functions (e.g., rand, srand, used to generate random numbers)
// Macro definitions: core parameters of the game
#define ROW 9 // Number of rows in the actual game area (9 rows)
#define COL 9 // Number of columns in the actual game area (9 columns)
#define ROWS ROW+3 // Total number of rows in the minefield array (larger than the actual number of rows by 3, to handle boundaries, avoid out-of-bounds access)
#define COLS COL+2 // Total number of columns in the minefield array (larger than the actual number of columns by 2, to handle boundaries)
#define MINE 10 // Total number of mines in the game (10 mines)
// Function declarations: declare all functions used in the game (for other files to call)
// Print the game menu (e.g., start/exit options)
void menu();
// Initialize the board array
// Parameters: board- the two-dimensional array to be initialized, rows- number of rows in the array, cols- number of columns in the array, set- character to fill for initialization
void set_keyboard(char board[ROWS][COLS], int rows, int cols, char set);
// Print the displayed board (player interface or minefield)
// Parameters: board- the two-dimensional array to be displayed, row- number of rows in the actual game area, col- number of columns in the actual game area
void printf_keyboard(char board[ROWS][COLS], int row, int col);
// Randomly place mines in the minefield array
// Parameters: board- minefield array, row- number of rows in the actual game area, col- number of columns in the actual game area, mine- number of mines to be placed
void set_mine(char board[ROWS][COLS], int row, int col, int mine);
// Handle the player's mine clearance operation (core game logic)
// Parameters: show- player interface array, mine- minefield array, row- number of rows in the actual game area, col- number of columns in the actual game area
void move_mine(char show[ROWS][COLS], char mine[ROWS][COLS], int row, int col);