[mine sweeping] how to implement C language (including recursive expansion)

catalogue

Introduction to mine clearance

Realization idea

Implementation process

Code decomposition

Chessboard definition

Interactive menu()

Initialize checkerboard init_board()

Print checkerboard display()

Layout thunder set_mine()

Returns the count of mines with 8 coordinates around this coordinate_ mine()

Recursive expansion super_open_mine()

Mine sweep_mine()

Judge how many "thunder" counts are left on the chessboard_ show_ mine()

Game implementation function (game)

Test function test()

Main function ()

Code overview

Introduction to mine clearance

         The minesweeping game is to uncover all non mine grids and win. Stepping on mine grids is even a failure.   The main area of the game consists of many squares,   Click a grid randomly with the left mouse button, the grid will be opened and the numbers in the grid will be displayed. The numbers in the grid mean that several mines are hidden in the eight grids around it.

In C language, we use the way of inputting coordinates instead of mouse clicking.

The function is not introduced in this article: (I don't want to introduce it, but the blogger hasn't mastered the ability, mainly because he is lazy)

  1. Interactive difficulty selection function
  2. Marking mine function
  3. Select coordinate expansion function after marking mine

Realization idea

        First, we use three files to contain the whole program

  • Mine.h
  • Mine.c
  • test.c

Mine.h header file contains all header files and global variables required for code implementation

Mine.c source file contains the main functions implemented by the code

The test.c source file is responsible for testing the code

Implementation process

  1. Print interactive menu
  2. Initialize chessboard
  3. Lay thunder
  4. Minesweeping (recursive expansion)
  5. Judge victory
  6. Victory game is over, otherwise cycle step 4

When defining the two-dimensional array of chessboard, we need to define two arrays; An array mine is used to place the thunder position (not shown), and another array show is used to show the chess face!

Code decomposition

  • Chessboard definition

//Global variable rows and columns
#define ROW 3
#define COL 3

//Avoid array out of bounds, and add more rows and columns around the original chessboard
#define ROWS ROW+2
#define COLS COL+2
  • Interactive menu()

//Interactive menu
void menu()
{
	printf("-----------------------\n");
	printf("------ [Mine clearance]  ------\n");
	printf("------  1.start   ------\n");
	printf("------  0.sign out   ------\n");
	printf("-----------------------\n");
}
  • Initialize checkerboard init_board()

Here, we initialize the show chessboard to '*'  

Initialize the mine chessboard to '0'

//Initialize chessboard
void init_board(char board[ROWS][COLS], int row, int col, char ch)
{
	int i = 0;
	int j = 0;
	for (i = 0; i < ROWS; i++)
	{
		for (j = 0; j < COLS; j++)
		{
			board[i][j] = ch;
		}
	}
}
  • Print checkerboard display()

//Print chessboard
void display(char show[ROWS][COLS], int row, int col)
{
	int i = 0;
	int j = 0;
	for (i = 0; i <= col; i++)
	{
		//Print column coordinates
		printf("%d ", i);
	}
	printf("\n");
	for (i = 1; i <= row; i++)
	{
		//Print line coordinates
		printf("%d ", i);
		for (j = 1; j <= col; j++)
		{
			printf("%c ", show[i][j]);
		}
		printf("\n");
	}
	printf("\n");
}
  • Layout thunder set_mine()

//Number of Mines
#define COUNT 1

//Lay thunder
void set_mine(char mine[ROWS][COLS], int row, int col)
{
	int x = 0;
	int y = 0;
	int count = COUNT;
	while (count)
	{
		//Obtain random numbers and generate thunder ('1 ') on the chessboard
		x = rand() % row + 1;
		y = rand() % col + 1;
		if (mine[x][y] == '0')
		{
			mine[x][y] = '1';
			count--;
		}
	}
}
  • Returns the count of mines with 8 coordinates around this coordinate_ mine()

Note that the return type of the function here is static

//Returns the number of mines in a circle around this coordinate
static count_mine(char mine[ROWS][COLS], int x, int y)
{
	return mine[x - 1][y] +
		mine[x - 1][y - 1] +
		mine[x][y - 1] +
		mine[x + 1][y - 1] +
		mine[x + 1][y] +
		mine[x + 1][y + 1] +
		mine[x][y + 1] +
		mine[x - 1][y + 1] - 8 * '0';//ASCII value differs from numeric character by '0'
}
  • Recursive expansion super_open_mine()

Recursive expansion condition:

  1. It's not ray at this coordinate,  != ' 1'
  2. There is no thunder in the eight coordinates around this coordinate, count = 0
  3. This coordinate has not been expanded,! = '"

