利用循环与数组的知识,可以初步实现扫雷游戏的编写。
利用控制台的功能,可以用自己写出的代码玩扫雷游戏啦!!!
整个代码将由多个函数嵌套而成,因此我们在同一个项目中建设三个文件,来用于存放函数的头文件,函数运行和主函数。
先确定整体思路:
创建雷区——初始化雷区(随机生成雷)——打印雷区——进行扫雷——反馈结果并显示周围雷数——打印雷区——直到雷全部扫完,游戏结束。
首先,我们创建两个二维数组。(InitBoard,Print)
一个用来存放雷区状况,一个用来存放每一格周围有多少颗雷的情况,详情如下
左边为show数组,右边为mine数组。
用’*‘符号初始化mine数组,’*‘地区意为未扫雷地带。打印出雷区和每一格的横纵坐标。
void InitBoard(char arr[100][100],int row,int col,char set)//初始化数组
{
int j;
int i;
for (i = 0; i <= row+1; i++)
{
for (j = 0; j <= col+1; j++)
{
arr[i][j] = set;
}
}
}
void print(char arr[100][100], int row,int col)
{
int i,j,m;
for (m = 0; m <= col; m++)
{
printf("%2d ", m);
}
printf("\n");
for (i = 1; i <=row; i++)
{
printf("%2d ", i);
for (j = 1; j <= col; j++)
{
printf("%c ", arr[i][j]);
}
printf("\n");
}
}
ps.将雷区从mine[1][1]开始设置,是为了防止检查周围雷数时数组越界。比如想要初始化9*9的雷区,就需要初始化11*11的二维数组,如上方图1,2所示。
打印9*9以上的雷区时,会出现坐标与‘*’对不齐的情况,可以参照以上代码,用"%2d"进行向右对齐。
现在开始布雷(Creat)
num为想要布置的雷数,用’1‘字符来表示雷。
利用
srand((unsigned int)time(NULL));
int x = rand() % row + 1;
int y = rand() % col + 1;
生成随机坐标,将其放进循环之中,通过if语句判断该坐标是否有雷,有则进入下一次循环,无则布雷并且使count变量减一,count为需设雷数,当其为零时,循环结束,布雷完成。详情如下:
void creat(char arr[100][100], int row, int col,int num)
{
srand((unsigned int)time(NULL));
int count = num;
while (count)
{
int x = rand() % row + 1;
int y = rand() % col + 1;
if (arr[x][y] == '*')
{
arr[x][y] = '1';
count--;
}
}
}
最后进入扫雷环节(Find)
ps.可以将mine和show一起打印出来,看着答案扫雷以检验项目是否正确。具体流程如下:
InitBoard(mine, row, col, '*');
InitBoard(show, row, col, '*');
creat(mine, row, col, num);
print(show, row, col);
print(mine, row, col);
但是最后记得把打印mine的部分给注释掉,不然你的扫雷游戏就会自动泄题啦。
玩家通过向控制台中输入坐标进行扫雷,程序判断mine数组中对应下标的字符是否为’1‘。
如果为’1‘,则输出“你被炸死啦”并返回0。
若为’*‘,则调用另一个函数,该函数会对该坐标周围一圈进行查看,最终返回以该坐标为中心的3*3方格中有几个’1‘,即周围雷数,并将其值num返回。Find函数会将num这一返回值赋予show数组中对应坐标并返回1。
若不为’1‘或’*‘,则说明玩家输入的数组越界,输出"格式错误,请重新填写“并返回2。
int Find(char arr[100][100],char ch[100][100], int row, int col)
{
int x, y;
scanf("%d,%d", &x, &y);
if (arr[x][y] == '1')
{
printf("你被炸死了\n");
return 0;
}
else if (arr[x][y] == '*')
{
ch[x][y] =Jud(arr,x,y)+'0';
return 1;
}
else
printf("格式错误,请重新填写:\n");
return 2;
}
上述用于查找周围雷数的函数为Jud,向其中传入用户输入的坐标(x,y),他会对(x-1,y-1)(x-1,y)(x-1,y+1)(x,y-1)(x,y)(x,y+1)(x+1,y-1)(x+1,y)(x+1,y+1)这九个坐标进行检查,统计其中的雷数并将其返回。具体如下
int Jud(char arr[100][100], int x, int y)
{
int i, m, n,num=0;
for (i = y - 1; i <= y + 1; i++)
{
if (arr[x - 1][i] == '1')
{
num++;
}
}
for (m = y-1; m <= y + 1; m++)
{
if (arr[x][m] == '1')
{
num++;
}
}
for (n = y - 1; n <= y + 1; n++)
{
if (arr[x+1][n] == '1')
{
num++;
}
}
return num;
}
利用以上的五个函数,我们就可以实现一个扫雷游戏的函数game。
只需要按照前面所说的“创建雷区——初始化雷区(随机生成雷)——打印雷区——进行扫雷——反馈结果并显示周围雷数——打印雷区——直到雷全部扫完,游戏结束”的顺序调用函数即可。
由于扫雷需要多次操作和判断,我们将Find函数放进while循环之中,以其返回值来决定是否继续循环。
定义一个count来计算循环次数,当循环进行的次数等于非雷坐标数时,输出"恭喜你,扫雷成功!!!”并使循环结束(break)。
完整的game函数如下:
void game(int t)
{
int count = 0;
int i,j;
char show[100][100] = { '0'};
char mine[100][100] = { '0'};
int row=0,col=0,num=0;
if (t == 1)
{
row = 3;
col = 3;
num = 2;
}
else if (t == 2)
{
row = 9;
col = 9;
num = 10;
}
else if (t == 3)
{
row = 16;
col = 16;
num = 40;
}
InitBoard(mine, row, col, '*');
InitBoard(show, row, col, '*');
Creat(mine, row, col, num);
Print(show, row, col);
/*Print(mine, row, col);*/
//print(show, row, col);
printf("请输入扫雷坐标:");
while (Find(mine,show, row, col))
{
Print(show, row, col);
count++;
if (count == row * col - num)
{
printf("恭喜你,扫雷成功!!!\n");
break;
}
printf("请输入扫雷坐标:");
}
}
如此,扫雷游戏的编写就已经接近尾声了,我们可以再做一些修缮,为其增添一点游戏的仪式感。
int menu()
{
int t;
Sleep(1000);
printf("****************************************\n");
Sleep(1000);
printf("****************************************\n");
Sleep(1000);
printf("****************************************\n");
Sleep(1000);
printf("****************游戏开始****************\n");
Sleep(1000);
printf("****************************************\n");
Sleep(1000);
printf("****************************************\n");
Sleep(1000);
printf("****************************************\n");
printf("请选择你想要的难度:\n");
printf("1.简单:3*3,雷*2\n");
printf("2.普通:9*9,雷*10\n");
printf("3.困难:16*16,雷*40\n");
scanf("%d", &t);
return t;
}
加入菜单函数,利用闪烁打印游戏开始菜单(具体可以参照前面“猜数游戏”那篇文章),并让玩家自由选择不同的游戏难度,通过返回值的形式,与game函数嵌套在一起。
int main()
{
int t;
int w = 1;
while (w)
{
game(menu());
printf("输入'0'退出游戏,输入'1'继续游戏:\n");
scanf("%d", &w);
}
return 0;
}
主函数中,将整个game和menu函数放入循环之中,通过循环末尾对变量w的改变,给玩家提供终止游戏和继续玩两个选项,互动性杠杠滴。
最后,三个文件的代码都放这了,希望大家耐心看,耐心理解,我们一同进步!
game.h
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
void InitBoard(char arr[100][100], int row, int col,char set);//初始化数组
void Print(char arr[100][100], int row,int col);
void Creat(char arr[100][100], int row, int col,int num);
int Jud(char arr[100][100], int x, int y);
int Find(char arr[100][100], char ch[100][100], int row, int col);
game.c
#include"game.h"
void InitBoard(char arr[100][100],int row,int col,char set)//初始化数组
{
int j;
int i;
for (i = 0; i <= row+1; i++)
{
for (j = 0; j <= col+1; j++)
{
arr[i][j] = set;
}
}
}
void Print(char arr[100][100], int row,int col)
{
int i,j,m;
for (m = 0; m <= col; m++)
{
printf("%2d ", m);
}
printf("\n");
for (i = 1; i <=row; i++)
{
printf("%2d ", i);
for (j = 1; j <= col; j++)
{
printf("%c ", arr[i][j]);
}
printf("\n");
}
}
void Creat(char arr[100][100], int row, int col,int num)
{
srand((unsigned int)time(NULL));
int count = num;
while (count)
{
int x = rand() % row + 1;
int y = rand() % col + 1;
if (arr[x][y] == '*')
{
arr[x][y] = '1';
count--;
}
}
}
int Jud(char arr[100][100], int x,int y)
{
int i, m, n,num=0;
for (i = y - 1; i <= y + 1; i++)
{
if (arr[x - 1][i] == '1')
{
num++;
}
}
for (m = y-1; m <= y + 1; m++)
{
if (arr[x][m] == '1')
{
num++;
}
}
for (n = y - 1; n <= y + 1; n++)
{
if (arr[x+1][n] == '1')
{
num++;
}
}
return num;
}
int Find(char arr[100][100],char ch[100][100], int row, int col)
{
int x, y;
scanf("%d,%d", &x, &y);
if (arr[x][y] == '1')
{
printf("你被炸死了\n");
return 0;
}
else if (arr[x][y] == '*')
{
ch[x][y] =Jud(arr,x,y)+'0';
return 1;
}
else
printf("格式错误,请重新填写:\n");
return 2;
}
test.c
#include"game.h"
void game(int t)
{
int count = 0;
int i,j;
char show[100][100] = { '0'};
char mine[100][100] = { '0'};
int row=0,col=0,num=0;
if (t == 1)
{
row = 3;
col = 3;
num = 2;
}
else if (t == 2)
{
row = 9;
col = 9;
num = 10;
}
else if (t == 3)
{
row = 16;
col = 16;
num = 40;
}
InitBoard(mine, row, col, '*');
InitBoard(show, row, col, '*');
Creat(mine, row, col, num);
Print(show, row, col);
/*Print(mine, row, col);*/
//print(show, row, col);
printf("请输入扫雷坐标:");
while (Find(mine,show, row, col))
{
Print(show, row, col);
count++;
if (count == row * col - num)
{
printf("恭喜你,扫雷成功!!!\n");
break;
}
printf("请输入扫雷坐标:");
}
}
int menu()
{
int t;
Sleep(1000);
printf("****************************************\n");
Sleep(1000);
printf("****************************************\n");
Sleep(1000);
printf("****************************************\n");
Sleep(1000);
printf("****************游戏开始****************\n");
Sleep(1000);
printf("****************************************\n");
Sleep(1000);
printf("****************************************\n");
Sleep(1000);
printf("****************************************\n");
printf("请选择你想要的难度:\n");
printf("1.简单:3*3,雷*2\n");
printf("2.普通:9*9,雷*10\n");
printf("3.困难:16*16,雷*40\n");
scanf("%d", &t);
return t;
}
int main()
{
int t;
int w = 1;
while (w)
{
game(menu());
printf("输入'0'退出游戏,输入'1'继续游戏:\n");
scanf("%d", &w);
}
return 0;
}