Easy Minesweeper Game

Posted by veroaero on Wed, 01 Dec 2021 06:59:05 +0100

I believe that everyone has played a minesweeper game. After learning the two-dimensional array, I also wrote a simple Minesweeper game rule in c language as follows:

1. Set the game's board size by using macro Row and macro List (Row and List are 12 If you want to play 10x10 minesweeper);

2. Set the number of mines in the board by macro BoomNumber (the number of Mines needs to be <=(Row-2)*(List-2));

3. Enter the coordinates to be scanned for the user. If there are mines, the thunder explosion game is over. If there are no mines, count the number of mines around the coordinates, and loop the operation until all the unscanned places on the board are mines.

#pragma warning (disable:4996)
#pragma once
#include<stdio.h>
#include<time.h>
#include<stdlib.h>
#define Row 12
#define List 12
#define BoomNumber 20
#Define Boom'1'//1 is lightning
#define nice '0'
extern void Game();
extern void SetMine(char MineBoard, int row, int list);
extern void Select(char MineBoard, int row, int list);
extern void Menu();
extern void CountBoom(char MineBoard[][List], int row, int list, int x, int y);

This is the header file of the Minesweeper game where the declared functions and defined macros are explained below

The key to the problem is:

1. How to randomly bury BoomNumber mines into the board

2. When the user chooses the coordinates of the minesweeper, the system finds that there are no mines here How to count the number of surrounding mines and make them visible to the user

Considering that the user only needs to know where the system is buried after the thunder explosion, and the user does not need to see where the mines are buried for the rest of the time, for convenience we need to set up two chessboards, one for burying the mines and the other for showing to the user, with the chessboard crossed and vertically, so we consider burying the mines for the MineBoard[Row][List] ShowBoard[Row][List] is displayed to the user, and we set both arrays to char type for memory issues;

The problem of the chessboard is solved, so we need to bury mines before the user chooses coordinates for the first time. 2. ShowBoard arrays are shown, because BoomNumber thunders need to be buried randomly, so we use the random number method to make the system generate coordinates randomly without duplicate coordinates. Boom is buried in the generated coordinate locations, and nice is buried in the rest locations (without thunder), because the burying of thunder is a few operations. First, we initialize the elements in the MineBoard array to be all nice;

void SetMine(char MineBoard[][List], int row, int list)
{
	for (int i = 0;i < row;i++)
	{
		for (int j = 0;j < list;j++)
		{
			MineBoard[i][j] =nice;
		}
	}//Mine-free is nice
	int num = 0;
	int _x;
	int _y;
	while (num < BoomNumber)
	{
		_x = 1 + rand()%(Row-2);
		_y = 1 + rand()%(Row-2);
		if (MineBoard[_x][_y] != Boom)
		{
			MineBoard[_x][_y] = Boom;
			num++;
		}
	}
}

ShowBoard is shown to the user when the burying is completed

void ShowBoards(char ShowBoard[][List], int row, int list)
{
	printf("  ");
	for (int x = 1;x < list - 1;x++)
	{
		printf(" %2d ",x);
	}
	printf("\n");
	for (int i = 1;i < row-1;i++)
	{
		printf(" %2d",i);
		for (int j = 1;j < list-1;j++)
		{
			printf(" %c |",ShowBoard[i][j]);
		}
		printf("\n");
		printf("   ");
		for (int k = 0;k < row - 2;k++)
		{
			printf("----");
		}
		printf("\n");
	}
}

At this point the user chooses the coordinate to scan, counts the number of thunders around it if there are no thunders, and the game ends if there are thunders

Considering that user-entered coordinates may have been scanned or that user-entered coordinates are not within the range of (1.1)~ (Row-2, Row-2), we want to remind user that the coordinates they entered and the coordinates they were scanned or entered are not valid until the user has scanned all the coordinates in Boom.

void Select(char ShowBoard[Row][List], char MineBoard[][List], int row, int list)
{
	int step = 0;
	int x = 0;
	int y = 0;
	while (step < ((row - 2) * (list - 2) - BoomNumber))
	{
		printf("Please enter the coordinates you want to clear the mine:(x,y)\n");
		scanf("%d,%d", &x, &y);
		if (x > 0 && x < (List-1) && y>0 && y < (List-1))
		{
			if (ShowBoard[x][y] == 42)
			{
				if (MineBoard[x][y] == nice)
				{
					CountBoom(ShowBoard, MineBoard, Row, List,x,y);
					system("cls");
					ShowBoards(ShowBoard, Row, List);
					step++;
					if (step == ((row - 2) * (list - 2) - BoomNumber))
					{
						printf("Minesweeper success!\n");
						Menu();
					}
				}
				else if(MineBoard[x][y] == Boom)
				{
					system("cls");
					printf("You've been blown up! Game over\n");
					ShowMineBoard(MineBoard, Row, List);
				}
			}
			else {
				printf("This has been scanned,Please enter legal coordinates\n");
			}
		}
		else {
			printf("Please enter legal coordinates\n");
		}
	}
}

Counting the number of mines around the coordinates chosen by the user and displaying this number on ShowBoard, I used the sprintf function to convert numbers to characters (because we defined the ShowBoard array as the char type) when counting the number of mines because the MineBoard array is also the char type when adding up the number of mines at eight locations around (x, y) using the Boom ASCII code value. Since the thunder is''1'(ascii value 49) and no thunder is''0' (ascii value 48), it is necessary to subtract 8''0'ASCII code values after operation, and then go back to define the two chessboards. We only need 10x10 chessboards but have 12x12 chessboards defined. This is to facilitate counting the number of thunders around the edge chessboard

