致读者:
扫雷,是一个Windows平台下一个经典的小游戏,今有兴趣玩了几把后,就利用所学二维数组的相关知识模拟实现了一个“扫雷游戏”。由于学识浅薄,界面有点简陋,尽请谅解!
【项目思路】:
1、首先想一想扫雷游戏在Windows平台下是如何实现的。
2、其次通过观察游戏,我们可以想到需要用两个二维数组来实现扫雷的功能。
3、游戏刚开始,需要需要显示棋盘,用“*”遮盖雷的坐标,所以要有一个填充棋盘的函数。
4、通过rand()函数,随机生成雷的坐标,埋雷的函数。
5、每次扫过后,都要显示新的棋盘,显示棋盘的函数。
6、如果要想第一次踩不到雷的,需要把该坐标下得雷移动到其他不是雷的坐标,并且点击不是雷,还要满足一点击一片的效果。
7、最后需要一个函数判断是否扫雷成功。
【项目样图】:
是不是很有意思?当然重中之重的是:
要注意需要用二维数组来打印两个棋盘,假如我们要打印10X10的棋盘,那我们的二维数组元素也要为10X10个吗?,不能,因为我们在设计算法时需要统计坐标周围8个方位雷的个数,假如要统计边界坐标周围雷的个数,那么就会有数组越界的问题,那我们就要在10X10的边界多上一圈元素,也就要定义12X12的数组元素,这些元素我们不要打印出来,心里有数就行。
【项目代码】:
game.h:
/********************************************************************************************* * 项目名称:扫雷游戏 * * 编译环境:Vs 2013 * * 创建日期:2018.4.18 * * 项目编辑:Mr.Yao * ***********************************************************************************************/ //知识点: //1.数组 //2.函数 //3.循环 //4.扩展内容: 递归 (内存换取时间) #ifndef __GAME_H_ #define __GAME_H_ #include <stdio.h> #include <Windows.h> #include <time.h> #include <string.h> enum opp { EXIT, PLAY }; #define EASY 10 #define HARD 30 #define ROW 10 #define COL 10 #define ROWS (ROW+2) #define COLS (COL+2) void InitMap(char arr[ROWS][COLS], int row,int col, char set); //创建初始化棋盘 void PrintMap(char arr[ROWS][COLS], int row, int col); //打印棋盘 void SetMy(char arr[ROWS][COLS], int row, int col, int count); //布雷 void SweepMap(char my_map[ROWS][COLS], char player_map[ROWS][COLS], int row, int cow, int sum); //扫雷 void MoveLei(char my_map[ROWS][COLS], int x, int y); //若第一次扫到雷,则移动雷的位置 void GetCount(char my_map[ROWS][COLS], char player_map[ROWS][COLS], int x, int y);//统计雷数 #endif
game.c:
#define _CRT_SECURE_NO_WARNINGS 1 #include "game.h" void InitMap(char arr[ROWS][COLS], int row, int col, char set) { memset(arr, set, col*row*sizeof(arr[0][0])); } void PrintMap(char arr[ROWS][COLS], int row, int col) { int i = 0; int j = 0; printf(" "); for (i = 1; i<=row ; i++) { printf("%3d", i); } printf("\n"); for (i = 0; i<=row; i++) { printf("---"); } printf("\n"); for (i = 1; i <= row; i++) { printf("%2d|", i); for (j = 1; j <= col ; j++) { printf("%3c", arr[i][j]); } printf("\n"); } } void SetMy(char arr[ROWS][COLS], int row, int col, int sum) { int count = sum; int x = 0; int y = 0; while (count) { x = rand() % row + 1; y = rand() % col + 1; if (arr[x][y] == '0') { arr[x][y] = '1'; count--; } } } void SweepMap(char my_map[ROWS][COLS],char player_map[ROWS][COLS], int row, int col, int sum) { int x = 0; int y = 0; int count = 0; int temp = 0; int win = 0; while (win < (row * col - sum)) { printf("请输入你扫雷坐标:>"); scanf("%d%d", &x, &y); temp++; if (x >= 1 && x <= row&&y >= 1 && y <= col) { while ((my_map[x][y] == '1') && (temp == 1)) { //保证玩家第一次不死 MoveLei(my_map, x, y); //对周围的雷数进行遍历 GetCount(my_map, player_map, x, y); } if (my_map[x][y] == '1') { printf("\n恭喜你,壮烈牺牲\n"); PrintMap(my_map, ROW, COL); break; } else { GetCount(my_map, player_map, x, y); printf("\n"); win++; } PrintMap(player_map, ROW, COL); } else { printf("坐标输入有误\n"); } } if(win == (row * col - sum)) { printf("恭喜你,排完了\n"); } } //若输入的坐标无雷,则要遍历周围,统计雷数 //若周围无雷,则递归遍历,统计周围雷数 void GetCount(char my_map[ROWS][COLS], char player_map[ROWS][COLS], int x, int y) { if ((my_map[x][y] == '0')) { int count = 0; if (my_map[x - 1][y - 1] == '1') count++; if (my_map[x - 1][y] == '1') count++; if (my_map[x - 1][y + 1] == '1') count++; if (my_map[x][y - 1] == '1') count++; if (my_map[x][y + 1] == '1') count++; if (my_map[x + 1][y - 1] == '1') count++; if (my_map[x + 1][y] == '1') count++; if (my_map[x + 1][y + 1] == '1') count++; player_map[x][y] = (count + '0'); } if (player_map[x][y] == '0') { if (player_map[x - 1][y - 1] == '*') GetCount(my_map, player_map, x - 1, y - 1); if (player_map[x - 1][y] == '*') GetCount(my_map, player_map, x - 1, y); if (player_map[x - 1][y + 1] == '*') GetCount(my_map, player_map, x - 1, y + 1); if (player_map[x][y - 1] == '*') GetCount(my_map, player_map, x, y - 1); if (player_map[x][y + 1] == '*') GetCount(my_map, player_map, x, y + 1); if (player_map[x + 1][y - 1] == '*') GetCount(my_map, player_map, x + 1, y - 1); if (player_map[x + 1][y] == '*') GetCount(my_map, player_map, x + 1, y); if (player_map[x + 1][y + 1] == '*') GetCount(my_map, player_map, x + 1, y + 1); } } //为提高游戏体验,设置玩家第一次无论如何都不会被炸死 void MoveLei(char my_map[ROWS][COLS], int x, int y) { int ret = 1; do { my_map[x][y] = '0'; while (ret) { x = rand() % ROW + 1; y = rand() % COL + 1; if (my_map[x][y] == '0') { my_map[x][y] = '1'; } ret--; } } while (ret); }
test.c:
#define _CRT_SECURE_NO_WARNINGS 1 #include "game.h" void GotoXY(int x, int y) //设定输出位置 { COORD c; c.X = x - 1; c.Y = y - 1; SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), c); } void meau() { GotoXY(10, 5); printf("开始游戏\n Let's Go!"); Sleep(1500); system("cls"); printf("**** 《扫雷》 ****\n"); printf("************************\n"); printf("******* 1.play *******\n"); printf("******* 0.exit *******\n"); printf("************************\n"); } void game() { int input = 0; int sum = 0; char my_map[ROWS][COLS]; char player_map[ROWS][COLS]; InitMap(my_map,ROWS,COLS,'0'); InitMap(player_map, ROWS, COLS, '*'); printf("**** 1.Easy 0.Hard *****\n"); scanf("%d", &input); switch (input) { case PLAY: sum = EASY; break; case EXIT: sum = HARD; break; default: printf("输入有误\n"); break; } printf("\n这个棋盘有%d个雷。\n", sum); SetMy(my_map,ROW,COL,sum); PrintMap(player_map, ROW, COL); //PrintMap(my_map, ROW, COL); SweepMap(my_map,player_map ,ROW, COL, sum); system("pause"); } void test() { int input = 0; do { meau(); printf("请选择:>"); scanf("%d", &input); switch (input) { case PLAY: game(); break; case EXIT: break; default: printf("输出有误\n"); } } while (input); } int main() { srand((unsigned)time(NULL)); test(); system("pause"); return 0; }