0
点赞
收藏
分享

微信扫一扫

用C语言简单的写个扫雷吧

前言:

最近重新拾起了学习C语言的兴趣,在复习到函数递归的时候看见了扫雷这个小游戏,谨以此文纪念自己的程序修改过程。我写的时候参考了系统自带的扫雷玩法,便兴冲冲的开始写代码了,所以写的时候绕了一大圈弯路。我所使用的编程软件是cfree5,因为电脑版本是32位Windows7,实在找不到别的编译器了哈哈哈哈哈哈哈。下面直接上源码,200来行。

头文件:game.h

这也算是我第一次尝试用头文件写代码,第一次感觉写代码思路这么清晰。

#include<stdio.h>
#include<stdlib.h> //这个是清屏函数所属函数库
#include<time.h> //这个函数库有产生时间戳的函数,产生随机数用
#include<windows.h> //延迟时间函数在这里,为了好看

#define heng (20+2) //顾名思义,横着得,这个20可以随意更改代表扫雷界面的长
#define shu (20+2) //顾名思义,竖着的,这个20同样随意更改,表示宽
#define lei 20 //顾名思义,雷的数量哈哈哈哈

void denglu();//登录界面打印
void game();//游戏函数
void chushihua(char a[heng][shu]);//初始化
void dayin(char a[heng][shu]);//打印
void panduan(char b[heng][shu]);//判断雷周围的数字
void xunzhao(char a[heng][shu],char b[heng][shu],char c[heng][shu],int i,int j);
//寻找可以扩散的方块,即空白块和最边上的数字块
int dianji(char a[heng][shu],char b[heng][shu],char c[heng][shu],int i,int j);
//点击图上的方块(当然是通过写坐标)
void baozha(char a[heng][shu],char b[heng][shu]);//点到雷了,爆炸了
int shengli(char a[heng][shu],char b[heng][shu],int m);//胜利!!

源文件:game.c

这个地方能看出来我英语确实不好,函数名基本都是拼音,一目了然,绝对不会有重复函数(狗头)。

#include"game.h"

void panduan(char b[heng][shu])
{
int i,j;//记录每个方块的循环
int x,y;//记录当前方块的数字
int c=0;//记录(雷周围的)数字大小
for(i=1;i<heng-1;i++)
for(j=1;j<shu-1;j++)
if(b[i][j]!='*')
{
c=0
for(x=i-1;x<i+2;x++)
for(y=j-1;y<j+2;y++)
if(b[x][y]=='*')
c++, b[i][j]=c+48
}
}

void chushihua(char a[heng][shu])
{
int r=lei;
int i,j;
srand((unsigned int)time(NULL));//保证每次产生的雷都不一样
while(r)
{
i=rand()%(heng-2)+1;
j=rand()%(shu-2)+1;
if(a[i][j]!='*')//雷可不能放重
{
a[i][j]='*';
r--;
}
}
panduan(a);
}
void dayin(char a[heng][shu])
{
int i,j;
printf("\n \t ");
for(i=1;i<shu-1;i++)
printf(" %2d ",i);//这个2d是左对齐还是右对齐来着,忘了
for(i=1;i<heng-1;i++)//这几步主要是为了好看
{
printf("\n %2d",i);
for(j=1;j<shu-1;j++)
if(j==1)
printf(" | %c |",a[i][j]);
else
printf(" %c |",a[i][j]);
if(i<heng-2)
{
printf("\n\t|");
for(j=1;j<shu-1;j++)
printf("---|");
}
}
}

void xunzhao(char a[heng][shu],char b[heng][shu],char c[heng][shu],int i,int j)
{
int x,y;
if(i==0||j==0||i==heng-1||j==shu-1);//把最边上的都给屏蔽掉
else
for(x=i-1;x<i+2;x++)
for(y=j-1;y<j+2;y++)
if(c[x][y]==0) //每个寻找过得位置都置‘1’,防止浪费栈的空间
{
c[x][y]='1';
if(b[x][y]==0)//空白块直接展开,并且寻找下一个
{
a[x][y]='0';
xunzhao(a,b,c,x,y);
}
else if(b[x][y]>'0'&&b[x][y]<'9')//数字块记录但是不再展开
a[x][y]=b[x][y];
}
}

int dianji(char a[heng][shu],char b[heng][shu],char c[heng][shu],int i,int j)
{
if(b[i][j]=='*')
return 0;
else
{
xunzhao(a,b,c,i,j);
return 1;
}
}

void baozha(char a[heng][shu],char b[heng][shu])
{
int i,j;
for(i=0;i<heng;i++)
for(j=0;j<shu;j++)
if(b[i][j]=='*')
a[i][j]=b[i][j];
system("cls");
dayin(a);//这一步是为了展现炸弹爆炸,看起来比较厉害
}

int shengli(char a[heng][shu],char b[heng][shu],int m)
{
int i,j;
int s=0;
if(m=10)//这个指的是标记的部位等于10个的时候进行胜利判定
for(i=0;i<heng;i++)
for(j=0;j<shu;j++)
if(b[i][j]=='*'&&a[i][j]==5)//雷的位置和标记位置一样
s++;
if(s==10)
{
printf("\n\n\t\t胜利!");
return 1;
}
else
return 0;
}

