扫雷游戏的功能说明 :
• 使⽤控制台实现经典的扫雷游戏
• 游戏可以通过菜单实现继续玩或者退出游戏
• 扫雷的棋盘是9*9的格⼦
• 默认随机布置10个雷
• 可以排查雷:
◦ 如果位置不是雷,就显⽰周围有⼏个雷
◦ 如果位置是雷,就炸死游戏结束
◦ 把除10个雷之外的所有⾮雷都找出来,排雷成功,游戏结束
c
test.c //⽂件中写游戏的测试逻辑
game.c //⽂件中写游戏中函数的实现等
game.h //⽂件中写游戏需要的数据类型和函数声明等
逻辑开始:
一、菜单
- 输入1进入游戏,输入0退出游戏,输入其他数字显示输入错误,并且重新输入
c
test.c
#include "game.h"
int main()
{
menu();
{
regain:
printf("请输入你的选择:");
int input1;
scanf("%d", &input1);
switch (input1)
{
case 1:
{
printf("进入游戏\n");
game();
break;
}
case 0:
{
printf("退出游戏\n");
break;
}
default:
{
printf("输入错误,请重新输入:");
goto regain;
}
}
}
return 0;
}
c
game.c
#include "game.h"
void menu()
{
printf("****************\n");
printf("**** 1.Play ****\n");
printf("**** 0.Quit ****\n");
printf("****************\n");
}
c
game.h
#pragma once
#include <stdio.h>
#include "game.h"
//菜单
void menu();
二、生成 9X9 的游戏界面
- 使用二维数组实现
- 运用两个棋盘,一个用于展示,一个用于设置雷,写出初始化棋盘的函数
- 将展示的棋盘
char show
全部初始化为'*'
,将布置雷的棋盘char mine
全部初始化为0
- 为方便后边测试,可以先把打印棋盘的函数写出
test.c文件增加了以下代码
c
test.c
#include "game.h"
void game()
{
//用于布置雷的二维数组
char mine[ROWS][COLS] = { 0 };
//用于游戏界面的的二维数组
char show[ROWS][COLS] = { 0 };
//用于游戏界面的的二维数组全部初始为 '*'
set_keyboard(show, ROWS, COLS, '*');
//用于布置雷的二维数组全部初始化为 '0'
set_keyboard(mine, ROWS, COLS, '0');
//打印函数
printf_keyboard(show, ROW, COL);
printf_keyboard(mine, ROW, COL);
}
game.c文件增加了以下代码
c
game.c
#include "game.h"
//初始化棋盘
void set_keyboard(char board[ROWS][COLS], int rows, int cols, char set)
{
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
board[i][j] = set;
}
}
}
//展示棋盘
void printf_keyboard(char board[ROWS][COLS], int row, int col)
{
printf("-------扫雷--------\n");
for (int r = 0; r <= row; r++)
{
printf("%d ", r);
}
printf("\n");
for (int i = 1; i <= row; i++)
{
printf("%d ", i);
for (int j = 1; j <= col; j++)
{
printf("%c ", board[i][j]);
}
printf("\n");
}
}
game.c文件增加了以下代码
c
#pragma once
#include <stdio.h>
#include "game.h"
#define ROW 9
#define COL 9
#define ROWS ROW+3
#define COLS COL+2
//菜单
void menu();
//初始化棋盘
void set_keyboard(char board[ROWS][COLS], int rows, int cols, char set);
//展示棋盘
void printf_keyboard(char board[ROWS][COLS], int row, int col);
三、随机布置雷
- 使用
srand((unsigned int) time(NULL))
和rand()
- 将雷设置为
1
,雷只能布置在char mine[x][y] == '0'
的地方
game.h文件增加了
#include <time.h>
#include "stdlib.h"
#define MINE 10
void set_mine(char board[ROWS][COLS], int row, int col, int mine);
c
game.h
#pragma once
#include <stdio.h>
#include "game.h"
#include <time.h>
#include "stdlib.h"
#define ROW 9
#define COL 9
#define ROWS ROW+3
#define COLS COL+2
#define MINE 10
//菜单
void menu();
//初始化棋盘
void set_keyboard(char board[ROWS][COLS], int rows, int cols, char set);
//展示棋盘
void printf_keyboard(char board[ROWS][COLS], int row, int col);
//随机布置雷
void set_mine(char board[ROWS][COLS], int row, int col, int mine);
c
game.c文件增加以下代码
game.c
//随机布置雷
void set_mine(char board[ROWS][COLS], int row, int col, int mine)
{
srand((unsigned int) time(NULL));
while (mine)
{
int x = (rand() % row) + 1;
int y = (rand() % col) + 1;
if (board[x][y] == '0');
{
board[x][y] = '1';
mine--;
}
}
}
test.c文件增加以下代码
c
test.c
//随机布置雷
set_mine(mine, ROW, COL, MINE);
四、排雷
- 注意输入的坐标,横纵坐标都只能是
0~9
,出现其他数字报错,并重新输入
- 所排的坐标要显示周围雷的个数,如果为
0
,展开周围的棋盘(运用到递归) - 如果所排的坐标是雷,显示
游戏结束
- 如果输入的坐标是已经输入过的坐标,显示
该坐标已经排除
- 判断游戏胜利,
排除的坐标个数与减掉雷后的格子数相等
test.c文件布局改为以下情况
c
test.c
void game()
{
//用于布置雷的二维数组
char mine[ROWS][COLS] = { 0 };
//用于游戏界面的的二维数组
char show[ROWS][COLS] = { 0 };
//用于游戏界面的的二维数组全部初始为 '*'
set_keyboard(show, ROWS, COLS, '*');
//用于布置雷的二维数组全部初始化为 '0'
set_keyboard(mine, ROWS, COLS, '0');
//随机布置雷
set_mine(mine, ROW, COL, MINE);
//打印函数
printf_keyboard(show, ROW, COL);
//printf_keyboard(mine, ROW, COL);
//排雷
move_mine(show, mine, ROW, COL);
}
game.c文件增加了以下代码
c
game.c
//计算周围雷的个数
int Count_mine(char mine[ROWS][COLS], int x, int y)
{
return mine[x][y] - '0';
}
//展开棋盘----递归
void Open_keyboard(char show[ROWS][COLS], char mine[ROWS][COLS], int x, int y)
{
//写递归首先写结束条件
//越界时,返回
if ((x > (ROWS - 2)) || (x < 1) || (y > (COLS - 2)) || (y < 1))
{
return;
}
//遇到以及排过雷的坐标返回
if (show[x][y] != '*')
{
return;
}
//计算雷的个数
int count = 0;
for (int i = -1; i <= 1; i++)
{
for (int j = -1; j <= 1; j++)
{
count += Count_mine(mine, x + i, y + j);
}
}
show[x][y] = count + '0';
//按照游戏规则,如果坐标显示雷的数目不为零,则返回
if (show[x][y] != '0')
{
return;
}
//展开雷
for (int i = -1; i <= 1; i++)
{
for (int j = -1; j <= 1; j++)
{
Open_keyboard(show, mine, x + i, y + j);
}
}
}
//排雷
void move_mine(char show[ROWS][COLS], char mine[ROWS][COLS], int row, int col)
{
int x, y;
while (1)
{
printf("请输入要排查的坐标:");
regain2:
scanf("%d %d", &x, &y);
if ((x >= 1 && x <= 9) && (y >= 1 && y <= 9))
{
if (show[x][y] == '*')
{
if (mine[x][y] == '0')
{
Open_keyboard(show,mine,x,y);
printf_keyboard(show, ROW, COL);
}
else
{
printf("很遗憾,踩到雷了,游戏结束\n以下是雷的位置:");
printf_keyboard(mine, ROW, COL);
break;
}
}
else
{
printf("该坐标已经排查过了,请输入别的坐标:");
goto regain2;
}
}
else
{
printf("输入错误,重新输入:");
goto regain2;
}
//判断赢
int Remove_mine_count = 0;
for (int i = 1; i <= row; i++)
{
for (int j = 1; j <= col; j++)
{
if (show[i][j] != '*')
{
Remove_mine_count++;
}
}
}
if (Remove_mine_count == ((ROW * COL) - MINE))
{
printf("恭喜你,排除所有的雷,游戏胜利\n");
printf_keyboard(mine, ROW, COL);
break;
}
}
}
game.h文件的代码不变
c
game.h
#pragma once
#include <stdio.h>
#include "game.h"
#include <time.h>
#include "stdlib.h"
#define ROW 9
#define COL 9
#define ROWS ROW+3
#define COLS COL+2
#define MINE 10
//菜单
void menu();
//初始化棋盘
void set_keyboard(char board[ROWS][COLS], int rows, int cols, char set);
//展示棋盘
void printf_keyboard(char board[ROWS][COLS], int row, int col);
//随机布置雷
void set_mine(char board[ROWS][COLS], int row, int col, int mine);
//排雷
void move_mine(char show[ROWS][COLS], char mine[ROWS][COLS], int row, int col);
五、扫雷游戏完整代码
test.c
c
#include "game.h"
void game()
{
//用于布置雷的二维数组
char mine[ROWS][COLS] = { 0 };
//用于游戏界面的的二维数组
char show[ROWS][COLS] = { 0 };
//用于游戏界面的的二维数组全部初始为 '*'
set_keyboard(show, ROWS, COLS, '*');
//用于布置雷的二维数组全部初始化为 '0'
set_keyboard(mine, ROWS, COLS, '0');
//随机布置雷
set_mine(mine, ROW, COL, MINE);
//打印函数
printf_keyboard(show, ROW, COL);
//printf_keyboard(mine, ROW, COL);
//排雷
move_mine(show, mine, ROW, COL);
}
int main()
{
menu();
{
regain1:
printf("请输入你的选择:");
int input1;
scanf("%d", &input1);
switch (input1)
{
case 1:
{
printf("进入游戏\n");
game();
break;
}
case 0:
{
printf("退出游戏\n");
break;
}
default:
{
printf("输入错误,请重新输入:");
goto regain1;
}
}
}
return 0;
}
game.c
c
#include "game.h"
//界面
void menu()
{
printf("****************\n");
printf("**** 1.Play ****\n");
printf("**** 0.Quit ****\n");
printf("****************\n");
}
//初始化棋盘
void set_keyboard(char board[ROWS][COLS], int rows, int cols, char set)
{
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
board[i][j] = set;
}
}
}
//展示棋盘
void printf_keyboard(char board[ROWS][COLS], int row, int col)
{
printf("-------扫雷--------\n");
for (int r = 0; r <= row; r++)
{
printf("%d ", r);
}
printf("\n");
for (int i = 1; i <= row; i++)
{
printf("%d ", i);
for (int j = 1; j <= col; j++)
{
printf("%c ", board[i][j]);
}
printf("\n");
}
}
//随机布置雷
void set_mine(char board[ROWS][COLS], int row, int col, int mine)
{
srand((unsigned int) time(NULL));
while (mine)
{
int x = (rand() % row) + 1;
int y = (rand() % col) + 1;
if (board[x][y] == '0');
{
board[x][y] = '1';
mine--;
}
}
}
//计算周围雷的个数
int Count_mine(char mine[ROWS][COLS], int x, int y)
{
return mine[x][y] - '0';
}
//展开棋盘----递归
void Open_keyboard(char show[ROWS][COLS], char mine[ROWS][COLS], int x, int y)
{
//写递归首先写结束条件
//越界时,返回
if ((x > (ROWS - 2)) || (x < 1) || (y > (COLS - 2)) || (y < 1))
{
return;
}
//遇到以及排过雷的坐标返回
if (show[x][y] != '*')
{
return;
}
//计算雷的个数
int count = 0;
for (int i = -1; i <= 1; i++)
{
for (int j = -1; j <= 1; j++)
{
count += Count_mine(mine, x + i, y + j);
}
}
show[x][y] = count + '0';
//按照游戏规则,如果坐标显示雷的数目不为零,则返回
if (show[x][y] != '0')
{
return;
}
//展开雷
for (int i = -1; i <= 1; i++)
{
for (int j = -1; j <= 1; j++)
{
Open_keyboard(show, mine, x + i, y + j);
}
}
}
//排雷
void move_mine(char show[ROWS][COLS], char mine[ROWS][COLS], int row, int col)
{
int x, y;
while (1)
{
printf("请输入要排查的坐标:");
regain2:
scanf("%d %d", &x, &y);
if ((x >= 1 && x <= 9) && (y >= 1 && y <= 9))
{
if (show[x][y] == '*')
{
if (mine[x][y] == '0')
{
Open_keyboard(show,mine,x,y);
printf_keyboard(show, ROW, COL);
}
else
{
printf("很遗憾,踩到雷了,游戏结束\n以下是雷的位置:");
printf_keyboard(mine, ROW, COL);
break;
}
}
else
{
printf("该坐标已经排查过了,请输入别的坐标:");
goto regain2;
}
}
else
{
printf("输入错误,重新输入:");
goto regain2;
}
//判断赢
int Remove_mine_count = 0;
for (int i = 1; i <= row; i++)
{
for (int j = 1; j <= col; j++)
{
if (show[i][j] != '*')
{
Remove_mine_count++;
}
}
}
if (Remove_mine_count == ((ROW * COL) - MINE))
{
printf("恭喜你,排除所有的雷,游戏胜利\n");
printf_keyboard(mine, ROW, COL);
break;
}
}
}
game.h
c
#pragma once
#include <stdio.h>
#include "game.h"
#include <time.h>
#include "stdlib.h"
#define ROW 9
#define COL 9
#define ROWS ROW+3
#define COLS COL+2
#define MINE 10
//菜单
void menu();
//初始化棋盘
void set_keyboard(char board[ROWS][COLS], int rows, int cols, char set);
//展示棋盘
void printf_keyboard(char board[ROWS][COLS], int row, int col);
//随机布置雷
void set_mine(char board[ROWS][COLS], int row, int col, int mine);
//排雷
void move_mine(char show[ROWS][COLS], char mine[ROWS][COLS], int row, int col);