Primary minesweeping (C language version)

Posted by Thora_Fan on Tue, 21 Sep 2021 10:25:17 +0200

This blog mainly talks about a simple version of mine sweeping.

catalogue

1. Overall design of mine clearance project

2. Function module implementation in game function

2.1 initialize the chessboard module——   void InitBoard(char board[ROWS][COLS], int row, int col, char ret);

2.2 display chessboard function——   void DisplayBoard(char board[ROWS][COLS], int row, int col);

2.3 buried lightning function module——   void SetMine(char mine[ROWS][COLS], int row, int col, int count);

2.4 demining function module——   void MoveMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col, int count);

1. Overall design of mine clearance project

First of all, just like Sanzi, we need to build a large framework, from the simple user interface at the beginning, to the results of selecting different options, and finally to the writing of specific game content modules.

General framework:

#include<stdio.h>
int main()
{
	int input = 0;
	do
	{
		menu();  //menu
		printf("Please select");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			printf("The Minesweeper game!");
			break;
		case 0:
			printf("Quit the game!\n");
			break;
		default:
			printf("Wrong selection, reselect!\n");
			break;
		}
	} while (input);
	return 0;
}

General operation process:

The program runs first, and then determines whether to play the game through input.

For the menu (simple menu function), we can make a simple menu according to our own ideas, such as:

void menu()
{
	printf("****************************\n");
	printf("*******    1.play    *******\n");
	printf("*******    0.exit    *******\n");
	printf("****************************\n");
}

After the above is done, it is time to design the function modules in the game function in detail.

2. Function module implementation in game function

2.1 initialize the chessboard module——   void InitBoard(char board[ROWS][COLS], int row, int col, char ret);

The main function of this module is to initialize the chessboard into the content we want at the beginning of the game, so as to facilitate our later steps.

It should be noted here that the difference between minesweeping and Sanzi chess is that Sanzi chess only needs one chessboard, while minesweeping requires two chessboards, that is, two two-dimensional arrays (one for storing mine information and the other for storing mine clearance information), so as to make the overall structure clearer and simpler. Because it is two two-dimensional arrays, when designing this initialization function, you should have the address, row, column and characters of the first element of the chessboard.

The detailed code is as follows:

//statement
//Initialize chessboard
void InitBoard(char board[ROWS][COLS], int row, int col, char ret);
//definition
//Initialize chessboard
void InitBoard(char board[ROWS][COLS], int row, int col, char ret)
{
	int i = 0; 
	for (i = 0; i < row; i++)
	{
		int j = 0;
		for (j = 0; j < col; j++)
		{
			board[i][j] = ret;  //Put the content you want to initialize on the chessboard
		}
	}
}

2.2 display chessboard function——   void DisplayBoard(char board[ROWS][COLS], int row, int col);

As the name suggests, this function simply prints the chessboard so that we can see the contents in the demining process.

The detailed code is as follows:

//statement
//Print chessboard
void DisplayBoard(char board[ROWS][COLS], int row, int col);
//definition
//Print chessboard
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
	printf("------------------------------------\n");   //Split line
	int i = 0;
	for (i = 0; i <= row; i++)    //Coordinates of columns
	{
		printf("%d ", i);
	}
	printf("\n");                 //The coordinates are separated from the chessboard by a newline
	for (i = 1; i <= row; i++)
	{
		int j = 0;
		printf("%d ", i);         //Print out the coordinates of the line
		for (j = 1; j <= col; j++)
		{
			printf("%c ", board[i][j]);
		}
		printf("\n");
	}
	printf("------------------------------------\n");   //Split line
}

When designing this function, we can also add a division line up and down like the above code, and print the coordinates of travel and column at the same time, so as to make the interface effect better.

Then there are the last two links - mine laying and mine clearance.

2.3 buried lightning function module——   void SetMine(char mine[ROWS][COLS], int row, int col, int count);

The code is as follows:

//statement
//Buried mine
void SetMine(char mine[ROWS][COLS], int row, int col, int count);
//definition
//Buried mine
void SetMine(char mine[ROWS][COLS], int row, int col, int count)
{
	int x = 0;
	int y = 0;
	while (count)
	{
		x = rand() % row + 1;   //0 - 8 plus 1 becomes 1 - 9
		y = rand() % col + 1;
		if (mine[x][y] != '1')  //Judge whether there is thunder in this coordinate
		{
			mine[x][y] = '1';   //If there is no thunder, bury it
			count--;            //If the mine is buried successfully, the total number will be reduced by 1 until the count is 0
		}
	}
}

The rand function is used in the middle of the buried mine function module, so in the main function, we use the srand function and the time function to set a start time.

//Use the timestamp to determine the initial time	
srand((unsigned int)time(NULL));

