1.扫雷是一款经典的游戏,用二维数组的使用去实现,加上许多函数的接口,和玩家的选择要求;
如何实现扫雷:
先创建三个文件,
1.game.c(函数接口定义)
2.game.h (函数声明)
3. test.c(测试游戏)
第一步宏定义棋盘及炸弹:我们设置好行数和列数之后,再在其基础上设置一个辅助棋盘既周围扩大一圈的棋盘,分别在行数及列数的基础上加二,然后我们设置炸弹数,用宏定义的好处是后期修改时方便
#define ROW 9 #define COL 9 #define ROWS ROW+2 #define COLS COL+2 #define BOMBSNUM 10 #define SAFENUM ROW*COL-BOMBSNUM
初始化棋盘:(注意:如果不初始化,那么打印出来的都是随机值)
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; } } }
接下来放置炸弹:用字符0和1来代表炸弹可以方便我们后面计算周围的炸弹
void SetBombs(char Bombs[ROWS][COLS], int row, int col, int Bombsnum) { int x, y,count=0; while( count < Bombsnum ) { x = rand() % row+1; y = rand() % col+1; if (Bombs[x][y] != '1') { Bombs[x][y] = '1'; count++; } } }
使用rand函数来获取一个随机的坐标,当坐标不重复并且所处位置没有炸弹时,将炸弹存放
显示菜单:
void GameMenu() { printf("*****************************************\n"); printf("********* 1.开始游戏 *********\n"); printf("********* 0.结束游戏 *********\n"); printf("*****************************************\n"); }
初始化棋盘后,那么我们就显示棋盘:
void ShowBoard(char Board[ROWS][COLS], int row, int col) { int i, j; printf(" "); for (i = 0; i < row+1; i++) { printf("%d ",i); } printf("\n"); for (i = 0; i < row; i++) { if (0 == i) printf(" |"); else printf("|"); printf("---"); } printf("|\n"); for (i = 0; i < row; i++) { for (j = 0; j < col; j++) { if (0 == j) { printf(" "); printf("%d ", i + 1); printf("|"); } printf(" %c |", Board[i+1][j+1]); } printf("\n"); for (j = 0; j < col; j++) { if ( 0 == j ) printf(" |"); printf("---|"); } printf("\n"); } }
还有一点计算炸弹的周围个数:
因为我们之前初始化时将用字符1代表有炸弹,字符0代表没有炸弹,所以在这一部我们可以利用这个规律,来计算周围的炸弹数。我们只需要让选择的位置周边的八个格子全部相加,然后减去8个字符0,即可得到整形的炸弹数,而后在主函数给其加上一个字符0将其将这个数字变为字符型的对应数字,存放与棋盘中
int BombsAround(char Bombs[ROWS][COLS], int row, int col) { return Bombs[row - 1][col] + Bombs[row + 1][col] + Bombs[row][col - 1] + Bombs[row][col + 1] + Bombs[row + 1][col + 1] + Bombs[row - 1][col - 1] + Bombs[row + 1][col - 1] + Bombs[row - 1][col + 1] - 8 * '0'; }
游戏的胜负输赢条件:
int WinGame(char Board[ROWS][COLS], int row, int col) { int i, j, flag=0; for (i=1; i < row; i++) { for (j = 1; j < col; j++) { if (Board[i][j] == '*') flag++; } } return flag; }
我们只需要计算棋盘中剩余的炸弹数,当剩余炸弹数等于我们的放置炸弹数时,游戏胜利
1.当第一次为炸弹时,将炸弹移动到别的位置:
这个函数实现的方法很简单,我们只需要将那个位置的炸弹清空,再次调用SetBombs函数重新设置一个炸弹即可。
int BombsAround(char Bombs[ROWS][COLS], int row, int col) { return Bombs[row - 1][col] + Bombs[row + 1][col] + Bombs[row][col - 1] + Bombs[row][col + 1] + Bombs[row + 1][col + 1] + Bombs[row - 1][col - 1] + Bombs[row + 1][col - 1] + Bombs[row - 1][col + 1] - 8 * '0'; }
2.当我们选择的位置周边不存在炸弹,同时以九宫格的方式扩撒,将周边不存在炸弹的地方展开
这个很简单我们就可以想到用递归函数来完成,我们只需要用BombsAround函数来知道这个位置是否存在炸弹,如果不存在则显示为‘ ’,如果存在则显示炸弹数。我们可以用递归的方式,当位置合法时,对他周围的八个格子进行判断,那八个格子再对他们周围的格子进行判断
void SafeArea(char Board[ROWS][COLS], char Bombs[ROWS][COLS], int row, int col) { int flag; flag = BombsAround(Bombs, row, col); if (0 == flag) { Board[row][col] = ' '; if (row - 1 > 0 && row + 1 <= ROW && col > 0 && col <= COL && Board[row - 1][col] == '*') SafeArea(Board, Bombs, row-1, col); if (row + 1 > 0 && row + 1 <= ROW && col > 0 && col <= COL && Board[row +1 ][col] == '*') SafeArea(Board, Bombs, row+1, col); if (row > 0 && row <= ROW && col - 1 > 0 && col - 1 <= COL && Board[row][col - 1] == '*') SafeArea(Board, Bombs, row, col-1); if (row > 0 && row <= ROW && col + 1 > 0 && col + 1 <= COL && Board[row][col + 1] == '*') SafeArea(Board, Bombs, row, col+1); if (row - 1 > 0 && row - 1 <= ROW && col - 1 > 0 && col - 1 <= COL && Board[row - 1][col - 1] == '*') SafeArea(Board, Bombs, row-1, col-1); if (row + 1 > 0 && row + 1 <= ROW && col + 1 > 0 && col + 1 <= COL && Board[row + 1][col + 1] == '*') SafeArea(Board, Bombs, row+1, col+1); if (row - 1 > 0 && row - 1 <= ROW && col + 1 > 0 && col + 1 <= COL && Board[row - 1][col + 1] == '*') SafeArea(Board, Bombs, row-1, col+1); if (row + 1 > 0 && row + 1 <= ROW && col - 1 > 0 && col - 1 <= COL && Board[row + 1][col - 1] == '*') SafeArea(Board, Bombs, row+1, col-1); } else { Board[row][col] = BombsAround(Bombs, row, col) + '0'; } }
排查炸弹:
char FindBombs(char Board[ROWS][COLS], char Bombs[ROWS][COLS], int row, int col) { int x, y,count=1; while(count) { printf("请输入行和列:\n"); scanf("%d%d",&x,&y); system("CLS"); if (x > 0 && x <= row && y > 0 && y <= col) { if (Bombs[x][y] == '1') { if (1 == count) { MoveBomb(Bombs, x, y); Board[x][y] = BombsAround(Bombs, x, y) + '0'; if (Board[x][y] == '0') Board[x][y] = ' '; SafeArea(Board, Bombs, x, y); count++; } else { ShowBoard(Bombs, ROW, COL); return 'F'; } } else if (Board[x][y] >= '0' && Board[x][y] <= '8' && Board[x][y] != '*' && Board[x][y] != ' ') { printf("该坐标已被输入\n"); } else { Board[x][y] = BombsAround(Bombs, x, y) + '0'; SafeArea(Board, Bombs, x, y); count++; if (WinGame(Board, ROW, COL) == BOMBSNUM) return 'T'; ShowBoard(Board, ROW, COL); } } else { printf("输入错误,请重新输入\n"); } } }
我们需要判断输入是否合法,输入是否重复,如果错误则重新输入,当输入的位置为炸弹时,如果是第一次输入,则将炸弹移动到别的位置,如果不是第一次输入,则代表游戏失败,返回’F’。每次输入完一个位置,我们将那个位置周围的炸弹数保存到Board棋盘中,既玩家看到的棋盘,然后再使用展开函数来展开周围不必要的格子,并且用WinGame函数判断是否胜利。
void Game(char Board[ROWS][COLS],char Bombs[ROWS][COLS], int row, int col) { char flag; InitBoard(Board, ROWS, COLS, '*'); InitBoard(Bombs, ROWS, COLS, '0'); SetBombs(Bombs, ROW, COL, BOMBSNUM); ShowBoard(Board, ROW, COL); printf("\n"); ShowBoard(Bombs, ROW, COL); flag = FindBombs(Board, Bombs, ROW, COL); if (flag == 'F') { printf("该位置为炸弹,游戏结束\n"); } else { printf("游戏胜利\n"); } }
上面想说的都说完了,完整代码如下:
game.c文件:
#include "game.h" void GameMenu() { printf("*****************************************\n"); printf("********* 1.开始游戏 *********\n"); printf("********* 0.结束游戏 *********\n"); printf("*****************************************\n"); } 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 SetBombs(char Bombs[ROWS][COLS], int row, int col, int Bombsnum) { int x, y,count=0; while( count < Bombsnum ) { x = rand() % row+1; y = rand() % col+1; if (Bombs[x][y] != '1') { Bombs[x][y] = '1'; count++; } } } //放置炸弹 void ShowBoard(char Board[ROWS][COLS], int row, int col) { int i, j; printf(" "); for (i = 0; i < row+1; i++) { printf("%d ",i); } printf("\n"); for (i = 0; i < row; i++) { if (0 == i) printf(" |"); else printf("|"); printf("---"); } printf("|\n"); for (i = 0; i < row; i++) { for (j = 0; j < col; j++) { if (0 == j) { printf(" "); printf("%d ", i + 1); printf("|"); } printf(" %c |", Board[i+1][j+1]); } printf("\n"); for (j = 0; j < col; j++) { if ( 0 == j ) printf(" |"); printf("---|"); } printf("\n"); } } //界面 int BombsAround(char Bombs[ROWS][COLS], int row, int col) { return Bombs[row - 1][col] + Bombs[row + 1][col] + Bombs[row][col - 1] + Bombs[row][col + 1] + Bombs[row + 1][col + 1] + Bombs[row - 1][col - 1] + Bombs[row + 1][col - 1] + Bombs[row - 1][col + 1] - 8 * '0'; } //算出周围的炸弹 void MoveBomb(char Bombs[ROWS][COLS], int row, int col) { Bombs[row][col] = '0'; SetBombs(Bombs, ROW, COL, 1); } //防止玩家第一次选择时遇到炸弹,将炸弹移动到别的位置 void SafeArea(char Board[ROWS][COLS], char Bombs[ROWS][COLS], int row, int col) { int flag; flag = BombsAround(Bombs, row, col); if (0 == flag) { Board[row][col] = ' '; if (row - 1 > 0 && row + 1 <= ROW && col > 0 && col <= COL && Board[row - 1][col] == '*') SafeArea(Board, Bombs, row-1, col); if (row + 1 > 0 && row + 1 <= ROW && col > 0 && col <= COL && Board[row +1 ][col] == '*') SafeArea(Board, Bombs, row+1, col); if (row > 0 && row <= ROW && col - 1 > 0 && col - 1 <= COL && Board[row][col - 1] == '*') SafeArea(Board, Bombs, row, col-1); if (row > 0 && row <= ROW && col + 1 > 0 && col + 1 <= COL && Board[row][col + 1] == '*') SafeArea(Board, Bombs, row, col+1); if (row - 1 > 0 && row - 1 <= ROW && col - 1 > 0 && col - 1 <= COL && Board[row - 1][col - 1] == '*') SafeArea(Board, Bombs, row-1, col-1); if (row + 1 > 0 && row + 1 <= ROW && col + 1 > 0 && col + 1 <= COL && Board[row + 1][col + 1] == '*') SafeArea(Board, Bombs, row+1, col+1); if (row - 1 > 0 && row - 1 <= ROW && col + 1 > 0 && col + 1 <= COL && Board[row - 1][col + 1] == '*') SafeArea(Board, Bombs, row-1, col+1); if (row + 1 > 0 && row + 1 <= ROW && col - 1 > 0 && col - 1 <= COL && Board[row + 1][col - 1] == '*') SafeArea(Board, Bombs, row+1, col-1); } else { Board[row][col] = BombsAround(Bombs, row, col) + '0'; } } int WinGame(char Board[ROWS][COLS], int row, int col) { int i, j, flag=0; for (i=1; i < row; i++) { for (j = 1; j < col; j++) { if (Board[i][j] == '*') flag++; } } return flag; } char FindBombs(char Board[ROWS][COLS], char Bombs[ROWS][COLS], int row, int col) { int x, y,count=1; while(count) { printf("请输入行和列:\n"); scanf("%d%d",&x,&y); system("CLS"); if (x > 0 && x <= row && y > 0 && y <= col) { if (Bombs[x][y] == '1') { if (1 == count) { MoveBomb(Bombs, x, y); Board[x][y] = BombsAround(Bombs, x, y) + '0'; SafeArea(Board, Bombs, x, y); count++; } else { ShowBoard(Bombs, ROW, COL); return 'F'; } } else if (Board[x][y] >= '0' && Board[x][y] <= '8' && Board[x][y] != '*' && Board[x][y] != ' ') { printf("该坐标已被输入\n"); } else { Board[x][y] = BombsAround(Bombs, x, y) + '0'; SafeArea(Board, Bombs, x, y); count++; if (WinGame(Board, ROW, COL) == BOMBSNUM) return 'T'; ShowBoard(Board, ROW, COL); } } else { printf("输入错误,请重新输入\n"); } } } //排查炸弹 void Game(char Board[ROWS][COLS],char Bombs[ROWS][COLS], int row, int col) { char flag; InitBoard(Board, ROWS, COLS, '*'); InitBoard(Bombs, ROWS, COLS, '0'); SetBombs(Bombs, ROW, COL, BOMBSNUM); ShowBoard(Board, ROW, COL); printf("\n"); flag = FindBombs(Board, Bombs, ROW, COL); if (flag == 'F') { printf("该位置为炸弹,游戏结束\n"); } else { printf("游戏胜利\n"); } }
test.c文件:
#include "game.h" int main() { int n; char board[ROWS][COLS] = { 0 }; char bombs[ROWS][COLS] = { 0 }; srand((int)time(NULL)); do { GameMenu(); printf("请输入您的选择:\n"); scanf("%d", &n); switch (n) { case 1: Game(board, bombs, ROWS, COLS); break; case 0: printf("结束游戏\n"); break; default: printf("输入错误,请重新输入\n"); break; } }while (n); return 0; }
game.h文件:
#define _CRT_SECURE_NO_WARNINGS #pragma once #include<stdio.h> #include<stdlib.h> #include<time.h> #define ROW 9 #define COL 9 #define ROWS ROW+2 #define COLS COL+2 #define BOMBSNUM 10 void GameMenu(); void InitBoard(char Board[ROWS][COLS], int row, int col, char ch); void SetBombs(char Bombs[ROWS][COLS], int row, int col, int Bombsnum); void ShowBoard(char Board[ROWS][COLS], int row, int col); int BombsAround(char Bombs[ROWS][COLS], int row, int col); char FindBombs(char Board[ROWS][COLS], char Bombs[ROWS][COLS], int row, int col); void Game(char Board[ROWS][COLS], char Bombs[ROWS][COLS], int row, int col); void MoveBomb(char Bombs[ROWS][COLS], int row, int col); void OpenMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col, int x, int y); void SafeArea(char Board[ROWS][COLS], char Bombs[ROWS][COLS], int row, int col);
扫雷到此设计结束了,感谢您的阅读!!!如果内容对您有所帮助,记得给我点赞,关注,收藏,谢谢!后续持续更新!!!