C语言实现简易版扫雷游戏

时间:2021-07-20 23:45:58

本文实例为大家分享了C语言实现扫雷游戏的具体代码,供大家参考,具体内容如下

这个小项目源自两个月前学数组的时候,由于觉得比较重要,想记录一下。

首先,大概的思路是要做出两个二维数组充当棋盘,一个用于后台储存雷的情况,一个用于打印给玩家玩游戏

那么第一步我们知道,需要声明两个二维数组,一个打印出来给用户看,一个自己深埋在心里。

第二步应该是要埋雷,这里我们可以定义几个数值去让玩家选择埋雷的数量。

第三步也就是最难的扫雷部分了,我的思路是,首先玩家先输入一个坐标,我们再对玩家输入的坐标找到对应藏雷的数组,若此坐标就是雷,则反馈玩家游戏结束,若不是雷,则计算周围九宫格的雷数,并以数字的形式反馈给玩家。

第四步是最后一步,我们要在玩家输入坐标并得到反馈之后判断雷的数量是否为0,如果是则游戏结束,不是则继续,显然,第三第四步是在一个循环里面的。

下面是整个游戏的流程图

C语言实现简易版扫雷游戏

下面开始代码实现

我们先写出一个主函数

?
1
2
3
4
5
6
int main(void)
{
    test();
 
    return 0;
}

我们在test()函数中实现所有的游戏

首先写出游戏主体

游戏主体

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
void test()
{
    int input = 0;
    srand((unsigned)time(NULL));
    do
    {
        menu();//打印菜单
        scanf("%d", &input);//让用户输入
        switch (input)
        {
        case 1:
            printf("游戏开始\n");
            game();//玩游戏
            break;
        case 0:
            printf("退出游戏\n");
            break;
 
        default:
            printf("输入非法,请重新输入:>\n");
            break;
        }
    } while (input);
}

设计菜单

?
1
2
3
4
5
6
7
void menu()
{
    printf("******************************************************\n");
    printf("****************      1.进入游戏      ****************\n");
    printf("****************      0.退出游戏      ****************\n");
    printf("******************************************************\n");
}

我们把game函数暂时注释后打印菜单检查

C语言实现简易版扫雷游戏

接着进行下一步操作–制作游戏主体

游戏主体

自己定义头文件game.h,并在其中引用头文件

?
1
2
3
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

我想做一个10*10大小的棋盘,但是考虑到后面查找雷数量需要遍历9宫格,如果遍历到边界处则特别麻烦,所以我们不妨把数组行列设置为11 * 11。这样设置以后,布置雷的时候只要用到10 * 10的数组,外边一圈不布置,就很巧妙的避开了上述问题。

?
1
2
#define ROWS 11
#define COLS 11

接下来开始写game()函数

?
1
2
3
4
5
6
7
8
9
void game()
{
    //创建棋盘并初始化
    char mine[ROWS][COLS] = {0};
    char show[ROWS][COLS] = {0};
    //0代表不是雷
    //mine数组是后天储存雷用的
    //show数组是打印出来给玩家看的
}

接着分别初始化两个数组

?
1
2
3
4
5
6
//创建棋盘
char mine[ROWS][COLS] = {0};
char show[ROWS][COLS] = {0};
//初始化棋盘
initBoard(mine, ROWS, COLS, '0');
initBoard(show, ROWS, COLS, '*');

定义初始化数组的函数

?
1
2
3
4
5
6
7
8
9
10
11
12
13
void initBoard(char board[ROWS][COLS], int rows, int cols, char set)
{
    int i;
    int j;
    for (i = 0; i < rows; i++)
    {
 
        for (j = 0; j < cols; j++)
        {
            board[i][j] = set;
        }
    }
}

接下来打印棋盘给玩家看

?
1
2
3
4
5
6
7
8
9
10
11
void game()
{ //1.布置好的雷的信息
    char mine[ROWS][COLS] = {0};
    //2.排查出雷的信息
    char show[ROWS][COLS] = {0};
    //初始化
    initBoard(mine, ROWS, COLS, '0');
    initBoard(show, ROWS, COLS, '*');
    //打印棋盘
    printBoard(show, ROW, COL);
}

之前说了最后一圈数组是不给玩家看的,所以再加入宏定义

?
1
2
#define ROW ROWS - 2
#define COL COLS - 2

打印棋盘函数设置

?
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
void printBoard(char board[ROWS][COLS], int row, int col)
{
    int i, j;
    int cnt = 0;
    //打印列号
    printf("  ");
    for (i = 1; i <= col; i++)
    {
        printf("%d  ", i);
    }
    printf("\n");
    for (i = 1; i <= row; i++)
    {
        printf("%d", i); //打印行号
        for (j = 1; j <= col; j++)
        {
            printf(" %c ", board[i][j]);
            cnt++;
            if (cnt % 9 == 0)
            {
                printf("\n");
                cnt = 0;
            }
        }
    }
}