void CountBoom(char ShowBoard[Row][List],char MineBoard[][List], int row, int list, int x, int y)
{
	int a = MineBoard[x][y + 1]\
		+ MineBoard[x + 1][y + 1] + MineBoard[x - 1][y + 1] \
		+ MineBoard[x][y - 1] + MineBoard[x + 1][y - 1] \
		+ MineBoard[x - 1][y - 1] + MineBoard[x - 1][y] \
		+ MineBoard[x + 1][y] - 384;
	char  arr[32];//Set a larger array to prevent overflow
   sprintf(arr, "%d", a);//Convert Numbers to Characters
	ShowBoard[x][y] = arr[0];
}

The main logic of the Minesweeper game has now been sorted out

#include"FindMine.h"
void Menu()
{
	printf("*****1.Start the game*****\n");
	printf("*****2.Exit Game*****\n");
	printf("Please select:\n");
	int a = 0;
	scanf("%d", &a);
	system("cls");
	if (a == 1)
	{
		Game();
	}
	else if (a == 2)
	{
		exit(0);
	}
	else {
		printf("Error in input, please reselect\n");
		Menu();
	}
}
void Game()
{
	char ShowBoard[Row][List];
	for (int i = 0;i < Row;i++)
	{
		for (int j = 0;j < List;j++)
		{
			ShowBoard[i][j] = '*';
		}
	}
	char MineBoard[Row][List];
	SetMine(MineBoard, Row, List);
	ShowBoards(ShowBoard, Row, List);
	Select(ShowBoard, MineBoard, Row, List);
}
int main()
{
	srand((unsigned int)time(NULL));
	Menu();
	return 0;
}

These are user-visible functions

#include"FindMine.h"
void ShowBoards(char ShowBoard[][List], int row, int list)
{
	printf("  ");
	for (int x = 1;x < list - 1;x++)
	{
		printf(" %2d ",x);
	}
	printf("\n");
	for (int i = 1;i < row-1;i++)
	{
		printf(" %2d",i);
		for (int j = 1;j < list-1;j++)
		{
			printf(" %c |",ShowBoard[i][j]);
		}
		printf("\n");
		printf("   ");
		for (int k = 0;k < row - 2;k++)
		{
			printf("----");
		}
		printf("\n");
	}
}
void ShowMineBoard(char MineBoard[][List], int row, int list)
{
	for (int i = 1;i < row-1;i++)
	{
		for (int j = 1;j < list-1;j++)
		{
			printf("%c", MineBoard[i][j]);
		}
		printf("\n");
	}
	Menu();
}
void CountBoom(char ShowBoard[Row][List],char MineBoard[][List], int row, int list, int x, int y)
{
	int a = MineBoard[x][y + 1]\
		+ MineBoard[x + 1][y + 1] + MineBoard[x - 1][y + 1] \
		+ MineBoard[x][y - 1] + MineBoard[x + 1][y - 1] \
		+ MineBoard[x - 1][y - 1] + MineBoard[x - 1][y] \
		+ MineBoard[x + 1][y] - 384;
	char  arr[32];//Set a larger array to prevent overflow
   sprintf(arr, "%d", a);//Convert Numbers to Characters
	ShowBoard[x][y] = arr[0];
}
void Select(char ShowBoard[Row][List], char MineBoard[][List], int row, int list)
{
	int step = 0;
	int x = 0;
	int y = 0;
	while (step < ((row - 2) * (list - 2) - BoomNumber))
	{
		printf("Please enter the coordinates you want to clear the mine:(x,y)\n");
		scanf("%d,%d", &x, &y);
		if (x > 0 && x < (List-1) && y>0 && y < (List-1))
		{
			if (ShowBoard[x][y] == 42)
			{
				if (MineBoard[x][y] == nice)
				{
					CountBoom(ShowBoard, MineBoard, Row, List,x,y);
					system("cls");
					ShowBoards(ShowBoard, Row, List);
					step++;
					if (step == ((row - 2) * (list - 2) - BoomNumber))
					{
						printf("Minesweeper success!\n");
						Menu();
					}
				}
				else if(MineBoard[x][y] == Boom)
				{
					system("cls");
					printf("You've been blown up! Game over\n");
					ShowMineBoard(MineBoard, Row, List);
				}
			}
			else {
				printf("This has been scanned,Please enter legal coordinates\n");
			}
		}
		else {
			printf("Please enter legal coordinates\n");
		}
	}
}
void SetMine(char MineBoard[][List], int row, int list)
{
	for (int i = 0;i < row;i++)
	{
		for (int j = 0;j < list;j++)
		{
			MineBoard[i][j] =nice;
		}
	}//Mine-free is nice
	int num = 0;
	int _x;
	int _y;
	while (num < BoomNumber)
	{
		_x = 1 + rand()%(Row-2);
		_y = 1 + rand()%(Row-2);
		if (MineBoard[_x][_y] != Boom)
		{
			MineBoard[_x][_y] = Boom;
			num++;
		}
	}
}

These are the functions that need to be called in the Game function

Topics: C data structure Dynamic Programming