这个小项目源自两个月前学数组的时候,由于觉得比较重要,想记录一下。
首先,大概的思路是要做出两个二维数组充当棋盘,一个用于后台储存雷的情况,一个用于打印给玩家玩游戏
那么第一步我们知道,需要声明两个二维数组,一个打印出来给用户看,一个自己深埋在心里。
第二步应该是要埋雷,这里我们可以定义几个数值去让玩家选择埋雷的数量。
第三步也就是最难的扫雷部分了,我的思路是,首先玩家先输入一个坐标,我们再对玩家输入的坐标找到对应藏雷的数组,若此坐标就是雷,则反馈玩家游戏结束,若不是雷,则计算周围九宫格的雷数,并以数字的形式反馈给玩家。
第四步是最后一步,我们要在玩家输入坐标并得到反馈之后判断雷的数量是否为0,如果是则游戏结束,不是则继续,显然,第三第四步是在一个循环里面的。
下面是整个游戏的流程图
下面开始代码实现
我们先写出一个主函数
int main(void)
{
test();
return 0;
}
我们在test()函数中实现所有的游戏
首先写出游戏主体
游戏主体
void test()
{
int input = 0;
srand((unsigned)time(NULL));
do
{
menu();//打印菜单
scanf("%d", &input);//让用户输入
switch (input)
{
case 1:
printf("游戏开始\n");
game();//玩游戏
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("输入非法,请重新输入:>\n");
break;
}
} while (input);
}
设计菜单
void menu()
{
printf("******************************************************\n");
printf("**************** 1.进入游戏 ****************\n");
printf("**************** 0.退出游戏 ****************\n");
printf("******************************************************\n");
}
我们把game函数暂时注释后打印菜单检查
接着进行下一步操作–制作游戏主体
游戏主体
自己定义头文件game.h,并在其中引用头文件
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
我想做一个10*10大小的棋盘,但是考虑到后面查找雷数量需要遍历9宫格,如果遍历到边界处则特别麻烦,所以我们不妨把数组行列设置为11 * 11。这样设置以后,布置雷的时候只要用到10 * 10的数组,外边一圈不布置,就很巧妙的避开了上述问题。
#define ROWS 11
#define COLS 11
接下来开始写game()函数
void game()
{
//创建棋盘并初始化
char mine[ROWS][COLS] = {0};
char show[ROWS][COLS] = {0};
//0代表不是雷
//mine数组是后天储存雷用的
//show数组是打印出来给玩家看的
}
接着分别初始化两个数组
//创建棋盘
char mine[ROWS][COLS] = {0};
char show[ROWS][COLS] = {0};
//初始化棋盘
initBoard(mine, ROWS, COLS, '0');
initBoard(show, ROWS, COLS, '*');
定义初始化数组的函数
void initBoard(char board[ROWS][COLS], int rows, int cols, char set)
{
int i;
int j;
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
board[i][j] = set;
}
}
}
接下来打印棋盘给玩家看
void game()
{ //1.布置好的雷的信息
char mine[ROWS][COLS] = {0};
//2.排查出雷的信息
char show[ROWS][COLS] = {0};
//初始化
initBoard(mine, ROWS, COLS, '0');
initBoard(show, ROWS, COLS, '*');
//打印棋盘
printBoard(show, ROW, COL);
}
之前说了最后一圈数组是不给玩家看的,所以再加入宏定义
#define ROW ROWS - 2
#define COL COLS - 2
打印棋盘函数设置
void printBoard(char board[ROWS][COLS], int row, int col)
{
int i, j;
int cnt = 0;
//打印列号
printf(" ");
for (i = 1; 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]);
cnt++;
if (cnt % 9 == 0)
{
printf("\n");
cnt = 0;
}
}
}
}
接下来布置雷
void game()
{ //1.布置好的雷的信息
char mine[ROWS][COLS] = {0};
//2.排查出雷的信息
char show[ROWS][COLS] = {0};
//初始化
initBoard(mine, ROWS, COLS, '0');
initBoard(show, ROWS, COLS, '*');
//打印棋盘
printBoard(show, ROW, COL);
//布置雷
putMine(mine, ROW, COL);
}
布置雷函数设置
void putMine(char board[ROWS][COLS], int row, int col)
{
int cnt = modeChoose();//在此加入模式选择
while (cnt > 0)
{
int x;
int y;
while (1)
{
//置入随机坐标
x = rand() % row + 1;
y = rand() % col + 1;
if (board[x][y] == '0')
{
board[x][y] = '1';
cnt--;
break;
}
}
}
}
设置模式选择函数
首先定义不同难度所放置的雷数
#define EASY_COUNT 10
#define PRIME_COUNT 20
#define HARD_COUNT 50
接下来做modeChoose()函数
int modeChoose(void)
{
printf("**************** 1.简单难度 ****************\n");
printf("**************** 2.普通难度 ****************\n");
printf("**************** 3.困难难度 ****************\n");
printf("请输入你想要玩的难度:>");
int mode;
int n;
do
{
scanf("%d", &mode);
switch (mode)
{
case 1:
n = EASY_COUNT;
break;
case 2:
n = PRIME_COUNT;
break;
case 3:
n = HARD_COUNT;
break;
default:
printf("输入非法,请重新输入:>\n");
break;
}
} while (mode != 1 && mode != 2 && mode != 3);
return n;
}
类比菜单,让用户选择
做完这些以后,就开始扫雷了
扫雷
void game()
{
//创建棋盘
char mine[ROWS][COLS] = {0};
char show[ROWS][COLS] = {0};
//初始化棋盘
initBoard(mine, ROWS, COLS, '0');
initBoard(show, ROWS, COLS, '*');
//布置雷
putMine(mine ,ROW,COL);
//打印棋盘
printBoard(show,ROW,COL);
//扫雷
findMine(mine,show,ROWS,COLS);
}
扫雷函数设置
void findMine(char mine[ROWS][COLS], char show[ROWS][COLS], int rows, int cols)
{
printf("请输入你要排查雷的坐标(示例:2 5):>");
int x, y;
}
首先提示玩家输入坐标,然后在循环里读入这个坐标
void findMine(char mine[ROWS][COLS], char show[ROWS][COLS], int rows, int cols)
{
printf("请输入你要排查雷的坐标(示例:2 5):>");
int x, y;
//判断x,y周围在mine数组周围有几个雷,并将此数目传给show
while (1)
{
scanf("%d %d", &x, &y);
}
}
首先判断输入坐标是否超出数组范围,是的话提醒用户重新输入,不是的话进行下一步处理。
接下来分情况考虑,首先判断读入的坐标在数组中是不是雷(用1表示雷),是的话游戏结束,不是的话进行下一步处理
void findMine(char mine[ROWS][COLS], char show[ROWS][COLS], int rows, int cols)
{
printf("请输入你要排查雷的坐标(示例:2 5):>");
int x, y;
//判断x,y周围在mine数组周围有几个雷,并将此数目传给show
while (1)
{
scanf("%d %d", &x, &y);
while (1)
{
if (x < 1 || x > 9 || y < 1 || y > 9)
{
printf("输入坐标非法,请重新输入!:>\n");
break;
}
else
{
break;
}
}
if (mine[x][y] == '1')
{
printf("很遗憾,你被炸死了!\n");
printBoard(mine, ROW, COL);//游戏结束了就可以打印后台棋盘给玩家看了
break;
}
else
{
//下一步处理
}
}
}
现在我们需要确定,踩下坐标不为雷的情况。
若不为0,我们通过递归去判断这个坐标周围为0的情况,把为0的情况自动去除后再打印给玩家看,去除雷的坐标用空格打印。
这样分析下来,我们需要再封装一个函数
void findMine(char mine[ROWS][COLS], char show[ROWS][COLS], int rows, int cols)
{
printf("请输入你要排查雷的坐标(示例:2 5):>");
int x, y;
//判断x,y周围在mine数组周围有几个雷,并将此数目传给show
while (1)
{
scanf("%d %d", &x, &y);
while (1)
{
if (x < 1 || x > 9 || y < 1 || y > 9)
{
printf("输入坐标非法,请重新输入!:>\n");
break;
}
else
{
break;
}
}
if (mine[x][y] == '1')
{
printf("很遗憾,你被炸死了!\n");
printBoard(mine, ROW, COL);
break;
}
else
{
findZero(mine, show, x, y);
}
}
}
findzero函数实现
void findZero(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
{
if (mineCount(mine, x, y) == '0')//若雷的数量为0
{
show[x][y] = ' ';
if (show[x - 1][y] == '*')
{
findZero(mine, show, x - 1, y);
}
if (show[x][y - 1] == '*')
{
findZero(mine, show, x, y - 1);
}
if (show[x][y + 1] == '*')
{
findZero(mine, show, x, y + 1);
}
if (show[x + 1][y] == '*')
{
findZero(mine, show, x + 1, y);
}
}
else
{
char count = mineCount(mine, x, y);
show[x][y] = count;
}
}
其中mineCount函数定义如下
char mineCount(char board[ROWS][COLS], int x, int y)
{
//遍历从x-1,y-1到x+1,y+1的雷数并返回
int i, j;
char cnt = '0';
for (i = x - 1; i <= (x + 1); i++)
{
for (j = y - 1; j <= (y + 1); j++)
{
if (board[i][j] == '1')
{
cnt = cnt + 1;
}
}
}
return cnt;
}
记得每次操作完要打印数组给玩家看,这之后再写一段判断游戏是否结束的代码就大功告成了qwq。
void findMine(char mine[ROWS][COLS], char show[ROWS][COLS], int rows, int cols)
{
printf("请输入你要排查雷的坐标(示例:2 5):>");
int x, y;
//判断x,y周围在mine数组周围有几个雷,并将此数目传给show
while (1)
{
scanf("%d %d", &x, &y);
while (1)
{
if (x < 1 || x > 9 || y < 1 || y > 9)
{
printf("输入坐标非法,请重新输入!:>\n");
break;
}
else
{
break;
}
}
if (mine[x][y] == '1')
{
printf("很遗憾,你被炸死了!\n");
printBoard(mine, ROW, COL);
break;
}
else
{
findZero(mine, show, x, y);
printBoard(show, ROW, COL);
int i, j;
int cnt = 0; //判断扫雷是否全部完成
for (i = 1; i <= ROW; i++)
{
for (j = 1; j <= COL; j++)
{
if (show[i][j] == '*')
{
cnt++;
}
}
}
if (cnt == 0)
{
printf("恭喜你通关游戏!\n");
break;
}
else
{
printf("请输入你要排查雷的坐标(示例:2 5):>\n");
}
}
}
}
总代码如下
总代码
test.c
#include "game.h"
void menu()
{
printf("******************************************************\n");
printf("**************** 1.进入游戏 ****************\n");
printf("**************** 0.退出游戏 ****************\n");
printf("******************************************************\n");
}
void game()
{
//创建棋盘
char mine[ROWS][COLS] = {0};
char show[ROWS][COLS] = {0};
//初始化棋盘
initBoard(mine, ROWS, COLS, '0');
initBoard(show, ROWS, COLS, '*');
//布置雷
putMine(mine ,ROW,COL);
//打印棋盘
printBoard(show,ROW,COL);
//扫雷
findMine(mine,show,ROWS,COLS);
}
void test()
{
int input = 0;
srand((unsigned)time(NULL));
do
{
menu();
scanf("%d", &input);
switch (input)
{
case 1:
printf("游戏开始\n");
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("输入非法,请重新输入:>\n");
break;
}
} while (input);
}
int main(void)
{
test();
return 0;
}
头文件game.h
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define ROWS 11
#define COLS 11
#define ROW ROWS - 2
#define COL COLS - 2
#define EASY_COUNT 10
#define PRIME_COUNT 20
#define HARD_COUNT 50
void initBoard(char board[ROWS][COLS], int row, int col, char ch);
void printBoard(char show[ROWS][COLS], int row, int col);
void putMine(char board[ROWS][COLS], int row, int col);
void findMine(char mine[ROWS][COLS], char show[ROWS][COLS], int rows, int cols);
game.c
#include "game.h"
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 printBoard(char board[ROWS][COLS], int row, int col)
{
int i;
int j;
int flag = 0;
printf(" ");
for (i = 1; i <= row; 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]);
flag++;
}
if (flag % 9 == 0)
{
printf("\n");
flag = 0;
}
}
}
int modeChoose(void)
{
printf("**************** 1.简单难度 ****************\n");
printf("**************** 2.普通难度 ****************\n");
printf("**************** 3.困难难度 ****************\n");
printf("请输入你想要玩的难度:>");
int mode;
int n;
do
{
scanf("%d", &mode);
switch (mode)
{
case 1:
n = EASY_COUNT;
break;
case 2:
n = PRIME_COUNT;
break;
case 3:
n = HARD_COUNT;
break;
default:
printf("输入非法,请重新输入:>\n");
break;
}
} while (mode != 1 && mode != 2 && mode != 3);
return n;
}
void putMine(char board[ROWS][COLS], int row, int col)
{
int cnt = modeChoose();//再此加入模式选择
while (cnt > 0)
{
int x;
int y;
while (1)
{
//置入随机坐标
x = rand() % row + 1;
y = rand() % col + 1;
if (board[x][y] == '0')
{
board[x][y] = '1';
cnt--;
break;
}
}
}
}
char mineCount(char board[ROWS][COLS], int x, int y)
{
//遍历从x-1,y-1到x+1,y+1的雷数并返回
int i, j;
char cnt = '0';
for (i = x - 1; i <= (x + 1); i++)
{
for (j = y - 1; j <= (y + 1); j++)
{
if (board[i][j] == '1')
{
cnt = cnt + 1;
}
}
}
return cnt;
}
void findZero(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
{
if (mineCount(mine, x, y) == '0')//若雷的数量为0
{
show[x][y] = ' ';
if (show[x - 1][y] == '*')
{
findZero(mine, show, x - 1, y);
}
if (show[x][y - 1] == '*')
{
findZero(mine, show, x, y - 1);
}
if (show[x][y + 1] == '*')
{
findZero(mine, show, x, y + 1);
}
if (show[x + 1][y] == '*')
{
findZero(mine, show, x + 1, y);
}
}
else
{
char count = mineCount(mine, x, y);
show[x][y] = count;
}
}
void findMine(char mine[ROWS][COLS], char show[ROWS][COLS], int rows, int cols)
{
printf("请输入你要排查雷的坐标(示例:2 5):>");
int x, y;
//判断x,y周围在mine数组周围有几个雷,并将此数目传给show
while (1)
{
scanf("%d %d", &x, &y);
while (1)
{
if (x < 1 || x > 9 || y < 1 || y > 9)
{
printf("输入坐标非法,请重新输入!:>\n");
break;
}
else
{
break;
}
}
if (mine[x][y] == '1')
{
printf("很遗憾,你被炸死了!\n");
printBoard(mine, ROW, COL);
break;
}
else
{
findZero(mine, show, x, y);
printBoard(show, ROW, COL);
int i, j;
int cnt = 0; //判断扫雷是否全部完成
for (i = 1; i <= ROW; i++)
{
for (j = 1; j <= COL; j++)
{
if (show[i][j] == '*')
{
cnt++;
}
}
}
if (cnt == 0)
{
printf("恭喜你通关游戏!\n");
break;
}
else
{
printf("请输入你要排查雷的坐标(示例:2 5):>\n");
}
}
}
}