2.4 demining function module——   void MoveMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col, int count);

The content of this module is the core of the real game.

The code is as follows:

//statement
//mine clearance
void MoveMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col, int count);
//definition
//mine clearance
void MoveMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col, int count)
{
	int x = 0;
	int y = 0;
	int ret = 0;
	while (1)                  //Multiple demining is required, so the cycle is used here
	{
		printf("Please enter the coordinates:");
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col)  //Judge whether it is legal coordinates
		{
			if (mine[x][y] == '1')                     //Judge whether the coordinate is thunder
			{
				printf("I'm sorry, you were killed!\n");
				break;
			}
			else if (show[x][y] != '*')                //Judge whether the coordinate has been mined
			{
				printf("Coordinates are occupied, please re-enter!\n");
			}
			else
			{
				//Count the number of surrounding mines
				show[x][y] = TotalMine(mine, x, y) + '0';
				//Print chessboard
				DisplayBoard(show, ROW, COL);
				ret++;
				if (ret == (row * col - count))      //If all the mines are found
				{
					printf("Congratulations on your success!\n");    //Game success
					DisplayBoard(mine, ROW, COL);
					break;
				}
			}
		}
		else
		{
			printf("Illegal coordinates!\n");
		}
	}
}

Note: when designing the demining function, we also designed a statistical function (used to count the number of mines around the arranged coordinates)

The code is as follows:

//statement
//Count the number of surrounding mines
int TotalMine(char mine[ROWS][COLS], int x, int y);
//definition
//Count the number of surrounding mines
int TotalMine(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');
//The principle is to add up the contents of the coordinates around the coordinates, then subtract the values of 8 initialized characters, and finally get the number of mines
}

After completing the above contents, we can connect these modules in the game.c file. Of course, we can also add some functions to make our interface more concise and clear.

The source code after connection is as follows:

//Contents in test.c file
#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 };  //Storage of mine clearing information

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

	//Print chessboard
	DisplayBoard(show, ROW, COL);

	//Buried mine
	SetMine(mine, ROW, COL, EASY_MODE);

	//DisplayBoard(mine, ROW, COL);
	
	//mine clearance
	MoveMine(mine, show, ROW, COL, EASY_MODE);
}

int main()
{
	int input = 0;
	srand((unsigned int)time(NULL));
	do
	{
		menu();  //menu
		printf("Please select");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			system("cls");
			game();
			break;
		case 0:
			system("cls");         //Clear screen
			printf("Quit the game!\n");
			break;
		default:
			printf("Wrong selection, reselect!\n");
			Sleep(1000);
			system("cls");
			break;
		}
	} while (input);
	return 0;
}
//Function declaration in game.h
#pragma once

#include<stdio.h>

#include<stdlib.h>

#include<time.h>

#include<windows.h>

#define ROW 9
#define COL 9
#define EASY_MODE 10

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

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

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

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

//mine clearance
void MoveMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col, int count);

//Count the number of surrounding mines
int TotalMine(char mine[ROWS][COLS], int x, int y);
//Definition of functions in game.c
#include"game.h"

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

//Print chessboard
void DisplayBoard(char board[ROWS][COLS], int row, int col)
{
	printf("------------------------------------\n");   //Split line
	int i = 0;
	for (i = 0; i <= row; i++)    //Coordinates of columns
	{
		printf("%d ", i);
	}
	printf("\n");                 //The coordinates are separated from the chessboard by a newline
	for (i = 1; i <= row; i++)
	{
		int j = 0;
		printf("%d ", i);         //Print out the coordinates of the line
		for (j = 1; j <= col; j++)
		{
			printf("%c ", board[i][j]);
		}
		printf("\n");
	}
	printf("------------------------------------\n");   //Split line
}

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

//Count the number of surrounding mines
int TotalMine(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');
}

//mine clearance
void MoveMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col, int count)
{
	int x = 0;
	int y = 0;
	int ret = 0;
	while (1)
	{
		printf("Please enter the coordinates:");
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col)
		{
			if (mine[x][y] == '1')
			{
				printf("I'm sorry, you were killed!\n");
				Sleep(2000);
				system("cls");
				break;
			}
			else if (show[x][y] != '*')
			{
				printf("Coordinates are occupied, please re-enter!\n");
			}
			else
			{
				//Count the number of surrounding mines
				show[x][y] = TotalMine(mine, x, y) + '0';
				system("cls");
				//Print chessboard
				DisplayBoard(show, ROW, COL);
				ret++;
				if (ret == (row * col - count))
				{
					printf("Congratulations on your success!\n");
					DisplayBoard(mine, ROW, COL);
					Sleep(5000);
					system("cls");
					break;
				}
			}
		}
		else
		{
			printf("Illegal coordinates!\n");
		}
	}
}

Topics: C