//Recursive expansion
void super_open_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
{
    //Obtain the mine number of eight coordinates around the coordinate
	int count = count_mine(mine, x, y);
	if (count == 0 && show[x][y] != ' ')
	{
		show[x][y] = ' ';
		
		if (x - 1 >= 0 && x <= ROW && y >= 0 && y <= COL && show[x - 1][y] == '*')
		{
			super_open_mine(mine, show, x - 1, y);
		}
		if (x + 1 >= 0 && x + 1 <= ROW && y >= 0 && y <= COL && show[x + 1][y] == '*')
		{
			super_open_mine(mine, show, x + 1, y);
		}
		if (x >= 0 && x <= ROW && y - 1 >= 0 && y - 1 <= COL && show[x][y - 1] == '*')
		{
			super_open_mine(mine, show, x, y - 1);
		}
		if (x >= 0 && x <= ROW && y + 1 >= 0 && y + 1 <= COL && show[x][y + 1] == '*')
		{
			super_open_mine(mine, show, x, y + 1);
		}
	}
	else
	{
		show[x][y] = count + '0';
	}
}
  • Mine sweep_mine()

//Check thunder
int sweep_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
	int x = 0;
	int y = 0;
	int count = 0;
	printf("Please enter minesweeping coordinates(that 's ok.column):>");
	scanf("%d.%d", &x, &y);
	if ((x >= 1 && x <= row) && (y >= 1 && y <= col))
	{
		if (mine[x][y] == '1')
		{
			return 1;
		}
		else
		{
			super_open_mine(mine, show, x, y);
			display(show, ROW, COL);
			return 0;
		}
	}
	else
	{
		printf("The coordinates entered are illegal, please re-enter!\a\n\n");
	}
	return 0;
}
  • Judge how many "thunder" counts are left on the chessboard_ show_ mine()

//Judge how many "thunder" there are on the chessboard
int count_show_mine(char show[ROWS][COLS], int row, int col)
{
	int i = 0;
	int j = 0;
	int count = 0;
	for (i = 1; i <= row; i++)
	{
		for (j = 1; j <=col; j++)
		{
			if (show[i][j] == '*')
			{
				count++;
			}
		}
	}
	return count;
}
  • Game implementation function (game)

//Game implementation function
void game()
{
	char mine[ROWS][COLS] = { 0 };
	char show[ROWS][COLS] = { 0 };
	init_board(mine, ROWS, COLS, '0');//mine initialized to '0'
	init_board(show, ROWS, COLS, '*');//show is initialized to '*'
	set_mine(mine, ROW, COL);
	//display(mine, ROW, COL);
	display(show, ROW, COL);
	while (1)
	{
		int ret = sweep_mine(mine, show, ROW, COL);
		if (ret)
		{
			printf("\n You're blown up. The game's over!\n\a");
			display(mine, ROW, COL);
			break;
		}
		int key = count_show_mine(show, ROW, COL);
		if (key == COUNT)
		{
			printf("WIN!\a\n");
			break;
		}
	}

}
  • Test function test()

//Test function
void test()
{
	srand((unsigned int)time(NULL));
	int choose = -1;
	do
	{
		menu();
		scanf("%d", &choose);
		switch (choose)
		{
		case 1:
			printf("\n Game start:\n");
			game();
			break;
		case 0:
			printf("game over...\n\a");
			break;
		default:
			printf("Input error, please re-enter!\n\a");
			break;
		}
	} while (choose);
}
  • Main function ()

//calling function 
int main(void)
{
	test();
	return 0;
}

Code overview

  • Mine.h
#pragma once

#Include < stdio. H > / / printf(), scanf() function header file
#Include < stdlib. H > / / get the timestamp header file
#Include < time. H > / / time header file

//Global variable rows and columns
#define ROW 3
#define COL 3

//Avoid array out of bounds, and add more rows and columns around the original chessboard
#define ROWS ROW+2
#define COLS COL+2

//Number of Mines
#define COUNT 1

//Function declaration
void menu();
void init_board();
void display();
void set_mine();
int sweep_mine();
  • Mine.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "Mine.h"

//Interactive menu
void menu()
{
	printf("-----------------------\n");
	printf("------ [Mine clearance]  ------\n");
	printf("------  1.start   ------\n");
	printf("------  0.sign out   ------\n");
	printf("-----------------------\n");
}

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

