C语言实现简易版扫雷的完整过程

时间:2021-12-08 03:38:17

一、问题描述

用C语言实现简易版扫雷。

二、基本流程

1.菜单界面。

2.创建地图 (两个地图)。

3.初始化地图。

4.打印地图。

5.程序读取玩家输入的要翻开位置的坐标,并校验。

6.如果不是地雷,统计当前位置周围雷的个数, 并显示到地图上.。

7.判定游戏是否胜利。

三、步骤

1.菜单界面

1.开始游戏 0.退出游戏

?
1
2
3
4
5
6
7
8
9
10
int menu(){
    printf("----------------------\n");
    printf("------1.开始游戏------\n");
    printf("------0.退出游戏------\n");
    printf("----------------------\n");
    int choice = 0;
    printf("请输入你的选择:");
    scanf("%d", &choice);
    return choice;
}

2.创建地图

我们需要两张地图,所以要创建两个二维数组。

第一个二维数组,表示玩家看到的地图。(show)

第二个二维数组,表示当前位置是不是地雷(1表示是地雷,0表示不是地雷)。(mine)

使用宏定义的原因:

1.推高代码可读性,后续代码中遇到9,方便理解含义。

2.提高扩展性,如果将来要修改棋盘尺寸,代码修改会很方便。

?
1
2
3
4
#define MAX_ROW 9
#define MAX_COL 9
    char show[MAX_ROW][MAX_COL] = { 0 };
    char mine[MAX_ROW][MAX_COL] = { 0 };

3.初始化地图

使用 * 表示未翻开的地。

show地图一开始全都是 * 。

mine地图是由0,1组成的。(1表示是地雷,0表示不是地雷)一开始都为0,随后由电脑随机在地图上生成1。

这里我们使用宏定义了DIFFICULTY,表示地雷的数量:10个。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#define DIFFICULTY 10
void init(char show[MAX_ROW][MAX_COL], char mine[MAX_ROW][MAX_COL]){
    for (int row = 0; row < MAX_ROW; row++){
        for (int col = 0; col < MAX_COL; col++){
            show[row][col] = '*';
            //初始化 mine,先全设为'0', 然后随机生成n个'1'
            mine[row][col] = '0';
        }
    }
    int n = DIFFICULTY;
    while (n>0){
    // 生成雷的随机位置
        int row = rand() % MAX_ROW;
        int col = rand() % MAX_COL;
        if (mine[row][col] == '1'){
        // 如果当前位置已经有雷了,就直接进入下次循环, 重新产生随机位置
            continue;
        }
        mine[row][col] = '1';
        n--;
    }
}

4.打印地图

打印出地图。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void printMap(char themap[MAX_ROW][MAX_COL]){
    printf(" |");
    for (int col = 0; col < MAX_COL; col++) {
        printf("%d ", col);
    }
    printf("\n");
    printf("--+------------------\n");
    for (int row = 0; row < MAX_ROW; row++) {
        printf(" %d|", row);
        for (int col = 0; col < MAX_COL; col++) {
            printf("%c ", themap[row][col]);
        }
        printf("\n");
    }
}

5.玩家翻开坐标

玩家通过输入坐标的方式翻开土地。

注意:

1.输入坐标要在地图范围内。

2.不能重复翻开土地。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
//程序读取玩家输入的要翻开位置的坐标, 并校验
int row = 0;
      int col = 0;
      printf("请输入翻开的坐标(row col):");
      scanf("%d %d", &row, &col);
      if (row < 0 || col < 0 || row >= MAX_ROW || col >= MAX_COL){
          printf("输入的坐标超过范围,重新输入:\n");
          continue;
      }
      if (show[row][col] != '*'){
          printf("已经翻开,请重新输入:\n");
          continue;
      }

6.判断是否为地雷

如果翻开的位置在mine上显示为1,那么翻到地雷了,输出被炸死,打印地雷地图,让玩家死得明白。

如果翻开的位置上在mine上不是1,那么继续下一步骤。

?
1
2
3
4
5
if (mine[row][col] == '1'){
            printf("你已经被炸死了!!!\n");
            printMap(mine);
            break;
        }

7.更新地图

计算周围的地雷数量,在翻开位置显示。