接下来布置雷

?
1
2
3
4
5
6
7
8
9
10
11
12
13
void game()
{ //1.布置好的雷的信息
    char mine[ROWS][COLS] = {0};
    //2.排查出雷的信息
    char show[ROWS][COLS] = {0};
    //初始化
    initBoard(mine, ROWS, COLS, '0');
    initBoard(show, ROWS, COLS, '*');
    //打印棋盘
    printBoard(show, ROW, COL);
    //布置雷
    putMine(mine, ROW, COL);
}

布置雷函数设置

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
void putMine(char board[ROWS][COLS], int row, int col)
{
    int cnt = modeChoose();//在此加入模式选择
    while (cnt > 0)
    {
        int x;
        int y;
        while (1)
        {
            //置入随机坐标
            x = rand() % row + 1;
            y = rand() % col + 1;
            if (board[x][y] == '0')
            {
                board[x][y] = '1';
                cnt--;
                break;
            }
        }
    }
}

设置模式选择函数

首先定义不同难度所放置的雷数

?
1
2
3
#define EASY_COUNT 10
#define PRIME_COUNT 20
#define HARD_COUNT 50

接下来做modeChoose()函数

?
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
int modeChoose(void)
{
    printf("****************      1.简单难度      ****************\n");
    printf("****************      2.普通难度      ****************\n");
    printf("****************      3.困难难度      ****************\n");
    printf("请输入你想要玩的难度:>");
    int mode;
    int n;
    do
    {
        scanf("%d", &mode);
        switch (mode)
        {
        case 1:
            n = EASY_COUNT;
            break;
        case 2:
            n = PRIME_COUNT;
            break;
        case 3:
            n = HARD_COUNT;
            break;
        default:
            printf("输入非法,请重新输入:>\n");
            break;
        }
    } while (mode != 1 && mode != 2 && mode != 3);
 
    return n;
}

类比菜单,让用户选择

做完这些以后,就开始扫雷了

扫雷

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void game()
{
    //创建棋盘
    char mine[ROWS][COLS] = {0};
    char show[ROWS][COLS] = {0};
    //初始化棋盘
    initBoard(mine, ROWS, COLS, '0');
    initBoard(show, ROWS, COLS, '*');
    //布置雷
    putMine(mine ,ROW,COL);
    //打印棋盘
    printBoard(show,ROW,COL);
    //扫雷
    findMine(mine,show,ROWS,COLS);
}

扫雷函数设置

?
1
2
3
4
5
void findMine(char mine[ROWS][COLS], char show[ROWS][COLS], int rows, int cols)
{
    printf("请输入你要排查雷的坐标(示例:2 5):>");
    int x, y;
}

首先提示玩家输入坐标,然后在循环里读入这个坐标

?
1
2
3
4
5
6
7
8
9
10
void findMine(char mine[ROWS][COLS], char show[ROWS][COLS], int rows, int cols)
{
    printf("请输入你要排查雷的坐标(示例:2 5):>");
    int x, y;
    //判断x,y周围在mine数组周围有几个雷,并将此数目传给show
    while (1)
    {
        scanf("%d %d", &x, &y);
    }
}

首先判断输入坐标是否超出数组范围,是的话提醒用户重新输入,不是的话进行下一步处理。

接下来分情况考虑,首先判断读入的坐标在数组中是不是雷(用1表示雷),是的话游戏结束,不是的话进行下一步处理

?
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
void findMine(char mine[ROWS][COLS], char show[ROWS][COLS], int rows, int cols)
{
    printf("请输入你要排查雷的坐标(示例:2 5):>");
    int x, y;
    //判断x,y周围在mine数组周围有几个雷,并将此数目传给show
    while (1)
    {
        scanf("%d %d", &x, &y);
        while (1)
        {
            if (x < 1 || x > 9 || y < 1 || y > 9)
            {
                printf("输入坐标非法,请重新输入!:>\n");
                break;
            }
            else
            {
                break;
            }
        }
        if (mine[x][y] == '1')
        {
            printf("很遗憾,你被炸死了!\n");
            printBoard(mine, ROW, COL);//游戏结束了就可以打印后台棋盘给玩家看了
            break;
        }
        else
        {
        //下一步处理
        }
    }
}

现在我们需要确定,踩下坐标不为雷的情况。
若不为0,我们通过递归去判断这个坐标周围为0的情况,把为0的情况自动去除后再打印给玩家看,去除雷的坐标用空格打印。
这样分析下来,我们需要再封装一个函数

