目录
1.扫雷实现的逻辑
2.游戏的实现
2.1打印菜单
2.2玩家选择
2.3游戏实现扫雷的逻辑
1.布置雷的逻辑
2.排雷的第一种情况
3.排雷的第二种情况
2.3棋盘的初始化
2.4打印棋盘
1.代码
2.打印效果
2.5布置雷
2.6排雷
2.7game()函数
3.源代码
game.h
game.c
test.c
4.总结
和我们之前的三子棋一样,扫雷的核心思想也是二维数组的利用
今天我们就来试着利用数组的知识来实现扫雷游戏
跟三子棋一样,我们首先创建三个文件:game.h , game.c , test.c
- 1.用define定义常量,定义数组的行和列,这样改变数组行列不需要整个修改代码,只需要改变define后面定义常量的值;
- 2.需要一个菜单来供我们选择进入游戏还是退出游戏,menu函数;
- 3.玩游戏肯定不止玩一局,所以需要设置循环do...while;
- 4.需要俩个数组,一个用来设置雷(mine),存放雷的信息;一个用来让玩家排查雷(show),存放玩家输入的坐标信息;
- 5.需要初始化俩个数组,我们把要埋雷的数组初始化为’0‘,要排雷的数组初始化为’*‘;
- 6.需要打印棋盘让玩家来排雷;
- 7.需要设置雷和排雷函数;
定义一个menu()函数来打印菜单
void menu() {
printf("******************\n");
printf("***** 1.play *****\n");
printf("***** 0.exit *****\n");
printf("******************\n");
}
我们在main()中采取do-while循环来实现重复游戏,用switch()来获取玩家的选择
int main() {
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);
return 0;
}
目前我们的实现效果是这样的
假设我们实现一个9*9的棋盘,上面布置十个雷
这样我们就需要一个9*9的数组来存放雷
假设这是我们的棋盘
最开始每个位置都放0;0表示非雷
当我们布置雷的时候,把雷放成1
假设我们在排这个绿色坐标的时候,它不是雷,这时候我们需要统计它周围红圈中8个坐标的雷的个数;像上面这种情况,我们需要显示1;但是这个1会与我们表示雷的1冲突,为了解决这个问题,我们再单独给他一个数组,全部放成 ‘ * ’ ;
这个时候,我们在 ‘ * ’ 棋盘中,对应的位置显示‘1’表示这个坐标周围的八个坐标里有一个雷;我们给玩家展示的时候,展示第2个数组
- 第一个棋盘存雷和非雷的信息
- 第二个棋盘存玩家排查出来的雷的信息
假设我们要排查边缘的这个坐标,这个是超出了我们9*9的数组范围
这个时候为了防止越界,我们再把这个数组扩充,即在设置存雷的数组的时候,范围设置成11*11
像这样
这个时候,就不存在越界行为了
为了便于计算,我们的展示棋盘同样扩大到11*11(严丝合缝);
我们定一个InitBoard()函数来初始化棋盘
定义两个11*11的数组
这个数组用来放布置好的雷的信息(11*11)
这个数组用来放排查出的雷的信息(11*11)
为了保证两个数组严格的统一,包括元素类型也要统一,我们定义为char数组
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
//初始化棋盘
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set)
{
int i = 0, j = 0;
for (i = 0; i < rows; i++) {
for (j = 0; j < cols; j++) {
board [i][j] = set;
}
}
}
test.c
void game() {
char mine[ROWS][COLS] = { 0 };
char show[ROWS][COLS] = { 0 };
InitBoard(mine, ROWS, COLS, '0');
InitBoard(show, ROWS, COLS, '*');
}
我们定义一个DisplayBoard()函数来打印棋盘
在打印的时候,我们可以打印出坐标
game.c
//打印棋盘
void DisplayBoard(char board[ROWS][COLS], int row, int col) {
int i = 0, j = 0;
for (i = 0; i <= col; i++) {
printf("%d ", i);
}
printf("\n");
for (i = 1; i <= row; i++) {
printf("%d ", i);
for (j = 1; j <= col; j++){
printf("%c ", board[i][j]);
}
printf("\n");
}
}
test.c
void game() {
char mine[ROWS][COLS] = { 0 };
char show[ROWS][COLS] = { 0 };
InitBoard(mine, ROWS, COLS, '0');
InitBoard(show, ROWS, COLS, '*');
DisplayBoard(mine, ROW, COL);
DisplayBoard(show, ROW, COL);
}
我们定义一个setMine()函数来布置雷
假设我要布置十个雷
- 随机布置
- 用1表示雷
这里我们又要用到我们的随机数函数rand(),使用rand函数必然需要在main()函数中调用srand();
//布置雷
void setMine(char mine[ROWS][COLS], int row, int col) {
int count = EASY_COUNT;
while (count) {
int x = rand() % row + 1;
int y = rand() % col + 1;
if (mine[x][y] == '0') {
mine[x][y] = '1';
count--;
}
}
}
排查雷的逻辑是:
- 如果这个位置不是雷,就计算这个位置周围八个坐标有几个雷,并显示雷的个数
- 如果这个位置是雷,就炸死了,游戏结束
- 如果把不是雷的位置都找出来了,那么游戏也结束,玩家胜利
在扫雷的过程中,我们还需要计算周围雷的个数
定义一个GetMineCount()函数来统计周围雷的个数
int GetMineCount(char mine[ROWS][COLS], int x, int y) {
return(mine[x - 1][y] +
mine[x - 1][y - 1] +
mine[x][y - 1] +
mine[x + 1][y - 1] +
mine[x + 1][y] +
mine[x + 1][y + 1] +
mine[x][y + 1] +
mine[x - 1][y + 1] - 8 * '0');
}
定义一个FindMine()函数来排查雷
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_COUNT) {
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");
DisplayBoard(show, ROW, COL);
break;
}
else {
int count = GetMineCount(mine, x, y);
show[x][y] = count + '0';
DisplayBoard(show, ROW, COL);
win++;
}
}
else {
printf("该坐标已经被排查了\n");
}
}
else {
printf("非法坐标,请重新输入\n");
}
}
if (win == row * col - EASY_COUNT) {
printf("恭喜你,排雷成功\n");
DisplayBoard(mine, ROW, COL);
}
}
void game() {
char mine[ROWS][COLS] = { 0 };
char show[ROWS][COLS] = { 0 };
InitBoard(mine, ROWS, COLS, '0');
InitBoard(show, ROWS, COLS, '*');
//DisplayBoard(mine, ROW, COL);
DisplayBoard(show, ROW, COL);
//布置雷
setMine(mine, ROW, COL);
//排查雷
FindMine(mine, show, ROW, COL);
}
#define _CRT_SECURE_NO_WARNINGS 1
#pragma once
#include
#include
#include
#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);
//计算扫出来的雷个数
int GetMineCount(char mine[ROWS][COLS], int x, int y);
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
//初始化棋盘
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set)
{
int i = 0, j = 0;
for (i = 0; i < rows; i++) {
for (j = 0; j < cols; j++) {
board [i][j] = set;
}
}
}
//打印棋盘
void DisplayBoard(char board[ROWS][COLS], int row, int col) {
int i = 0, j = 0;
printf("--------扫雷--------\n");
for (i = 0; i <= col; i++) {
printf("%d ", i);
}
printf("\n");
for (i = 1; i <= row; i++) {
printf("%d ", i);
for (j = 1; j <= col; j++){
printf("%c ", board[i][j]);
}
printf("\n");
}
printf("--------扫雷--------\n");
}
//布置雷
void setMine(char mine[ROWS][COLS], int row, int col) {
int count = EASY_COUNT;
while (count) {
int x = rand() % row + 1;
int y = rand() % col + 1;
if (mine[x][y] == '0') {
mine[x][y] = '1';
count--;
}
}
}
//扫雷
int GetMineCount(char mine[ROWS][COLS], int x, int y) {
return(mine[x - 1][y] +
mine[x - 1][y - 1] +
mine[x][y - 1] +
mine[x + 1][y - 1] +
mine[x + 1][y] +
mine[x + 1][y + 1] +
mine[x][y + 1] +
mine[x - 1][y + 1] - 8 * '0');
}
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_COUNT) {
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");
DisplayBoard(show, ROW, COL);
break;
}
else {
int count = GetMineCount(mine, x, y);
show[x][y] = count + '0';
DisplayBoard(show, ROW, COL);
win++;
}
}
else {
printf("该坐标已经被排查了\n");
}
}
else {
printf("非法坐标,请重新输入\n");
}
}
if (win == row * col - EASY_COUNT) {
printf("恭喜你,排雷成功\n");
DisplayBoard(mine, ROW, COL);
}
}
#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, '*');
//DisplayBoard(mine, ROW, COL);
DisplayBoard(show, ROW, COL);
//布置雷
setMine(mine, ROW, COL);
//排查雷
FindMine(mine, show, ROW, COL);
}
int main() {
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);
return 0;
}
这就是扫雷的全部过程了,希望对各位有帮助4
今天我们练习写出了扫雷游戏,这是一个不错的进步,对数组有了更多的理解
小杜跟各位小伙伴在一起成长,祝我们都能成为大牛!
//小杜的成长之路