?
1
updateShow(show,mine,row,col);
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 根据当前 row, col 的位置, 计算出当前位置周围有几个雷
// 并且更新显示到 show 中
void updateShow(char show[MAX_ROW][MAX_COL], char mine[MAX_ROW][MAX_COL], 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 >= MAX_ROW
                || c < 0 || c >= MAX_COL) {
                continue;
            }
            if (mine[r][c] == '1') {
                count++;
            }
        }
    }
    //此时 count 里面就已经存好了 row, col 周围 八个格子 的雷的个数
    // 把这个结果写到 show 中即可.
    // 需要把数字 count 转成对应的字符
    show[row][col] = count + '0';
 
}

8.判断是否胜利

定义一个变量safe,表示翻开的不是地雷的土地,每次更新地图后,safe加一。如果最后翻开的不是地雷的土地等于地图的大小减地雷数,那么排除所有地雷,确认安全。

?
1
2
3
4
5
6
7
8
9
//记录翻开的格子的个数
int safe = 0;
updateShow(show,mine,row,col);
safe++;
      if (safe == MAX_ROW*MAX_COL - DIFFICULTY){
          printf("已经排除所有的雷,你已经安全!!!\n");
          printMap(mine);
          break;
      }

四、代码实现

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#define _CRT_SECURE_NO_WARNINGS
#define MAX_ROW 9
#define MAX_COL 9
#define DIFFICULTY 10
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
 
int menu(){
    printf("----------------------\n");
    printf("------1.开始游戏------\n");
    printf("------0.退出游戏------\n");
    printf("----------------------\n");
    int choice = 0;
    printf("请输入你的选择:");
    scanf("%d", &choice);
    return choice;
}
void init(char show[MAX_ROW][MAX_COL], char mine[MAX_ROW][MAX_COL]){
    for (int row = 0; row < MAX_ROW; row++){
        for (int col = 0; col < MAX_COL; col++){
            show[row][col] = '*';
            mine[row][col] = '0';
        }
    }
    int n = DIFFICULTY;
    while (n>0){
        int row = rand() % MAX_ROW;
        int col = rand() % MAX_COL;
        if (mine[row][col] == '1'){
            continue;
        }
        mine[row][col] = '1';
        n--;
    }
}
void printMap(char themap[MAX_ROW][MAX_COL]){
    printf(" |");
    for (int col = 0; col < MAX_COL; col++) {
        printf("%d ", col);
    }
    printf("\n");
    printf("--+------------------\n");
    for (int row = 0; row < MAX_ROW; row++) {
        printf(" %d|", row);
        for (int col = 0; col < MAX_COL; col++) {
            printf("%c ", themap[row][col]);
        }
        printf("\n");
    }
}
void updateShow(char show[MAX_ROW][MAX_COL], char mine[MAX_ROW][MAX_COL], 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 >= MAX_ROW
                || c < 0 || c >= MAX_COL) {
                continue;
            }
            if (mine[r][c] == '1') {
                count++;
            }
        }
    }
    show[row][col] = count + '0';
 
}
void game(){
    char show[MAX_ROW][MAX_COL] = { 0 };
    char mine[MAX_ROW][MAX_COL] = { 0 };
    init(show, mine);
    int safe = 0;
    while (1){
        printMap(show);
        int row = 0;
        int col = 0;
        printf("请输入翻开的坐标(row col):");
        scanf("%d %d", &row, &col);
        if (row < 0 || col < 0 || row >= MAX_ROW || col >= MAX_COL){
            printf("输入的坐标超过范围,重新输入:\n");
            continue;
        }
        if (show[row][col] != '*'){
            printf("已经翻开,请重新输入:\n");
            continue;
        }
        if (mine[row][col] == '1'){
            printf("你已经被炸死了!!!\n");
            // 打印一遍地雷的地图, 让玩家死的明白
            printMap(mine);
            break;
        }
        updateShow(show, mine, row, col);
        safe++;
        if (safe == MAX_ROW*MAX_COL - DIFFICULTY){
            printf("已经排除所有的雷,你已经安全!!!\n");
            // 打印一遍地雷的地图, 让玩家知道雷在哪
            printMap(mine);
            break;
        }
    }
}
int main()
{
    srand((unsigned int)time(0));
    while (1){
        int choice = menu();
        if (choice == 1){
            game();
        }
        else if (choice == 0){
            printf("退出游戏,byebye!");
            break;
        }
        else{
            printf("输入错误,请重新输入:");
            continue;
        }
 
    }
}

总结

到此这篇关于C语言实现简易版扫雷的文章就介绍到这了,更多相关C语言简易版扫雷内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://blog.csdn.net/qq_34270874/article/details/109431722