Game Rules Overview
Minesweeper is a classic puzzle game that challenges players to identify and avoid hidden mines on a grid. The objective is to reveal all non-mine cells as quickly as possible. The game ends in failure if a player accidentally clicks on a mine cell.
The game board consists of a rectangular grid where mines are randomly distributed. Different difficulty levels are available:
- Beginner: 9x9 grid with 10 mines
- Intermediate: 16x16 grid with 40 mines
- Expert: 16x30 grid with 99 mines
- Custom: User-defined grid size and mine count (maximum 24x30)
Implementation Approach
To implement Minesweeper, we need to design a data structure that can represent the game state, including the mine positions, revealed cells, and flagged cells. A two-dimensional array is suitable for representing the game board.
Our implementation will require several key components:
- Game board initialization
- Mine placement algorithm
- Cell revealing mechanism
- Adjacent mine counting
- Win/lose condition checking
Code Implementation
Header File (minesweeper.h)
#include
#include
#include
#define GRID_ROWS 9
#define GRID_COLS 9
#define BUFFER_ROWS (GRID_ROWS + 2)
#define BUFFER_COLS (GRID_COLS + 2)
#define MINE_COUNT 10
// Function prototypes
void initializeBoard(char board[BUFFER_ROWS][BUFFER_COLS], int rows, int cols, char value);
void displayBoard(char board[BUFFER_ROWS][BUFFER_COLS], int displayRows, int displayCols);
void placeMines(char board[BUFFER_ROWS][BUFFER_COLS], int rows, int cols);
void revealCell(char mineField[BUFFER_ROWS][BUFFER_COLS], char playerBoard[BUFFER_ROWS][BUFFER_COLS], int x, int y);
int countAdjacentMines(char mineField[BUFFER_ROWS][BUFFER_COLS], int x, int y);
void playGame(char mineField[BUFFER_ROWS][BUFFER_COLS], char playerBoard[BUFFER_ROWS][BUFFER_COLS], int rows, int cols);
Game Logic Implementation (minesweeper.c)
#include "minesweeper.h"
void initializeBoard(char board[BUFFER_ROWS][BUFFER_COLS], int rows, int cols, char value) {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
board[i][j] = value;
}
}
}
void displayBoard(char board[BUFFER_ROWS][BUFFER_COLS], int displayRows, int displayCols) {
printf("------ Minesweeper Game ------\n");
// Print column numbers
for (int i = 0; i <= displayCols; i++) {
printf("%d ", i);
}
printf("\n");
// Print board with row numbers
for (int i = 1; i <= displayRows; i++) {
printf("%d ", i);
for (int j = 1; j <= displayCols; j++) {
printf("%c ", board[i][j]);
}
printf("\n");
}
}
void placeMines(char board[BUFFER_ROWS][BUFFER_COLS], int rows, int cols) {
int minesPlaced = 0;
while (minesPlaced < MINE_COUNT) {
int x = rand() % rows + 1;
int y = rand() % cols + 1;
if (board[x][y] == '0') {
board[x][y] = 'M'; // 'M' represents a mine
minesPlaced++;
}
}
}
int countAdjacentMines(char mineField[BUFFER_ROWS][BUFFER_COLS], int x, int y) {
int mineCount = 0;
for (int i = x - 1; i <= x + 1; i++) {
for (int j = y - 1; j <= y + 1; j++) {
if (mineField[i][j] == 'M') {
mineCount++;
}
}
}
return mineCount;
}
void revealCell(char mineField[BUFFER_ROWS][BUFFER_COLS], char playerBoard[BUFFER_ROWS][BUFFER_COLS], int x, int y) {
if (x < 1 || x > GRID_ROWS || y < 1 || y > GRID_COLS || playerBoard[x][y] != '*') {
return;
}
if (mineField[x][y] == 'M') {
// Game over - hit a mine
playerBoard[x][y] = 'M';
return;
}
int adjacentMines = countAdjacentMines(mineField, x, y);
playerBoard[x][y] = adjacentMines + '0';
// If there are no adjacent mines, reveal all adjacent cells recursively
if (adjacentMines == 0) {
for (int i = x - 1; i <= x + 1; i++) {
for (int j = y - 1; j <= y + 1; j++) {
if (i != x || j != y) {
revealCell(mineField, playerBoard, i, j);
}
}
}
}
}
void playGame(char mineField[BUFFER_ROWS][BUFFER_COLS], char playerBoard[BUFFER_ROWS][BUFFER_COLS], int rows, int cols) {
initializeBoard(mineField, BUFFER_ROWS, BUFFER_COLS, '0');
initializeBoard(playerBoard, BUFFER_ROWS, BUFFER_COLS, '*');
placeMines(mineField, rows, cols);
int cellsRevealed = 0;
int totalCells = rows * cols - MINE_COUNT;
while (cellsRevealed < totalCells) {
displayBoard(playerBoard, rows, cols);
int x, y;
printf("Enter coordinates to reveal (row column): ");
scanf("%d %d", &x, &y);
if (x < 1 || x > rows || y < 1 || y > cols) {
printf("Invalid coordinates. Please try again.\n");
continue;
}
if (playerBoard[x][y] != '*') {
printf("This cell has already been revealed. Please try another.\n");
continue;
}
revealCell(mineField, playerBoard, x, y);
if (playerBoard[x][y] == 'M') {
printf("Game over! You hit a mine!\n");
displayBoard(mineField, rows, cols);
return;
}
cellsRevealed++;
}
printf("Congratulations! You've successfully revealed all non-mine cells!\n");
displayBoard(mineField, rows, cols);
}
Main Program (main.c)
#include "minesweeper.h"
void displayMenu() {
printf("********************\n");
printf("***** 1.play *****\n");
printf("***** 0.exit *****\n");
printf("********************\n");
}
int main() {
srand((unsigned int)time(NULL));
int choice;
do {
displayMenu();
printf("Enter your choice: ");
scanf("%d", &choice);
switch (choice) {
case 1: {
char mineField[BUFFER_ROWS][BUFFER_COLS] = {0};
char playerBoard[BUFFER_ROWS][BUFFER_COLS] = {0};
playGame(mineField, playerBoard, GRID_ROWS, GRID_COLS);
break;
}
case 0:
printf("Exiting game...\n");
break;
default:
printf("Invalid choice. Please try again.\n");
break;
}
} while (choice != 0);
return 0;
}