?
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
void findMine(char mine[ROWS][COLS], char show[ROWS][COLS], int rows, int cols)
{
    printf("请输入你要排查雷的坐标(示例:2 5):>");
    int x, y;
    //判断x,y周围在mine数组周围有几个雷,并将此数目传给show
    while (1)
    {
        scanf("%d %d", &x, &y);
        while (1)
        {
            if (x < 1 || x > 9 || y < 1 || y > 9)
            {
                printf("输入坐标非法,请重新输入!:>\n");
                break;
            }
            else
            {
                break;
            }
        }
        if (mine[x][y] == '1')
        {
            printf("很遗憾,你被炸死了!\n");
            printBoard(mine, ROW, COL);
            break;
        }
        else
        {
            findZero(mine, show, x, y);
        }
    }
}

findzero函数实现

?
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
void findZero(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
{
    if (mineCount(mine, x, y) == '0')//若雷的数量为0
    {
        show[x][y] = ' ';
        if (show[x - 1][y] == '*')
        {
            findZero(mine, show, x - 1, y);
        }
        if (show[x][y - 1] == '*')
        {
            findZero(mine, show, x, y - 1);
        }
        if (show[x][y + 1] == '*')
        {
            findZero(mine, show, x, y + 1);
        }
        if (show[x + 1][y] == '*')
        {
            findZero(mine, show, x + 1, y);
        }
    }
    else
    {
        char count = mineCount(mine, x, y);
        show[x][y] = count;
    }
}

其中mineCount函数定义如下

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
char mineCount(char board[ROWS][COLS], int x, int y)
{
    //遍历从x-1,y-1到x+1,y+1的雷数并返回
    int i, j;
    char cnt = '0';
    for (i = x - 1; i <= (x + 1); i++)
    {
        for (j = y - 1; j <= (y + 1); j++)
        {
            if (board[i][j] == '1')
            {
                cnt = cnt + 1;
            }
        }
    }
 
    return cnt;
}

记得每次操作完要打印数组给玩家看,这之后再写一段判断游戏是否结束的代码就大功告成了qwq。

?
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
void findMine(char mine[ROWS][COLS], char show[ROWS][COLS], int rows, int cols)
{
    printf("请输入你要排查雷的坐标(示例:2 5):>");
    int x, y;
    //判断x,y周围在mine数组周围有几个雷,并将此数目传给show
    while (1)
    {
        scanf("%d %d", &x, &y);
        while (1)
        {
            if (x < 1 || x > 9 || y < 1 || y > 9)
            {
                printf("输入坐标非法,请重新输入!:>\n");
                break;
            }
            else
            {
                break;
            }
        }
        if (mine[x][y] == '1')
        {
            printf("很遗憾,你被炸死了!\n");
            printBoard(mine, ROW, COL);
            break;
        }
        else
        {
            findZero(mine, show, x, y);
 
            printBoard(show, ROW, COL);
            int i, j;
            int cnt = 0; //判断扫雷是否全部完成
            for (i = 1; i <= ROW; i++)
            {
                for (j = 1; j <= COL; j++)
                {
                    if (show[i][j] == '*')
                    {
                        cnt++;
                    }
                }
            }
            if (cnt == 0)
            {
                printf("恭喜你通关游戏!\n");
                break;
            }
            else
            {
                printf("请输入你要排查雷的坐标(示例:2 5):>\n");
            }
        }
    }
}

总代码如下

总代码

test.c

?
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
#include "game.h"
 
void menu()
{
    printf("******************************************************\n");
    printf("****************      1.进入游戏      ****************\n");
    printf("****************      0.退出游戏      ****************\n");
    printf("******************************************************\n");
}
 
void game()
{
    //创建棋盘
    char mine[ROWS][COLS] = {0};
    char show[ROWS][COLS] = {0};
    //初始化棋盘
    initBoard(mine, ROWS, COLS, '0');
    initBoard(show, ROWS, COLS, '*');
    //布置雷
    putMine(mine ,ROW,COL);
    //打印棋盘
    printBoard(show,ROW,COL);
    //扫雷
    findMine(mine,show,ROWS,COLS);
}
 
void test()
{
    int input = 0;
    srand((unsigned)time(NULL));
    do
    {
        menu();
        scanf("%d", &input);
        switch (input)
        {
        case 1:
            printf("游戏开始\n");
            game();
            break;
        case 0:
            printf("退出游戏\n");
            break;
 
        default:
            printf("输入非法,请重新输入:>\n");
            break;
        }
    } while (input);
}
int main(void)
{
    test();
 
    return 0;
}

头文件game.h

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
 
#define ROWS 11
#define COLS 11
#define ROW ROWS - 2
#define COL COLS - 2
#define EASY_COUNT 10
#define PRIME_COUNT 20
#define HARD_COUNT 50
 
void initBoard(char board[ROWS][COLS], int row, int col, char ch);
void printBoard(char show[ROWS][COLS], int row, int col);
void putMine(char board[ROWS][COLS], int row, int col);
void findMine(char mine[ROWS][COLS], char show[ROWS][COLS], int rows, int cols);

game.c

?
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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
#include "game.h"
 
void initBoard(char board[ROWS][COLS], int row, int col, char ch)
{
    //初始化数组
    int i, j;
    for (i = 0; i < row; i++)
    {
        for (j = 0; j < col; j++)
        {
            board[i][j] = ch;
        }
    }
}
 
void printBoard(char board[ROWS][COLS], int row, int col)
{
    int i;
    int j;
    int flag = 0;
    printf("  ");
    for (i = 1; i <= row; i++)
    {
        printf("% d ", i);
    }
    printf("\n");
    for (i = 1; i <= row; i++) //打印行
    {
        printf("%d ", i);
        for (j = 1; j <= col; j++) //打印列
        {
            printf(" %c ", board[i][j]);
            flag++;
        }
 
        if (flag % 9 == 0)
        {
            printf("\n");
            flag = 0;
        }
    }
}
 
int modeChoose(void)
{
    printf("****************      1.简单难度      ****************\n");
    printf("****************      2.普通难度      ****************\n");
    printf("****************      3.困难难度      ****************\n");
    printf("请输入你想要玩的难度:>");
    int mode;
    int n;
    do
    {
        scanf("%d", &mode);
        switch (mode)
        {
        case 1:
            n = EASY_COUNT;
            break;
        case 2:
            n = PRIME_COUNT;
            break;
        case 3:
            n = HARD_COUNT;
            break;
        default:
            printf("输入非法,请重新输入:>\n");
            break;
        }
    } while (mode != 1 && mode != 2 && mode != 3);
 
    return n;
}
 
void putMine(char board[ROWS][COLS], int row, int col)
{
    int cnt = modeChoose();//再此加入模式选择
    while (cnt > 0)
    {
        int x;
        int y;
        while (1)
        {
            //置入随机坐标
            x = rand() % row + 1;
            y = rand() % col + 1;
            if (board[x][y] == '0')
            {
                board[x][y] = '1';
                cnt--;
                break;
            }
        }
    }
}
 
char mineCount(char board[ROWS][COLS], int x, int y)
{
    //遍历从x-1,y-1到x+1,y+1的雷数并返回
    int i, j;
    char cnt = '0';
    for (i = x - 1; i <= (x + 1); i++)
    {
        for (j = y - 1; j <= (y + 1); j++)
        {
            if (board[i][j] == '1')
            {
                cnt = cnt + 1;
            }
        }
    }
 
    return cnt;
}
void findZero(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
{
    if (mineCount(mine, x, y) == '0')//若雷的数量为0
    {
        show[x][y] = ' ';
        if (show[x - 1][y] == '*')
        {
            findZero(mine, show, x - 1, y);
        }
        if (show[x][y - 1] == '*')
        {
            findZero(mine, show, x, y - 1);
        }
        if (show[x][y + 1] == '*')
        {
            findZero(mine, show, x, y + 1);
        }
        if (show[x + 1][y] == '*')
        {
            findZero(mine, show, x + 1, y);
        }
    }
    else
    {
        char count = mineCount(mine, x, y);
        show[x][y] = count;
    }
}
void findMine(char mine[ROWS][COLS], char show[ROWS][COLS], int rows, int cols)
{
    printf("请输入你要排查雷的坐标(示例:2 5):>");
    int x, y;
    //判断x,y周围在mine数组周围有几个雷,并将此数目传给show
    while (1)
    {
        scanf("%d %d", &x, &y);
        while (1)
        {
            if (x < 1 || x > 9 || y < 1 || y > 9)
            {
                printf("输入坐标非法,请重新输入!:>\n");
                break;
            }
            else
            {
                break;
            }
        }
        if (mine[x][y] == '1')
        {
            printf("很遗憾,你被炸死了!\n");
            printBoard(mine, ROW, COL);
            break;
        }
        else
        {
            findZero(mine, show, x, y);
 
            printBoard(show, ROW, COL);
            int i, j;
            int cnt = 0; //判断扫雷是否全部完成
            for (i = 1; i <= ROW; i++)
            {
                for (j = 1; j <= COL; j++)
                {
                    if (show[i][j] == '*')
                    {
                        cnt++;
                    }
                }
            }
            if (cnt == 0)
            {
                printf("恭喜你通关游戏!\n");
                break;
            }
            else
            {
                printf("请输入你要排查雷的坐标(示例:2 5):>\n");
            }
        }
    }
}

运行示例

C语言实现简易版扫雷游戏

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。

原文链接:https://blog.csdn.net/qq_55783740/article/details/116456124