扫雷.c 头文件在这

#include"game.h" 

void denglu()
{
printf("\n\n\t\t欢迎进入扫雷,请选择\n\n");
printf("\t\t1.开始游戏\n\n");
printf("\t\t2.退出游戏\n\n\t\t");
}

void game()
{
char a[heng][shu]={0},b[heng][shu]={0},c[heng][shu]={0};
int i,j,l;
int s=1,m=0;//用于判断操作行为
int g=-1;
chushihua(b);
while(g)
{
system("cls"); //每次选择完刷新页面
dayin(b);
printf("\n\n\t你可以选择一个坐标:");
scanf("%d%d",&i,&j);
printf("\n\t1 点击 \t2 标记\n\t你选择的操作是:");
while(s)
{
scanf("%d",&l);
switch(l)
{
case 1:g=dianji(a,b,c,i,j);
s=0;
break;
case 2:a[i][j]=5;//用ascii码里5这个符号主要是因为比较好看,可以换的
s=0;
m++;//标记的数目
break;
default:
printf("\n\t请重新输入操作!");
break;
}
}
s=1;
if(shengli(a,b,m)==1)
break;
if(g==0)
{
baozha(a,b);
printf("\n\t很不幸,你点到了炸弹\n\n\t游戏结束");
}
}
}

int main()
{
int a=0,b,c;
while(1)
{
denglu();
while(a!=2)
{
scanf("%d",&a);
switch(a)
{
case 1: printf("\n\t\t开启你的扫雷生涯吧!");
printf("\n\n\t本次游戏共有%d个雷,祝你玩得愉快!!",lei);
Sleep(2000);//等待两秒再刷新
system("cls");
game();
c=0;
break;
case 2:
break;
default:printf("\n\t\t输入错误,请重试\n\t\t");
break;
}
if(c==0)
break;
}
printf("\n\t1 是\t2 否");
printf("\n\t是否要重新玩一局?");
scanf("%d",&b);
system("cls");
if(b==2||a==2)
break;
}

system("cls");
printf("\n\n\t\t感谢游玩,我们下次再见!!\n\n");
return 0;
}

思路:
最开始的麻烦思路:

最开始的想法就是界面上显示多少方块就初始化多大的数组,比如10*10的方块,需要的横和竖分别为10,10。这样导致的结果就是当你去计算雷周围数字大小时,分九种情况讨论,分类就分了半个多小时,然后因为老打错改了半小时(当然最后全删掉了,啧),下面放一下代码:

void panduan(char b[heng][shu])
{
int i,j;
int x,y;
int c=0;
for(i=1;i<heng-1;i++)
for(j=1;j<shu-1;j++)
if(b[i][j]!='*')
{
c=0;
if(i==0&&j==0)
{
for(x=0;x<2;x++)
for(y=0;y<2;y++)
if(b[x][y]=='*')
c++, b[i][j]=c+48;
}
else if(i==heng-1&&j==0)
{
for(x=heng-1;x>heng-3;x--)
for(y=0;y<2;y++)
if(b[x][y]=='*')
c++, b[i][j]=c+48;
}
else if(i==0&&j==shu-1)
{
for(x=0;x<2;x++)
for(y=shu-1;y>shu-3;y--)
if(b[x][y]=='*')
c++, b[i][j]=c+48;
}
else if(i==heng-1&&j==shu-1)
{
for(x=heng-1;x<heng-3;x--)
for(y=shu-1;y<shu-3;y--)
if(b[x][y]=='*')
c++, b[i][j]=c+48;
}
else if(i==0)
{
for(x=0;x<2;x++)
for(y=j-1;y<j+2;y++)
if(b[x][y]=='*')
c++, b[i][j]=c+48;
}
else if(j==0)
{
for(x=i-1;x<i+2;x++)
for(y=0;y<2;y++)
if(b[x][y]=='*')
c++, b[i][j]=c+48;
}
else if(i==heng-1)
{
for(x=i;x>i-2;x--)
for(y=j-1;y<j+2;y++)
if(b[x][y]=='*')
c++, b[i][j]=c+48;
}
else if(j==shu-1)
{
for(x=i-1;x<i+2;x++)
for(y=shu-1;y>shu-3;y--)
if(b[x][y]=='*')
c++, b[i][j]=c+48;
}
else
{
for(x=i-1;x<i+2;x++)
for(y=j-1;y<j+2;y++)
if(b[x][y]=='*')
c++, b[i][j]=c+48;
}
}
}

这个地方分了四条边+四个角+中间九个方面,某种意义上很锻炼对C语言循环的理解。

更方便的思路:

在你的方块周围再加一层方块,所以头文件define时,heng=20+2,这个2指的就是左右各加了一层,这样好处是不用分类讨论,只要在打印的时候不打印最外层就可以了。其他具体思路都写在注释上了。

展示:

用C语言简单的写个扫雷吧_扫雷

登录界面如图

用C语言简单的写个扫雷吧_C语言_02

游戏方式如图

用C语言简单的写个扫雷吧_C语言_03

结果如图,雷太少了哈哈哈直接全出来了,踩个雷试试

用C语言简单的写个扫雷吧_函数嵌套_04



举报

相关推荐

0 条评论