用C写一个完整的扫雷游戏
时间: 2023-06-14 18:02:37 浏览: 243
以下是一个基于终端的简单扫雷游戏的C代码示例:
```C
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define ROWS 10 // 行数
#define COLS 10 // 列数
#define MINES 10 // 雷的数量
void init_board(int board[ROWS][COLS], int rows, int cols, int value);
void print_board(int board[ROWS][COLS], int rows, int cols);
void set_mines(int board[ROWS][COLS], int rows, int cols, int mines);
int get_adjacent_mines(int board[ROWS][COLS], int row, int col);
void reveal_board(int board[ROWS][COLS], int rows, int cols, int row, int col);
int check_win(int board[ROWS][COLS], int rows, int cols, int mines);
int main(void) {
int board[ROWS][COLS];
int mines = MINES;
int row, col;
char action;
srand(time(NULL)); // 用时间种子初始化随机数生成器
printf("Welcome to Minesweeper!\n\n");
init_board(board, ROWS, COLS, 0); // 初始化棋盘
set_mines(board, ROWS, COLS, mines); // 设置雷
do {
printf("\n");
print_board(board, ROWS, COLS); // 打印当前棋盘
printf("\nEnter row and column (e.g. 3 4), or 'f' or 'F' to flag a square: ");
scanf("%d %d", &row, &col);
getchar(); // 消耗回车符
printf("Enter 'r' or 'R' to reveal, or 'f' or 'F' to flag: ");
scanf("%c", &action);
getchar(); // 消耗回车符
if (action == 'r' || action == 'R') {
if (board[row][col] == -1) { // 踩中雷了
printf("\nGame over!\n");
print_board(board, ROWS, COLS); // 打印最终棋盘
return 0;
}
else {
reveal_board(board, ROWS, COLS, row, col); // 揭开格子
}
}
else if (action == 'f' || action == 'F') {
board[row][col] = -2; // 标记为旗子
mines--; // 减少剩余雷的数量
}
if (check_win(board, ROWS, COLS, mines)) { // 检查是否胜利
printf("\nCongratulations! You win!\n");
print_board(board, ROWS, COLS); // 打印最终棋盘
return 0;
}
} while(1);
return 0;
}
// 初始化棋盘
void init_board(int board[ROWS][COLS], int rows, int cols, int value) {
int i, j;
for (i = 0; i < rows; i++) {
for (j = 0; j < cols; j++) {
board[i][j] = value;
}
}
}
// 打印当前棋盘
void print_board(int board[ROWS][COLS], int rows, int cols) {
int i, j;
printf("\n ");
for (j = 0; j < cols; j++) {
printf("%d ", j);
}
printf("\n");
for (i = 0; i < rows; i++) {
printf("%d ", i);
for (j = 0; j < cols; j++) {
if (board[i][j] == -2) {
printf("F ");
}
else if (board[i][j] >= 0) {
printf("%d ", board[i][j]);
}
else {
printf("? ");
}
}
printf("\n");
}
}
// 设置雷
void set_mines(int board[ROWS][COLS], int rows, int cols, int mines) {
int i, j, count = 0;
while (count < mines) {
i = rand() % rows;
j = rand() % cols;
if (board[i][j] != -1) { // 如果这个位置不是雷
board[i][j] = -1; // 把这个位置设置为雷
count++;
}
}
}
// 获取周围的雷数
int get_adjacent_mines(int board[ROWS][COLS], int row, int col) {
int i, j, count = 0;
for (i = row - 1; i <= row + 1; i++) {
for (j = col - 1; j <= col + 1; j++) {
if (i >= 0 && i < ROWS && j >= 0 && j < COLS && board[i][j] == -1) {
count++;
}
}
}
return count;
}
// 揭开格子
void reveal_board(int board[ROWS][COLS], int rows, int cols, int row, int col) {
if (board[row][col] != -2 && board[row][col] < 0) { // 如果这个格子没有被揭开过
board[row][col] = get_adjacent_mines(board, row, col); // 获取周围的雷数
if (board[row][col] == 0) { // 如果周围没有雷
int i, j;
for (i = row - 1; i <= row + 1; i++) {
for (j = col - 1; j <= col + 1; j++) {
if (i >= 0 && i < ROWS && j >= 0 && j < COLS) {
reveal_board(board, ROWS, COLS, i, j); // 递归揭开周围的格子
}
}
}
}
}
}
// 检查是否胜利
int check_win(int board[ROWS][COLS], int rows, int cols, int mines) {
int i, j, count = 0;
for (i = 0; i < rows; i++) {
for (j = 0; j < cols; j++) {
if (board[i][j] == -2) { // 如果这个格子被标记为旗子
count++;
}
else if (board[i][j] < 0) { // 如果这个格子还没有被揭开过
return 0;
}
}
}
return count == mines; // 如果标记的旗子数等于雷的数量,就认为胜利了
}
```
这个代码示例使用了递归来揭开周围的格子,也可以使用一个待揭开的格子队列来实现。另外,这个示例只能在终端中运行,如果想要实现图形界面的扫雷游戏,需要使用图形库或者游戏引擎。
阅读全文