项目创建及其代码分类 test.c
- 游戏逻辑代码编写
game.h
- 游戏函数声明,符号定义,头文件的包含
game.c
- 游戏函数代码实现
主函数和菜单函数 在test.c
中编写主函数代码
使用do while
循环
调用menu
函数
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 int main () { int input = 0 ; do { menu(); printf ("请选择:>" ); scanf ("%d" ,&input); switch (input) { case 1 : printf ("开始扫雷游戏\n" ); printf ("游戏需要输入坐标(如:1 2)\n" ); game(); break ; case 0 : printf ("退出游戏" ); break ; default : printf ("选择错误,请重新选择" ); break ; } } while (input); return 0 ; }
在主函数上面定义并实现menu
函数
1 2 3 4 5 6 7 8 void menu () { printf ("**********************************\n" ); printf ("********** 1.play **********\n" ); printf ("********** 0.exit **********\n" ); printf ("**********************************\n" ); }
头文件 在头文件game.h
中引入我们需要的C语言头文件
1 2 #include <stdio.h> #include <string.h>
然后在其他源文件下引用该文件即可
这样就不用频繁的在各个源文件中引入C语言头文件了
编写游戏逻辑代码 确认需求 要做一个扫雷的小游戏,首先需要定义一个9*9雷区也就是先创建出一个二维的数组
然后初始化雷区(数组),并打印输出
而布置雷,我们可以使用随机数了布置雷
然后就是排查雷,我们需要让它在点击后显示周围的雷的数量,这可以使用循环遍历的方法
那么会出现一个问题,如果我们的雷在边缘位,在遍历时会遍历到数组大小之外的地方,导致越界
我们可以创建两个二维数组,一个用于存放布置好的雷,一个用于存放排查出的雷的信息
然后把这两个二维数组的行和列都改为11,这样就不用担心越界的问题
创建二维数组和初始化雷区 我们在主函数上面定义了game
函数
然后根据需求,创建出两个二维数组,然后初始化雷区
1 2 3 4 5 void game () { char mine[ROWS][COLS]; char show[ROWS][COLS]; }
然后我们在头文件中用define
定义常量行和列
这里可以分别定义两个,一个是整个数组的行列,一个是需要显示出来的行列
1 2 3 4 #define ROW 9 #define COL 9 #define ROWS ROW+2 #define COLS COL+2
然后调用InitBoard
初始化雷区,两个数组都要初始化
1 2 3 4 5 6 7 8 void game () { char mine[ROWS][COLS]; char show[ROWS][COLS]; InitBoard(mine, ROWS, COLS,'0' ); InitBoard(show, ROWS, COLS,'*' ); }
头文件声明函数
1 2 3 void InitBoard (char board[ROWS][COLS], int rows, int cols,char set ) ;
game.c
中实现函数
1 2 3 4 5 6 7 8 9 10 11 12 void InitBoard (char board[ROWS][COLS], int rows, int cols,char set ) { int i = 0 ; int j = 0 ; for ( i = 0 ; i < rows; i++) { for ( j = 0 ; j < cols; j++) { board[i][j] = set ; } } }
打印雷区 然后我们需要打印雷区,方便玩家查看
首先调用DisPlayBoard
函数打印雷区
1 2 3 4 5 6 7 8 9 10 void game () { char mine[ROWS][COLS]; char show[ROWS][COLS]; InitBoard(mine, ROWS, COLS,'0' ); InitBoard(show, ROWS, COLS,'*' ); DisPlayBoard(show, ROW, COL); }
头文件声明函数
1 2 void DisPlayBoard (char board[ROWS][COLS], int row, int col) ;
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 void DisPlayBoard (char board[ROWS][COLS], int row, int col) { int i = 0 ; int j = 0 ; printf ("------扫雷游戏------\n" ); for ( i = 0 ; 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]); } printf ("\n" ); } printf ("------扫雷游戏------\n" ); }
布置雷 我们需要使用随机数来随机布置雷的位置
在主函数中使用srand()
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 int main () { int input = 0 ; srand((unsigned int )time(NULL )); do { menu(); printf ("请选择:>" ); scanf ("%d" ,&input); switch (input) { case 1 : printf ("开始扫雷游戏\n" ); printf ("游戏需要输入坐标(如:1 2)\n" ); game(); break ; case 0 : printf ("退出游戏" ); break ; default : printf ("选择错误,请重新选择" ); break ; } } while (input); return 0 ; }
然后在game
函数中调用SetMine
函数
1 2 3 4 5 6 7 8 9 10 11 12 void game () { char mine[ROWS][COLS]; char show[ROWS][COLS]; InitBoard(mine, ROWS, COLS,'0' ); InitBoard(show, ROWS, COLS,'*' ); DisPlayBoard(show, ROW, COL); SetMine(mine, ROW, COL); }
声明函数
1 2 void SetMine (char board[ROWS][COLS], int row, int col) ;
game.c
中实现函数
这里需要使用 %
来随机生成下标,但是下标不能为0和10,否则就超出了该显示的位置
让数组元素为 1 代表有雷,0就是没有雷
把雷的总数用define
定义,写在头文件中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 void SetMine (char mine[ROWS][COLS], int row, int col) { int count = BOOM; while (count) { int x = rand() % row+1 ; int y = rand() % col+1 ; if (mine[x][y] == '0' ) { mine[x][y] = '1' ; count--; } } }
不要忘记了引用库函数所需的头文件
1 2 #include <time.h> #include <stdlib.h>
排查雷 game
函数中调用FindMine
函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 void game () { char mine[ROWS][COLS]; char show[ROWS][COLS]; InitBoard(mine, ROWS, COLS,'0' ); InitBoard(show, ROWS, COLS,'*' ); DisPlayBoard(show, ROW, COL); SetMine(mine, ROW, COL); FindMine(mine, show, ROW, COL); }
声明函数
1 2 void SetMine (char board[ROWS][COLS], int row, int col) ;
在排查雷的时候,我们输入排查雷的坐标
判断其合法性后,判断该位置是否是雷
如果是雷,炸死;如果不是雷,遍历周围的数组元素,获取到周围雷的数量
获取周围雷数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 int GetMineCount (char mine[ROWS][COLS], int x, int y) { int i = 0 ; int j = 0 ; int count = 0 ; for (i = x - 1 ; i <= x + 1 ; i++) { for (j = y - 1 ; j <= y + 1 ; j++) { if (mine[i][j] == '1' ) { count++; } } } return count; }
排查雷
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 void FindMine (char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col) { int x = 0 ; int y = 0 ; int win = 0 ; while (win < row * col - BOOM) { printf ("请输入要排查的坐标:>" ); while (getchar() != '\n' ) { } scanf ("%d %d" , &x, &y); if (x >= 1 && x <= row && y >= 1 && y <= col) { if (mine[x][y] == '1' ) { printf ("BOOM!!!!你被炸死了\n" ); show[x][y] = '@' ; DisPlayBoard(show, ROW, COL); break ; } else { int num = GetMineCount(mine,x,y); show[x][y] = num + '0' ; DisPlayBoard(show, ROW, COL); win++; } } else { printf ("坐标不合法,请重新输入\n" ); } } if (win == row * col - BOOM) { printf ("你赢了,你就是扫雷大师!!\n" ); DisPlayBoard(mine, ROW, COL); } }
功能增加 到了上面,就完成了扫雷游戏的编写,不过我们还能进行功能的优化
比如说,在点击之后,如果该位置周围没有雷,会展开
类似:
那么要完成这个功能我们需要使用递归的方法实现
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 void Expand (char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y, int * win) { if (x >= 1 && x <= ROW && y >= 1 && y <= COL) { int i = 0 ; int j = 0 ; int count = GetMineCount(mine,x,y); if (count == 0 ) { show[x][y] = '0' ; for (i = x - 1 ; i <= x + 1 ; i++) { for (j = y - 1 ; j <= y + 1 ; j++) { if (show[i][j] == '*' ) { Expand(mine, show, i, j, win); } } } } else { show[x][y] = count + '0' ; } (*win)++; } }
修改一下排查雷FindMine
函数
直接调用Expand
即可
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 row, int col) { int x = 0 ; int y = 0 ; int win = 0 ; while (win < row * col - BOOM) { printf ("请输入要排查的坐标:>" ); while (getchar() != '\n' ) { } scanf ("%d %d" , &x, &y); if (x >= 1 && x <= row && y >= 1 && y <= col) { if (mine[x][y] == '1' ) { printf ("BOOM!!!!你被炸死了\n" ); printf ("BOOM!!!!你被炸死了\n" ); printf ("BOOM!!!!你被炸死了\n" ); show[x][y] = '@' ; DisPlayBoard(show, ROW, COL); break ; } else { Expand(mine,show, x, y, &win); DisPlayBoard(show, ROW, COL); } } else { printf ("坐标不合法,请重新输入\n" ); } } if (win == row * col - BOOM) { printf ("你赢了,你就是扫雷大师!!\n" ); printf ("你赢了,你就是扫雷大师!!\n" ); printf ("你赢了,你就是扫雷大师!!\n" ); DisPlayBoard(mine, ROW, COL); } }
然后在game
函数里加上重新开始游戏的倒计时
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 game () { char mine[ROWS][COLS]; char show[ROWS][COLS]; InitBoard(mine, ROWS, COLS,'0' ); InitBoard(show, ROWS, COLS,'*' ); DisPlayBoard(show, ROW, COL); SetMine(mine, ROW, COL); FindMine(mine, show, ROW, COL); Sleep(1000 ); for (int i = 5 ; i > 0 ; i--) { printf ("倒计时后重新开始游戏:%d\n" , i); Sleep(1000 ); } system("cls" ); }
功能展示
代码展示 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 57 58 59 60 61 #define _CRT_SECURE_NO_WARNINGS 1 #include "game.h" void menu () { printf ("**********************************\n" ); printf ("********** 1.play **********\n" ); printf ("********** 0.exit **********\n" ); printf ("**********************************\n" ); } void game () { char mine[ROWS][COLS]; char show[ROWS][COLS]; InitBoard(mine, ROWS, COLS,'0' ); InitBoard(show, ROWS, COLS,'*' ); DisPlayBoard(show, ROW, COL); SetMine(mine, ROW, COL); FindMine(mine, show, ROW, COL); Sleep(1000 ); for (int i = 5 ; i > 0 ; i--) { printf ("倒计时后重新开始游戏:%d\n" , i); Sleep(1000 ); } system("cls" ); } int main () { int input = 0 ; srand((unsigned int )time(NULL )); do { menu(); printf ("请选择:>" ); scanf ("%d" ,&input); switch (input) { case 1 : printf ("开始扫雷游戏\n" ); printf ("游戏需要输入坐标(如:1 2)\n" ); game(); break ; case 0 : printf ("退出游戏" ); break ; default : printf ("选择错误,请重新选择" ); break ; } } while (input); return 0 ; }
game.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 #pragma once #define ROW 9 #define COL 9 #define ROWS ROW+2 #define COLS COL+2 #define BOOM 10 #include <stdio.h> #include <string.h> #include <time.h> #include <stdlib.h> #include <windows.h> void InitBoard (char board[ROWS][COLS], int rows, int cols,char set ) ;void DisPlayBoard (char board[ROWS][COLS], int row, int col) ;void SetMine (char board[ROWS][COLS], int row, int col) ;void FindMine (char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col) ;
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 #define _CRT_SECURE_NO_WARNINGS 1 #include "game.h" void InitBoard (char board[ROWS][COLS], int rows, int cols,char set ) { int i = 0 ; int j = 0 ; for ( i = 0 ; i < rows; i++) { for ( j = 0 ; j < cols; j++) { board[i][j] = set ; } } } void DisPlayBoard (char board[ROWS][COLS], int row, int col) { int i = 0 ; int j = 0 ; printf ("------扫雷游戏------\n" ); for ( i = 0 ; 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]); } printf ("\n" ); } printf ("------扫雷游戏------\n" ); } void SetMine (char mine[ROWS][COLS], int row, int col) { int count = BOOM; while (count) { int x = rand() % row+1 ; int y = rand() % col+1 ; if (mine[x][y] == '0' ) { mine[x][y] = '1' ; count--; } } } int GetMineCount (char mine[ROWS][COLS], int x, int y) { int i = 0 ; int j = 0 ; int count = 0 ; for (i = x - 1 ; i <= x + 1 ; i++) { for (j = y - 1 ; j <= y + 1 ; j++) { if (mine[i][j] == '1' ) { count++; } } } return count; } void Expand (char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y, int * win) { if (x >= 1 && x <= ROW && y >= 1 && y <= COL) { int i = 0 ; int j = 0 ; int count = GetMineCount(mine,x,y); if (count == 0 ) { show[x][y] = '0' ; for (i = x - 1 ; i <= x + 1 ; i++) { for (j = y - 1 ; j <= y + 1 ; j++) { if (show[i][j] == '*' ) { Expand(mine, show, i, j, win); } } } } else { show[x][y] = count + '0' ; } (*win)++; } } void FindMine (char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col) { int x = 0 ; int y = 0 ; int win = 0 ; while (win < row * col - BOOM) { printf ("请输入要排查的坐标:>" ); while (getchar() != '\n' ) { } scanf ("%d %d" , &x, &y); if (x >= 1 && x <= row && y >= 1 && y <= col) { if (mine[x][y] == '1' ) { printf ("BOOM!!!!你被炸死了\n" ); printf ("BOOM!!!!你被炸死了\n" ); printf ("BOOM!!!!你被炸死了\n" ); show[x][y] = '@' ; DisPlayBoard(show, ROW, COL); break ; } else { Expand(mine,show, x, y, &win); DisPlayBoard(show, ROW, COL); } } else { printf ("坐标不合法,请重新输入\n" ); } } if (win == row * col - BOOM) { printf ("你赢了,你就是扫雷大师!!\n" ); printf ("你赢了,你就是扫雷大师!!\n" ); printf ("你赢了,你就是扫雷大师!!\n" ); DisPlayBoard(mine, ROW, COL); } }
扫雷游戏程序下载地址 点击此处进行下载