//Print chessboard
void display(char show[ROWS][COLS], int row, int col)
{
	int i = 0;
	int j = 0;
	for (i = 0; i <= col; i++)
	{
		//Print column coordinates
		printf("%d ", i);
	}
	printf("\n");
	for (i = 1; i <= row; i++)
	{
		//Print line coordinates
		printf("%d ", i);
		for (j = 1; j <= col; j++)
		{
			printf("%c ", show[i][j]);
		}
		printf("\n");
	}
	printf("\n");
}

//Lay thunder
void set_mine(char mine[ROWS][COLS], int row, int col)
{
	int x = 0;
	int y = 0;
	int count = COUNT;
	while (count)
	{
		//Obtain random numbers and generate thunder ('1 ') on the chessboard
		x = rand() % row + 1;
		y = rand() % col + 1;
		if (mine[x][y] == '0')
		{
			mine[x][y] = '1';
			count--;
		}
	}
}

//Returns the number of mines in a circle around this coordinate
static count_mine(char mine[ROWS][COLS], int x, int y)
{
	return mine[x - 1][y] +
		mine[x - 1][y - 1] +
		mine[x][y - 1] +
		mine[x + 1][y - 1] +
		mine[x + 1][y] +
		mine[x + 1][y + 1] +
		mine[x][y + 1] +
		mine[x - 1][y + 1] - 8 * '0';//ASCII value differs from numeric character by '0'
}

//Recursive expansion
void super_open_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
{
	int count = count_mine(mine, x, y);
	if (count == 0 && show[x][y] != ' ')
	{
		show[x][y] = ' ';
		
		if (x - 1 >= 0 && x <= ROW && y >= 0 && y <= COL && show[x - 1][y] == '*')
		{
			super_open_mine(mine, show, x - 1, y);
		}
		if (x + 1 >= 0 && x + 1 <= ROW && y >= 0 && y <= COL && show[x + 1][y] == '*')
		{
			super_open_mine(mine, show, x + 1, y);
		}
		if (x >= 0 && x <= ROW && y - 1 >= 0 && y - 1 <= COL && show[x][y - 1] == '*')
		{
			super_open_mine(mine, show, x, y - 1);
		}
		if (x >= 0 && x <= ROW && y + 1 >= 0 && y + 1 <= COL && show[x][y + 1] == '*')
		{
			super_open_mine(mine, show, x, y + 1);
		}
	}
	else
	{
		show[x][y] = count + '0';
	}
}

//Check thunder
int sweep_mine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
	int x = 0;
	int y = 0;
	int count = 0;
	printf("Please enter minesweeping coordinates(that 's ok.column):>");
	scanf("%d.%d", &x, &y);
	if ((x >= 1 && x <= row) && (y >= 1 && y <= col))
	{
		if (mine[x][y] == '1')
		{
			return 1;
		}
		else
		{
			super_open_mine(mine, show, x, y);
			display(show, ROW, COL);
			return 0;
		}
	}
	else
	{
		printf("The coordinates entered are illegal, please re-enter!\a\n\n");
	}
	return 0;
}

//Judge how many "thunder" there are on the chessboard
int count_show_mine(char show[ROWS][COLS], int row, int col)
{
	int i = 0;
	int j = 0;
	int count = 0;
	for (i = 1; i <= row; i++)
	{
		for (j = 1; j <=col; j++)
		{
			if (show[i][j] == '*')
			{
				count++;
			}
		}
	}
	return count;
}

  • test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "Mine.h"

//Game implementation function
void game()
{
	char mine[ROWS][COLS] = { 0 };
	char show[ROWS][COLS] = { 0 };
	init_board(mine, ROWS, COLS, '0');
	init_board(show, ROWS, COLS, '*');
	set_mine(mine, ROW, COL);
	//display(mine, ROW, COL);
	display(show, ROW, COL);
	while (1)
	{
		int ret = sweep_mine(mine, show, ROW, COL);
		if (ret)
		{
			printf("\n You're blown up. The game's over!\n\a");
			display(mine, ROW, COL);
			break;
		}
		int key = count_show_mine(show, ROW, COL);
		if (key == COUNT)
		{
			printf("WIN!\a\n");
			break;
		}
	}

}

//Test function
void test()
{
	srand((unsigned int)time(NULL));
	int choose = -1;
	do
	{
		menu();
		scanf("%d", &choose);
		switch (choose)
		{
		case 1:
			printf("\n Game start:\n");
			game();
			break;
		case 0:
			printf("game over...\n\a");
			break;
		default:
			printf("Input error, please re-enter!\n\a");
			break;
		}
	} while (choose);
}

//calling function 
int main(void)
{
	test();
	return 0;
}

Tags: C Algorithm

Posted on Wed, 17 Nov 2021 09:16:22 -0500 by uwannadonkey