1.游戏的实现
-
使用控制台实现经典的扫雷游戏
-
游戏可以通过菜单实现继续玩或者退出游戏
-
扫雷的棋盘是9*9的格⼦ 二维数组
-
默认随机布置10个雷
-
可以排查雷
-
如果位置不是雷,就显示周围有几个雷
◦ 如果位置是雷,就炸死游戏结束
◦ 把除10个雷之外的所有非雷都找出来,排雷成功,游戏结束
写代码的时候需要注意的点
1.在初始化棋盘的时候我们为了避免定义两个初试化的函数,我们直接多定义一个变量用量存放棋盘格的样式char set
//test.c
void game() {
char mine[ROWS][COLS] = { 0 };
char show[ROWS][COLS] = { 0 };
//初始化棋盘
InitBoard(mine, ROWS, COLS,'0');
InitBoard(show, ROWS, COLS,'*');
}
//game.h
#include <stdio.h> //把该头文件直接放在game.h不需要每次都导入
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
void InitBoard(char board[ROWS][COLS], int rows, int cols,char set);
//game.c
#include <stdio.h>
#include "game.h"
//扫雷游戏
void InitBoard(char board[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++) {
board[i][j] = set;
}
}
}
2.打印棋盘的时候,我们只需要打印9 * 9的数组即可 数组的变量我们置为ROW COL
//test.c
void game() {
char mine[ROWS][COLS] = { 0 };
char show[ROWS][COLS] = { 0 };
//初始化棋盘
InitBoard(mine, ROWS, COLS,'0');
InitBoard(show, ROWS, COLS,'*');
//显示棋盘
DisplayBoard(show, ROW, COL);
DisplayBoard(mine, ROW, COL);
}
//game.h
void DisplayBoard(char board[ROWS][COLS], int row, int col);
//game.c
//打印棋盘
void DisplayBoard(char board[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++) {
printf("%d ", i); //显示行数
int j = 0;
for (j = 1; j <= col; j++) {
printf("%c ", board[i][j]);
}
printf("\n");
}
}
3.设置雷的时候,用随机函数设置十个雷,然后随机放在棋盘上
//game.c
//设置雷
void SetMine(char mine[ROWS][COLS], int row, int col) {
int count = EASY_COUNT;
int x = 0;
int y = 0;
while (count) //count--当放雷次数用完的时候退出循环
{
x = rand()%row+1; //随机放到0-9行
y = rand()%col+1;
if (mine[x][y] != '1') {
mine[x][y] = '1';//当棋盘格不是 1 的时候设置一个雷
count--;
}
}
}
4.排查雷(不断循环)
-
输入一个坐标
-
判断这个坐标是否越界
-
判断这个位置是不是雷
1.如果是雷,就炸死了,游戏结束
2.如果不是雷,就统计这个位置周围雷的个数,显示
-
统计这个位置周围雷的个数
一个字符怎么样得到数字本身? 用字符减去字符0即可( '1' - '0' = 1)
怎么排查周围的八个坐标位置有多少个雷, 用所有坐标加起来减去8乘' 0 '
//统计雷个数
int GetMineCount(char mine[ROW][COL],int x,int y) {
int i = 0;
int count = 0;
//循环更方便
for (i = -1; i <= 1; i++) {
int j = 0;
for (j = -1; j <= 1; j++) {
count += (mine[x + i][y + j] - '0');
}
}
return count; //将count返回
}
-
排雷代码
//排查雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col) {
int x = 0;
int y = 0;
while (1) { //死循环 不断的排查
printf("请输入要排查的目标:");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col) { //判断用户输入的数值不能越界 9行9列
if (mine[x][y] == '1') { //踩雷的话 游戏结束
printf("您已经踩雷,游戏结束");
DisplayBoard(mine, ROW, COL); //显示给用户看 雷的位置在哪里
break;
}
else
{
//如果不是雷的,就统计该位置的周围的八个位置中雷的个数
//定义一个统计雷个数的函数
int count = GetMineCount(mine, x, y);
show[x][y] = count + '0'; //要将字符数字显示到show数组的位置
DisplayBoard(show, ROW, COL);//布置雷的个数显示出来
}
}
else
{
printf("输入坐标有误x(1~9),y(1~9),请重新输入\n");
}
}
-
但是这个代码有问题,当我们完全排雷完的时候,怎么结束游戏然后胜利呢?
-
总共9×9=81个坐标 我们放了十个雷 那就是有 71个位置,当71个位置全排完,游戏就结束
//排查雷
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col) {
int x = 0;
int y = 0;
int win = 0; //定义 除了10个雷 之外的格子数 81 - 10 = 71个
while (win<col*row-EASY_COUNT) { //死循环 不断的排查 当排查次数超过71次的时候退出循环
printf("请输入要排查的目标:");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col) { //判断用户输入的数值不能越界 9行9列
if (mine[x][y] == '1') { //踩雷的话 游戏结束
printf("您已经踩雷,游戏结束");
DisplayBoard(mine, ROW, COL); //显示给用户看 雷的位置在哪里
break;
}
else
{
//如果不是雷的,就统计该位置的周围的八个位置中雷的个数
//定义一个统计雷个数的函数
int count = GetMineCount(mine, x, y);
show[x][y] = count + '0'; //要将字符数字显示到show数组的位置
DisplayBoard(show, ROW, COL);//布置雷的个数显示出来
win++;//每排一次雷 win就加一次
}
}
else
{
printf("输入坐标有误x(1~9),y(1~9),请重新输入\n");
}
}
if (win == col * row - EASY_COUNT) { //因为踩雷了也会同样执行到这里 我们需要写个判断
printf("恭喜您,排雷成功!!!!!\n");
DisplayBoard(mine, ROW, COL);//把排雷的情况显示给玩家
}
}
-
完整代码
1.game.h
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h> //把该头文件直接放在game.h不需要每次都导入
#include <time.h>
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
#define EASY_COUNT 10
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 mine[ROWS][COLS], int row, int col);
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);
2.game.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
//扫雷游戏
//初始化棋盘
void InitBoard(char board[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++) {
board[i][j] = set;
}
}
}
//打印棋盘
void DisplayBoard(char board[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++) {
printf("%d ", i); //显示行数
int j = 0;
for (j = 1; j <= col; j++) {
printf("%c ", board[i][j]);
}
printf("\n");
}
}
//设置雷
void SetMine(char mine[ROWS][COLS], int row, int col) {
int count = EASY_COUNT;
int x = 0;
int y = 0;
while (count) //count--当放雷次数用完的时候退出循环
{
x = rand()%row+1; //随机放到0-9行
y = rand()%col+1;
if (mine[x][y] != '1') {
mine[x][y] = '1';//当棋盘格不是 1 的时候设置一个雷
count--;
}
}
}
//统计雷个数
int GetMineCount(char mine[ROW][COL],int x,int y) {
int i = 0;
int count = 0;
//循环更方便
for (i = -1; i <= 1; i++) {
int j = 0;
for (j = -1; j <= 1; j++) {
count += (mine[x + i][y + j] - '0');
}
}
return count; //将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<col*row-EASY_COUNT) { //死循环 不断的排查 当排查次数超过71次的时候退出循环
printf("请输入要排查的目标:");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row && y >= 1 && y <= col) { //判断用户输入的数值不能越界 9行9列
if (mine[x][y] == '1') { //踩雷的话 游戏结束
printf("您已经踩雷,游戏结束");
DisplayBoard(mine, ROW, COL); //显示给用户看 雷的位置在哪里
break;
}
else
{
//如果不是雷的,就统计该位置的周围的八个位置中雷的个数
//定义一个统计雷个数的函数
int count = GetMineCount(mine, x, y);
show[x][y] = count + '0'; //要将字符数字显示到show数组的位置
DisplayBoard(show, ROW, COL);//布置雷的个数显示出来
win++;//每排一次雷 win就加一次
}
}
else
{
printf("输入坐标有误x(1~9),y(1~9),请重新输入\n");
}
}
if (win == col * row - EASY_COUNT) { //因为踩雷了也会同样执行到这里 我们需要写个判断
printf("恭喜您,排雷成功!!!!!\n");
DisplayBoard(mine, ROW, COL);//把排雷的情况显示给玩家
}
}
3.test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
void menu() {
printf("*****************************************\n");
printf("*************1.-->进入游戏***************\n");
printf("*************2.-->退出游戏***************\n");
printf("*****************************************\n");
}
void game() {
char mine[ROWS][COLS] = { 0 };
char show[ROWS][COLS] = { 0 };
//1.初始化棋盘
InitBoard(mine, ROWS, COLS ,'0');
InitBoard(show, ROWS, COLS ,'*');
//2.显示棋盘
DisplayBoard(show, ROW, COL);
printf("\n");
//DisplayBoard(mine, ROW, COL);
//3.布置雷
SetMine(mine, ROW, COL);
//DisplayBoard(mine, ROW, COL);
//4.排查雷
FindMine(mine, show, ROW, COL);//排查的时候两个数组都需改变
}
void test() {
int input = 0;
srand((unsigned int)time(NULL)); //用时间戳实现真正的随机数
do
{
menu();
printf("请选择:");
scanf("%d", &input);
switch (input)
{
case 1:
printf("进入扫雷游戏!!\n");
game();
break;
case 2:
printf("退出游戏!!");
break;
default:
printf("输入数字有误,请输入正确的数字\n");
}
} while (input); //input 等于0的时候退出游戏,其他数字都继续进行游戏
}
int main() {
test();
}
2.扫雷游戏的扩展
1.是否可以选择游戏难度
简单 9*9 棋盘,10个雷
中等 16*16棋盘,40个雷
困难 30*16棋盘,99个雷
2.如果排查位置不是雷,周围也没有雷,可以展开周围的⼀⽚
是否可以标记雷
是否可以加上排雷的时间显⽰
•
如果排查位置不是雷,周围也没有雷,可以展开周围的⼀⽚
•
是否可以标记雷
•
是否可以加上排雷的时间显⽰