扫雷游戏的功能说明
- 使⽤控制台实现经典的扫雷游戏
- 游戏可以通过菜单实现继续玩或者退出游戏
- 扫雷的棋盘是9*9的格⼦
- 默认随机布置10个雷
- 可以排查雷
- 如果位置不是雷,就显⽰周围有⼏个雷
- 如果位置是雷,就炸死游戏结束
- 把除10个雷之外的所有⾮雷都找出来,排雷成功,游戏结束
简单介绍:在一个9*9的格子中,随机种10个雷。如果这个地方放置雷,就存放1,不是雷就存放0。通过输入坐标来排除雷 。
主体框架:我创建了3个文件,一个专门用来声明函数的头文件game.h、一个用来进行游戏数据的game.c和一个主体逻辑的saolei.c这三个文件。
棋盘:
这里出现了一个问题,假设我们排查(2,5)这个坐标时,我们访问周围的⼀圈8个⻩⾊位置,统计周围雷的个数是1。
假设我们排查(8,6)这个坐标时,我们访问周围的⼀圈8个⻩⾊位置,统计周围雷的个数时,最下⾯的三个坐标就会越界,为了防⽌越界,我们在设计的时候,给数组扩⼤⼀圈,雷还是布置在中间的9*9的坐标上,周围⼀圈不去布置雷就⾏,这样就解决了越界的问题。所以我们将存放数据的数组创建成11*11是⽐较合适。
所以我创建了两个二维数组分别是mine和show。show数组显示棋盘,mine数组用来埋雷和统计周围雷的个数,同时将雷的个数传到show数组上面记录。
saolei.c文件
这个文件我用来编写游戏的主要框架。在main()函数中引入一个自定义函数text(),text()用来是否进行游戏,进入游戏就输入1,退出游戏就输入0,输入其他数字就提示重新选择。假如要进行多次游戏,这里我就采用了以do while循环。
void test()
{srand((unsigned int)time(NULL));int input = 0;do{menu();printf("请选择:>");scanf("%d", &input);switch(input){case 1:game();break;case 0:printf("游戏结束,退出游戏\n");break;default:printf("选择错误,重新选择\n");break;}} while (input);
}
那么我们输入1呢,就开始进行游戏了。首先是创建了两个字符二维数组mine和show,这两个数组都是11*11的,避免之后在9*9的棋盘中出现越界的情况。之后就是对这两个数组进行初始化。我创建了一个专门用来初始化棋盘的函数InitBoard。因为要对mine和show数组都要初始化,所以这个函数要传递4个参数,分别要传递数组,行和列、要初始化的值。注意传参时要一一对应。
void InitBoard(char arr[ROWS][COLS], int rows, int cols, char set)
{int i = 0;for (i = 0; i < rows; i++){int j = 0;for (j = 0; j < cols; j++){arr[i][j] = set;}}
}
接下来就是埋雷了,这里创建一个SetMine()函数,注意雷是在mine数组9*9上埋的。SetMine()函数传递3个参数,mine数组 行ROW和列COL。扫雷的精髓就是随机埋雷。这里就用到了上一次在猜数字游戏中讲到的rand和srand函数。不了解的可以去了解一下。当你输入的坐标不是雷(‘0’)就可以在这个位置上埋雷,埋上一个雷,雷的数量就减1,直到减为0,这里用一个while循环。
void SetMine(char arr[ROWS][COLS], int row, int col)
{int count = EASY;while (count){int x = rand() % row + 1;int y = rand() % col + 1;if (arr[x][y] == '0'){arr[x][y] = '1';count--;}}
}
打印棋盘:创建一个DisplayBoard函数用来打印棋盘(打印的是show,你也不想让你埋的雷可以看见吧)。打印棋盘是为了方面后面输入坐标,可以先把坐标轴先打印出来。打印的棋盘是9*9的。
void DisplayBoard(char arr[ROWS][COLS], int row, int col)
{printf("-----扫雷开始-----\n");int i = 0;//打印列for (i = 0; i <= col; i++){printf("%d ", i);}printf("\n");for (i = 1; i <= row; i++){int j = 0;printf("%d ", i);for (j = 1; j <= col; j++){printf("%c ", arr[i][j]);}printf("\n");}
}
接下来就是排雷了。创建了一个FindMine()函数,这个函数要传递4个参数,分别是mine,show,ROW和COL。排雷的时候要注意输入坐标的有效性,要保证坐标在9*9的棋盘中有效。当这个坐标不是雷的时候,我们还要统计这个坐标周围一圈有多少个雷,并传递给show数组上显示出来。还要注意这个坐标是否被排查过了。当所有非雷坐标都被排查过了,那么你就胜利了。
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-EASY){printf("请输入要查找的坐标:");scanf("%d %d", &x, &y);//判断坐标的有效性if (x >= 1 && x <= row && y >= 1 && y <= col){if (show[x][y] == '*'){if (mine[x][y] == '1'){printf("很遗憾你被炸死了\n");break;}else{//找出周围有几个雷int count = GetMine(mine, x, y);//数字转字符show[x][y] = count + '0';DisplayBoard(show, ROW, COL);win++;}}else{printf("该坐标已经被排查了\n");}}else{printf("坐标非法,请重新输入坐标\n");}}if (win == row * col - EASY){printf("恭喜你,胜利了!\n");}
}
那么呈上扫雷游戏的全部代码:
game.h:
#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 EASY 10//初始化棋盘
void InitBoard(char arr[ROWS][COLS], int rows, int cols, char set);//打印棋盘
void DisplayBoard(char arr[ROWS][COLS], int row, int col);//布置雷
void SetMine(char arr[ROWS][COLS], int row, int col);//排雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
game.c:
#define _CRT_SECURE_NO_WARNINGS 1//游戏数据
#include "game.h"void InitBoard(char arr[ROWS][COLS], int rows, int cols, char set)
{int i = 0;for (i = 0; i < rows; i++){int j = 0;for (j = 0; j < cols; j++){arr[i][j] = set;}}
}void DisplayBoard(char arr[ROWS][COLS], int row, int col)
{printf("-----扫雷开始-----\n");int i = 0;//打印列for (i = 0; i <= col; i++){printf("%d ", i);}printf("\n");for (i = 1; i <= row; i++){int j = 0;printf("%d ", i);for (j = 1; j <= col; j++){printf("%c ", arr[i][j]);}printf("\n");}
}void SetMine(char arr[ROWS][COLS], int row, int col)
{int count = EASY;while (count){int x = rand() % row + 1;int y = rand() % col + 1;if (arr[x][y] == '0'){arr[x][y] = '1';count--;}}
}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-EASY){printf("请输入要查找的坐标:");scanf("%d %d", &x, &y);//判断坐标的有效性if (x >= 1 && x <= row && y >= 1 && y <= col){if (show[x][y] == '*'){if (mine[x][y] == '1'){printf("很遗憾你被炸死了\n");break;}else{//找出周围有几个雷int count = GetMine(mine, x, y);//数字转字符show[x][y] = count + '0';DisplayBoard(show, ROW, COL);win++;}}else{printf("该坐标已经被排查了\n");}}else{printf("坐标非法,请重新输入坐标\n");}}if (win == row * col - EASY){printf("恭喜你,胜利了!\n");}
}int GetMine(char mine[ROWS][COLS], int x, int y)
{int i = 0;int count = 0;for (i = x - 1; i <= x + 1; i++){int j = 0;for (j = y - 1; j <= y + 1; j++){//字符转数字count += (mine[i][j] - '0');}}return count;
}
saolei.c:
#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] = { 0 };char show[ROWS][COLS] = { 0 };//初始化棋盘InitBoard(mine, ROWS, COLS, '0');InitBoard(show, ROWS, COLS, '*');//布置雷SetMine(mine, ROW, COL);//DisplayBoard(mine, ROW, COL);//打印棋盘DisplayBoard(show, ROW, COL);//排雷FindMine(mine, show, ROW, COL);}void test()
{srand((unsigned int)time(NULL));int input = 0;do{menu();printf("请选择:>");scanf("%d", &input);switch(input){case 1:game();break;case 0:printf("游戏结束,退出游戏\n");break;default:printf("选择错误,重新选择\n");break;}} while (input);
}int main()
{test();return 0;
}