你可以用链表写一个扫雷嘛 并且给出代码注释
时间: 2023-12-29 10:29:30 浏览: 83
链表(下):如何轻松写出正确的链表代码?.pdf
好的,下面是用链表实现扫雷游戏的代码,注释在代码中:
```
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <time.h>
// 定义节点结构体
typedef struct node {
int row;
int col;
struct node *next;
} Node;
// 定义链表头结点指针
Node *head = NULL;
// 定义地图大小
const int ROWS = 10;
const int COLS = 10;
// 定义地图数组
int map[ROWS][COLS];
// 打印地图
void print_map(bool show_all) {
printf(" ");
for (int col = 0; col < COLS; col++) {
printf("%d ", col);
}
printf("\n");
for (int row = 0; row < ROWS; row++) {
printf("%d ", row);
for (int col = 0; col < COLS; col++) {
if (show_all || map[row][col] >= 0) {
printf("%d ", map[row][col]);
} else {
printf(". ");
}
}
printf("\n");
}
}
// 初始化地图
void init_map(int num_mines) {
// 将地图全部初始化为-1(未翻开)
for (int row = 0; row < ROWS; row++) {
for (int col = 0; col < COLS; col++) {
map[row][col] = -1;
}
}
// 随机放置地雷
srand((unsigned int)time(NULL));
for (int i = 0; i < num_mines; i++) {
int row = rand() % ROWS;
int col = rand() % COLS;
if (map[row][col] == -1) {
map[row][col] = 9; // 9表示地雷
} else {
i--;
}
}
}
// 计算某个位置周围的地雷数量
int count_mines_around(int row, int col) {
int count = 0;
for (int r = row - 1; r <= row + 1; r++) {
for (int c = col - 1; c <= col + 1; c++) {
if (r >= 0 && r < ROWS && c >= 0 && c < COLS && !(r == row && c == col) && map[r][c] == 9) {
count++;
}
}
}
return count;
}
// 翻开某个位置
bool flip(int row, int col) {
if (map[row][col] >= 0) {
return false; // 已翻开
}
if (map[row][col] == 9) {
return true; // 翻开地雷,游戏结束
}
int count = count_mines_around(row, col);
map[row][col] = count;
if (count == 0) {
// 如果周围没有地雷,递归翻开周围的8个位置
for (int r = row - 1; r <= row + 1; r++) {
for (int c = col - 1; c <= col + 1; c++) {
if (r >= 0 && r < ROWS && c >= 0 && c < COLS && !(r == row && c == col)) {
flip(r, c);
}
}
}
}
return false;
}
// 添加节点到链表尾部
void add_node(int row, int col) {
Node *new_node = (Node*)malloc(sizeof(Node));
new_node->row = row;
new_node->col = col;
new_node->next = NULL;
if (head == NULL) {
head = new_node;
} else {
Node *temp = head;
while (temp->next != NULL) {
temp = temp->next;
}
temp->next = new_node;
}
}
// 从链表头部取出节点
Node* pop_node() {
if (head == NULL) {
return NULL;
}
Node *temp = head;
head = head->next;
temp->next = NULL;
return temp;
}
// 翻开某个位置及其周围的位置
void flip_around(int row, int col) {
add_node(row, col);
while (head != NULL) {
Node *node = pop_node();
int r = node->row;
int c = node->col;
flip(r, c);
for (int i = r - 1; i <= r + 1; i++) {
for (int j = c - 1; j <= c + 1; j++) {
if (i >= 0 && i < ROWS && j >= 0 && j < COLS && !(i == r && j == c)) {
add_node(i, j);
}
}
}
free(node);
}
}
int main() {
init_map(10); // 放置10个地雷
print_map(false); // 显示地图,未翻开的位置用"."表示
while (true) {
int row, col;
printf("请输入要翻开的位置(行 列):");
scanf("%d %d", &row, &col);
if (flip(row, col)) {
printf("翻开地雷,游戏结束!\n");
break;
}
print_map(false);
if (count_mines_around(row, col) == 0) {
flip_around(row, col);
}
print_map(false);
}
return 0;
}
```
这个程序实现了一个简单的扫雷游戏,可以翻开某个位置,并显示周围的地雷数量,如果翻开了地雷则游戏结束。在翻开某个位置时,如果该位置周围没有地雷,则会递归翻开周围的位置。在递归翻开周围位置时,我们使用了一个链表来保存需要翻开的位置,这样可以避免使用递归函数造成栈溢出。
阅读全文