一. 制作菜单
这个可以说是最简易的一步了
void menu()
{
printf("************************\n");
printf("*****1.play 0.exit*****\n");
printf("************************\n");
}
void testc()
{
int input=0;
do {
menu();
printf("请选择:");
scanf("%d", &input);
switch (input)
{
case 1:
printf("扫雷:\n");
break;
case 0:
printf("退出游戏,游戏结束\n");
break;
default:
printf("选择错误,请重新选择:\n");
break;
}
} while (input);
}
int main()
{
testc();
return 0;
}
这里算是大致的框架,主函数里面为了防止自己写到后面我们自己都看不懂了,就在其余函数里进行程序的开发,主函数主要进行调用。
二.创造游戏主体
(一)进行思路的整理
首先我们要有一个清晰的思路能够让我们对整个游戏进行构思,也就是所谓的结构框架。我们可以创造一个函数对此游戏进行,避免在主函数中太过杂乱,所以我们void game进行函数的调用,并且我们可以将头文件放在另一个文件中,方便我们的声明与调用。
1.游戏开始
既然我们要进行游戏,我们就要思考我们在哪里存放什么样的信息呢,这里我认为应该根据扫雷的特性,创作二维数组进行存放我们的棋盘。并且我们想要多大的方盘呢,这里我们引进我们自己制定的头文件game.h
#include<stdio.h>
#define _CRT_SECURE_NO_WARNINGS
#define row 9
#define col 9
#define rows row+2
#define cols col+2
这里我们用row与col分别代表创造的棋盘的行与列。但是我们可以进行思考我们制作的棋盘如果进行扫雷的话,我们应该怎么扫?
因此,我们在进行扫雷时,为了防止出现栈溢出 我们应该在扫雷的行与列中再加上2。
void game()
{
char mine[rows][cols] = {0};//数组每个初始化为‘0’
char show[rows][cols] = {0};//数组每个初始化为‘*’
这里我们想要两个棋盘的意思就是一个放我们的扫出来的,另一个则存放我们的初始棋盘还未进行清扫的。
2.这里将两个棋盘进行初始化
initboard(mine, rows, cols, '0');//放雷
initboard(show, rows, cols, '*');//存放排查出的雷的信息
void initboard(char arr[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++)
{
arr[i][j] = set;
}
}
}
3.布置雷区
接下来我们就应该开始布置雷区了,我们想要埋下10个雷,但是我们不想一直带着这个数一直跑,因为万一我们后面想要提升游戏难度就要变更雷数。所以同上面的行与列的数可以得出
#define mines 10
我们在头文件中定义有10个雷,以后带着mines一直跑
//布置雷(在9*9的棋盘上随机布置10个)
setmine(mine, row, col);
void setmine(char arr[rows][cols], int Row, int Col)
{
int count = mines;
while (count != 0)
{
int x = rand() % Row + 1;
int y = rand() % Col + 1;
if (arr[x][y] == '0')
{
arr[x][y] = '1';
count--;
}
}
}
4.判断棋盘
//打印棋盘
displayboard(mine, row, col);
displayboard(show, row, col);
void displayboard(char arr[rows][cols], int Row, int Col)//打印数组
{
int i = 0,j=0;
//打印列号
printf("-----扫雷游戏-----\n");
for (i = 0; i <= Col; i++)
{
printf("%2d ", i);
}
printf("\n");
for (i = 1; i <= Row; i++)
{
printf("%2d ", i);
for (j = 1; j <= Col; j++)
{
printf("%2c ", arr[i][j]);
}
printf("\n");
}
}
5.进行排查
//排查雷
finds(mine, show, row, col);
}
void finds(char mine[rows][cols], char show[rows][cols], int Row, int Col)//排查雷
{
int x = 0;
int y = 0;
int win=0;
int i = 0;
while (win < Row * Col - mines)
{
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(mine, 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 - mines)
{
printf("恭喜你,排雷成功了\n");
displayboard(mine, row, col);
}
}
补充:在这里面我们需要在输入的坐标中统计一下周围区域的雷我们在此需要有个函数进行统计工作,并返回此次坐标
static int getminecount(char mine[rows][cols], int x, int y)//不为雷后的统计
{
int i = 0,j=0,count=0;
for (i = x - 1; i <= x+1; i++)
{
for (j = y - 1; j < y + 1; j++)
{
count+=(mine[i][j] - '0');
}
}
return count;
}
结束:整体代码
(1)主体代码
#define _CRT_SECURE_NO_WARNINGS
#include"game.h"
void menu()//进行菜单
{
printf("************************\n");
printf("*****1.play 0.exit*****\n");
printf("************************\n");
}
void game()//进行游戏
{
char mine[rows][cols] = {0};//数组每个初始化为‘0’
char show[rows][cols] = {0};//数组每个初始化为‘*’
//初始化函数
initboard(mine, rows, cols, '0');//放雷
initboard(show, rows, cols, '*');//存放排查出的雷的信息
//布置雷(在9*9的棋盘上随机布置10个)
setmine(mine, row, col);
//打印棋盘
/*displayboard(mine, row, col);*/
displayboard(show, row, col);
//排查雷
finds(mine, show, row, col);
}
void testc()//菜单
{
int input=0;
srand((unsigned int)time(NULL));
do {
menu();
printf("请选择:");
scanf("%d", &input);
switch (input)
{
case 1:
printf("扫雷:\n");
game();//在此进行开始
break;
case 0:
printf("退出游戏,游戏结束\n");
break;
default:
printf("选择错误,请重新选择:\n");
break;
}
} while (input);
}
int main()//主函数进行带入
{
testc();
return 0;
}
(2)头文件代码
#include<stdio.h>
#define _CRT_SECURE_NO_WARNINGS
#include<time.h>
#define row 9
#define col 9
#define mines 10
#define rows row+2
#define cols col+2
//声明函数
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 finds(char mine[rows][cols],char show[rows][cols],int Row,int Col);
(3)实现代码
#define _CRT_SECURE_NO_WARNINGS
#include"game.h"
void displayboard(char arr[rows][cols], int Row, int Col)//打印数组
{
int i = 0,j=0;
//打印列号
printf("-----扫雷游戏-----\n");
for (i = 0; i <= Col; i++)
{
printf("%2d ", i);
}
printf("\n");
for (i = 1; i <= Row; i++)
{
printf("%2d ", i);
for (j = 1; j <= Col; j++)
{
printf("%2c ", arr[i][j]);
}
printf("\n");
}
}
void initboard(char arr[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++)
{
arr[i][j] = set;
}
}
}
void setmine(char arr[rows][cols], int Row, int Col)
{
int count = mines;
while (count != 0)
{
int x = rand() % Row + 1;
int y = rand() % Col + 1;
if (arr[x][y] == '0')
{
arr[x][y] = '1';
count--;
}
}
}
//static int getminecount(char mine[rows][cols], int x, int y)//统计周围雷
//{
// /*return mine[x - 1][y] + mine[x - 1][y - 1] + mine[x + 1][y] + mine[x + 1][y + 1] + mine[x][y - 1] + mine[x + 1][y - 1]
// + mine[x][y + 1] + mine[x - 1][y - 1] - 8 * '0';*/
//
//}
static int getminecount(char mine[rows][cols], int x, int y)//不为雷后的统计
{
int i = 0,j=0,count=0;
for (i = x - 1; i <= x+1; i++)
{
for (j = y - 1; j < y + 1; j++)
{
count+=(mine[i][j] - '0');
}
}
return count;
}
void finds(char mine[rows][cols], char show[rows][cols], int Row, int Col)//排查雷
{
int x = 0;
int y = 0;
int win=0;
int i = 0;
while (win < Row * Col - mines)
{
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(mine, 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 - mines)
{
printf("恭喜你,排雷成功了\n");
displayboard(mine, row, col);
}
}
当然, 现在一开玩你就发现了问题所在,咱们一排查只能排查一个位置,还是很麻烦。
(二)多区域排查
这时我们能不能一排查将那些周围连带着没有雷的大面积区域都排查出来呢?
当然有,但是该怎么做呢?
这时我们试着做一下,当然,我们每次进行排查都应该从输入的坐标进行递进到下一个坐标继续排查,相当于一个递归函数,哦吼,要用递归函数咯。
下面我们看一看函数的实现
//输出空白位置
void putelse(char mine[rows][cols], char show[rows][cols], int x, int y)
{
int count = 0;
if (mine[x][y] == '*')
return;
if (x == 0 || x == rows - 1 || y == 0 || y == cols - 1)//边界
return;
if (getminecount(mine, x, y) == 0)//判断周围
{
show[x][y] = '0';
if (show[x - 1][y - 1] == '*')
putelse(mine, show, x - 1, y - 1 );//每次传进此次坐标进行该坐标周围判断
if (show[x - 1][y] == '*')
putelse(mine, show, x - 1, y);
if (show[x - 1][y + 1] == '*')
putelse(mine, show, x - 1, y + 1);
if (show[x][y - 1] == '*')
putelse(mine, show, x, y - 1);
if (show[x][y + 1] == '*')
putelse(mine, show, x, y + 1);
if (show[x + 1][y - 1] == '*')
putelse(mine, show, x + 1, y - 1);
if (show[x + 1][y] == '*')
putelse(mine, show, x + 1, y);
if (show[x + 1][y + 1] == '*')
putelse(mine, show, x + 1, y + 1);
}
else if (getminecount(mine, x, y) > 0)//该坐标不为空
{
show[x][y] = '0' + getminecount(mine, x, y);//因为是字符,但是字符连续
return count;
}
}
小伙子,知道你要回头看。
static int getminecount(char mine[rows][cols], int x, int y)//不为雷后的统计
{
int i = 0,j=0,count=0;
for (i = x - 1; i <= x+1; i++)
{
for (j = y - 1; j < y + 1; j++)
{
count+=(mine[i][j] - '0');
}
}
return count;
}
噢,完成了喔。
最终:改后
(1)主体代码
#define _CRT_SECURE_NO_WARNINGS
#include"game.h"
void menu()//进行菜单
{
printf("************************\n");
printf("*****1.play 0.exit*****\n");
printf("************************\n");
}
void game()//进行游戏
{
char mine[rows][cols] = {0};//数组每个初始化为‘0’
char show[rows][cols] = {0};//数组每个初始化为‘*’
//初始化函数
initboard(mine, rows, cols, '0');//放雷
initboard(show, rows, cols, '*');//存放排查出的雷的信息
//布置雷(在9*9的棋盘上随机布置10个)
setmine(mine, row, col);
//打印棋盘
/*displayboard(mine, row, col);*/
displayboard(show, row, col);
//排查雷
finds(mine, show, row, col);
}
void testc()//菜单
{
int input=0;
srand((unsigned int)time(NULL));
do {
menu();
printf("请选择:");
scanf("%d", &input);
switch (input)
{
case 1:
printf("扫雷:\n");
game();//在此进行开始
break;
case 0:
printf("退出游戏,游戏结束\n");
break;
default:
printf("选择错误,请重新选择:\n");
break;
}
} while (input);
}
int main()//主函数进行带入
{
testc();
return 0;
}
(2)头文件代码
#include<stdio.h>
#define _CRT_SECURE_NO_WARNINGS
#include<windows.h>
#include<time.h>
#define row 9
#define col 9
#define mines 10
#define rows row+2
#define cols col+2
//声明函数
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 finds(char mine[rows][cols],char show[rows][cols],int Row,int Col);
//输出空白格
void putelse(char mine[rows][cols],char show[rows][cols], int Row, int Col);
(3)实现代码
#define _CRT_SECURE_NO_WARNINGS
#include"game.h"
void displayboard(char arr[rows][cols], int Row, int Col)//打印数组
{
int i = 0,j=0;
//打印列号
printf("-----扫雷游戏-----\n");
for (i = 0; i <= Col; i++)
{
printf("%2d ", i);
}
printf("\n");
for (i = 1; i <= Row; i++)
{
printf("%2d ", i);
for (j = 1; j <= Col; j++)
{
printf("%2c ", arr[i][j]);
}
printf("\n");
}
}
void initboard(char arr[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++)
{
arr[i][j] = set;
}
}
}
void setmine(char arr[rows][cols], int Row, int Col)
{
int count = mines;
while (count != 0)
{
int x = rand() % Row + 1;
int y = rand() % Col + 1;
if (arr[x][y] == '0')
{
arr[x][y] = '1';
count--;
}
}
}
//static int getminecount(char mine[rows][cols], int x, int y)//统计周围雷
//{
// /*return mine[x - 1][y] + mine[x - 1][y - 1] + mine[x + 1][y] + mine[x + 1][y + 1] + mine[x][y - 1] + mine[x + 1][y - 1]
// + mine[x][y + 1] + mine[x - 1][y - 1] - 8 * '0';*/
//
//}
static int getminecount(char mine[rows][cols], int x, int y)//不为雷后的统计
{
int i = 0,j=0,count=0;
for (i = x - 1; i <= x+1; i++)
{
for (j = y - 1; j < y + 1; j++)
{
count+=(mine[i][j] - '0');
}
}
return count;
}
//输出空白位置
void putelse(char mine[rows][cols], char show[rows][cols], int x, int y)
{
int count = 0;
if (mine[x][y] == '*')
return;
if (x == 0 || x == rows - 1 || y == 0 || y == cols - 1)//边界
return;
if (getminecount(mine, x, y) == 0)//周围为空
{
show[x][y] = '0';
if (show[x - 1][y - 1] == '*')
putelse(mine, show, x - 1, y - 1 );//每次传进此次坐标进行该坐标周围判断
if (show[x - 1][y] == '*')
putelse(mine, show, x - 1, y);
if (show[x - 1][y + 1] == '*')
putelse(mine, show, x - 1, y + 1);
if (show[x][y - 1] == '*')
putelse(mine, show, x, y - 1);
if (show[x][y + 1] == '*')
putelse(mine, show, x, y + 1);
if (show[x + 1][y - 1] == '*')
putelse(mine, show, x + 1, y - 1);
if (show[x + 1][y] == '*')
putelse(mine, show, x + 1, y);
if (show[x + 1][y + 1] == '*')
putelse(mine, show, x + 1, y + 1);
}
else if (getminecount(mine, x, y) > 0)//该坐标不为空
{
show[x][y] = '0' + getminecount(mine, x, y);//如果
return count;
}
}
void finds(char mine[rows][cols], char show[rows][cols], int Row, int Col)//排查雷
{
int x = 0;
int y = 0;
int win = 0;
int i = 0;
int coutt = 0;
int* p = &coutt;
while (win < Row * Col - mines)
{
printf("请输入要排查的坐标:");
scanf("%d %d", &x, &y);
//判断坐标的有效性
if (x >= 1 && x <= Row && y >= 1 && y <= Col)
{
if (mine[x][y] == '1')
{
printf("你被炸死了\n");
displayboard(mine, row, col);
break;
}
else
{
//统计坐标周围有几个雷
int count = getminecount(mine, x, y);
show[x][y] = count + '0';
if (count == 0)
{
putelse(mine, show, x, y, p);
}
system("cls");
displayboard(show, row, col);
win++;
}
}
else
{
printf("坐标非法,请重新输入\n");
}
}
if (win == Row * Col - mines)
{
printf("恭喜你,排雷成功了\n");
displayboard(mine, row, col);
}
}
这里,给各位整理一下之前的代码:
1.//初始化数组void initboard(char arr[rows][cols], int Rows, int Cols,char set);
void initboard(char arr[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++)
{
arr[i][j] = set;
}
}
}
2.//打印棋盘void displayboard(char arr[rows][cols], int Row, int Col);
void displayboard(char arr[rows][cols], int Row, int Col)//打印数组
{
int i = 0,j=0;
//打印列号
printf("-----扫雷游戏-----\n");
for (i = 0; i <= Col; i++)
{
printf("%2d ", i);
}
printf("\n");
for (i = 1; i <= Row; i++)
{
printf("%2d ", i);
for (j = 1; j <= Col; j++)
{
printf("%2c ", arr[i][j]);
}
printf("\n");
}
}
3.//布置雷void setmine(char arr[rows][cols], int Row, int Col);
void setmine(char arr[rows][cols], int Row, int Col)
{
int count = mines;
while (count != 0)
{
int x = rand() % Row + 1;
int y = rand() % Col + 1;
if (arr[x][y] == '0')
{
arr[x][y] = '1';
count--;
}
}
}
4.//排查雷void finds(char mine[rows][cols],char show[rows][cols],int Row,int Col);
void finds(char mine[rows][cols], char show[rows][cols], int Row, int Col)//排查雷
{
int x = 0;
int y = 0;
int win = 0;
int i = 0;
int coutt = 0;
int* p = &coutt;
while (win < Row * Col - mines)
{
printf("请输入要排查的坐标:");
scanf("%d %d", &x, &y);
//判断坐标的有效性
if (x >= 1 && x <= Row && y >= 1 && y <= Col)
{
if (mine[x][y] == '1')
{
printf("你被炸死了\n");
displayboard(mine, row, col);
break;
}
else
{
//统计坐标周围有几个雷
int count = getminecount(mine, x, y);
show[x][y] = count + '0';
if (count == 0)
{
putelse(mine, show, x, y, p);
}
system("cls");
displayboard(show, row, col);
win++;
}
}
else
{
printf("坐标非法,请重新输入\n");
}
}
if (win == Row * Col - mines)
{
printf("恭喜你,排雷成功了\n");
displayboard(mine, row, col);
}
}
5.//输出空白格void putelse(char mine[rows][cols],char show[rows][cols], int Row, int Col);
void putelse(char mine[rows][cols], char show[rows][cols], int x, int y)
{
int count = 0;
if (mine[x][y] == '*')
return;
if (x == 0 || x == rows - 1 || y == 0 || y == cols - 1)//边界
return;
if (getminecount(mine, x, y) == 0)//周围为空
{
show[x][y] = '0';
if (show[x - 1][y - 1] == '*')
putelse(mine, show, x - 1, y - 1 );//每次传进此次坐标进行该坐标周围判断
if (show[x - 1][y] == '*')
putelse(mine, show, x - 1, y);
if (show[x - 1][y + 1] == '*')
putelse(mine, show, x - 1, y + 1);
if (show[x][y - 1] == '*')
putelse(mine, show, x, y - 1);
if (show[x][y + 1] == '*')
putelse(mine, show, x, y + 1);
if (show[x + 1][y - 1] == '*')
putelse(mine, show, x + 1, y - 1);
if (show[x + 1][y] == '*')
putelse(mine, show, x + 1, y);
if (show[x + 1][y + 1] == '*')
putelse(mine, show, x + 1, y + 1);
}
else if (getminecount(mine, x, y) > 0)//该坐标不为空
{
show[x][y] = '0' + getminecount(mine, x, y);//如果
return count;
}
}
6.//不为雷后的统计static int getminecount(char mine[rows][cols], int x, int y)
static int getminecount(char mine[rows][cols], int x, int y)//不为雷后的统计
{
int i = 0,j=0,count=0;
for (i = x - 1; i <= x+1; i++)
{
for (j = y - 1; j < y + 1; j++)
{
count+=(mine[i][j] - '0');
}
}
return count;
}
好,终于结束了。