用的Xcode编译器,这是一个成功的俄罗斯方块。
头文件,也不知道是不是都能用上。
#include
#include
#include
#include
全局变量。
int i,j,a[25][10];
char l;
开始游戏的一个界面。
void kaishi()
{
printf(" 俄罗斯方块-ZCY版\n 注:此游戏需将键盘调至英文\n");
printf(" 1.新游戏\n");
printf(" 2.帮助\n");
}
void bangzhu()
{
printf(",分别进行左右移动,向下移,空格可以逆时针旋转方块,当每一层的方块堆满时对方块进行消除。\n" );
printf("3.返回\n");
}
生成方块的函数,我一共录入了6种方块,每一种方块有一个数字表示,这样一来就可以通过随机函数来实现随机生成方块。我规定了方块一定会有一个“第一块方块”,即之后的主函数里面的ks,这样一来可以使得方块会从第一排生成,即一定是这个样子。
并且这个ks将在之后的旋转中起大作用
另外在生成方块的同时我还用四个变量:min,max,down和形参up来记录方块的边界(由于刚生成时up和ks重合且为1,所以我直接将up作为形参),这四个变量是判断方块是否还能移动关键。
将生成方块的数组元素赋值为1,而空格则赋值为0.
int *shengcheng(int a[][10],int up)
{
int n,m,min,max,b[6]={
1,2,3,4,5,6},c[8]={
1,2,3,4,5,6,7,8},d[6],*p,flag=0,down;
srand((int)time(NULL));
n=b[rand()%6];
m=c[rand()%8];
d[0]=n;
d[1]=m;
switch(n)
{
case 1 :
{
if(a[1][m]==0&&a[2][m]==0&&a[3][m]==0&&a[3][m+1]==0&&m<=7)
{
a[1][m]=1;
a[2][m]=1;
a[3][m]=1;
a[3][m+1]=1;
min=m;
max=m+1;
down=up+2;
break;
}
else
{
flag=1;
break;
}
}
case 2 :
{
if(a[1][m]==0&&a[1][m+1]==0&&a[2][m]==0&&a[2][m+1]==0&&m<=7)
{
a[1][m]=1;
a[1][m+1]=1;
a[2][m]=1;
a[2][m+1]=1;
min=m;
max=m+1;
down=up+1;
break;
}
else
{
flag=1;
break;
}
}
case 3 :
{
if(a[1][m]==0&&a[2][m]==0&&a[3][m]==0&&a[4][m]==0)
{
a[1][m]=1;
a[2][m]=1;
a[3][m]=1;
a[4][m]=1;
min=m;
max=m;
down=up+3;
break;
}
else
{
flag=1;
break;
}
}
case 4 :
{
if(a[1][m]==0&&a[1][m+1]==0&&a[2][m+1]==0&&a[2][m+2]==0&&m<=6)
{
a[1][m]=1;
a[1][m+1]=1;
a[2][m+1]=1;
a[2][m+2]=1;
min=m;
max=m+2;
down=up+1;
break;
}
else
{
flag=1;
break;
}
}
case 5 :
{
if(a[1][m]==0&&a[1][m+1]==0&&a[1][m+2]==0&&a[2][m+1]==0&&m<=6)
{
a[1][m]=1;
a[1][m+1]=1;
a[1][m+2]=1;
a[2][m+1]=1;
min=m;
max=m+2;
down=up+1;
break;
}
else
{
flag=1;
break;
}
}
case 6 :
{
if(a[1][m]==0&&a[1][m+1]==0&&a[2][m]==0&&a[2][m-1]==0&&m>=2&&m<=7)
{
a[1][m]=1;
a[1][m+1]=1;
a[2][m]=1;
a[2][m-1]=1;
min=m-1;
max=m+1;
down=up+1;
break;
}
else
{
flag=1;
break;
}
}
}
d[2]=min;
d[3]=max;
d[4]=down;
d[5]=flag;
p=d;
return(p);
}
界面函数比较简单,我把周围黑色的框框位子所在的数组元素赋值为2,这样一来可以防止框框和框框内的元素搞混。
void jiemian(int a[][10],int sum)
{
for(i=0,j=0;j<10;j++)
{
a[i][j]=2;
printf("⬛️ ");
}
printf(" :%d",sum);
printf("\n");
for(i=1;i<24;i++)
{
j=0;
printf("⬛️ ");
a[i][j]=2;
for(j=1;j<9;j++)
{
if(a[i][j]==0)
printf("⬜️ ");
else
printf(" ");
}
printf("⬛️ ");
a[i][j]=2;
printf("\n");
}
for(i=24,j=0;j<10;j++)
{
printf("⬛️ ");
a[i][j]=2;
}
printf("\n");
}
接下来到了旋转函数,其实旋转的原理还是蛮简单的,但是要让方块准确无误地旋转,还是要认真思考一番。我以之前的ks为旋转轴,对方块即将旋转的位置进行判断,如果没有方块就可以旋转,如果有就不能,并且考虑到方块的旋转其实是一个循环的过程,于是我就定一了一个静态局部变量l,用来记录旋转的次数,4次一循环,然后清零(但是注意不是必须到4才能清零),在旋转的过程中ks一直不变,二min,max,up,down等数据则会发生相应的变化(注意ks在刚开始生成的时候一定是1,ks相当于一个旋转中心,旋转不会改变ks的值,而移动可以改变ks的值)。
int *xuanzhuan(int a[][10],int n,int m,int min,int max,int up,int down,int ks,int v)
{
int d[7],*p;
int static l;
if(v==10)
l=0;
switch(n)
{
case 1 :
{
switch(l)
{
case 0 :
{
if(a[ks+1][m-1]==0&&a[ks+1][m+1]==0&&a[ks][m+1]==0&&m>=2)
{
a[ks][m]=0;
a[ks+2][m]=0;
a[ks+2][m+1]=0;
a[ks+1][m-1]=1;
a[ks+1][m+1]=1;
a[ks][m+1]=1;
l++;
min=min-1;
down=down-1;
goto end;
}
else
goto end;
}
case 1 :
{
if(a[ks][m-1]==0&&m>=2)
{
a[ks+1][m-1]=0;
a[ks+1][m+1]=0;
a[ks][m+1]=0;
a[ks][m-1]=1;
a[ks][m]=1;
a[ks+2][m]=1;
l++;
max=max-1;
down=down+1;
goto end;
}
else
goto end;
}
case 2 :
{
if(a[ks+1][m-1]==0&&a[ks+2][m-1]==0&&a[ks+1][m+1]==0&&m>=2)
{
a[ks][m-1]=0;
a[ks][m]=0;
a[ks+2][m]=0;
a[ks+1][m-1]=1;
a[ks+2][m-1]=1;
a[ks+1][m+1]=1;
l++;
max=max+1;
up=up+1;
goto end;
}
else
goto end;
}
case 3 :
{
if(a[ks][m]==0&&a[ks+2][m]==0&&a[ks+2][m+1]==0&&m<=7)
{
a[ks+1][m-1]=0;
a[ks+2][m-1]=0;
a[ks+1][m+1]=0;
a[ks][m]=1;
a[ks+2][m]=1;
a[ks+2][m+1]=1;
l=0;
min=min+1;
up=up-1;
goto end;
}
else
goto end;
}
}
}
case 3 :
switch(l)
{
case 0 :
{
if(a[ks+1][m-1]==0&&a[ks+1][m+1]==0&&a[ks+1][m+2]==0&&m>=2&&m<=6)
{
a[ks][m]=0;
a[ks+2][m]=0;
a[ks+3][m]=0;
a[ks+1][m-1]=1;
a[ks+1][m+1]=1;
a[ks+1][m+2]=1;
l++;
min=min-1;
max=max+2;
up=up+1;
down=down-2;
goto end;
}
else
goto end;
}
case 1 :
{
if(a[ks][m]==0&&a[ks+2][m]==0&&a[ks+3][m]==0)
{
a[ks+1][m-1]=0;
a[ks+1][m+1]=0;
a[ks+1][m+2]=0;
a[ks][m]=1;
a[ks+2][m]=1;
a[ks+3][m]=1;
l=0;
min=min+1;
max=max-2;
up=up-1;
down=down+2;
goto end;
}
else
goto end;
}
}
case 4 :
switch(l)
{
case 0 :
{
if(a[ks+1][m]==0&&a[ks+2][m]==0)
{
a[ks][m]=0;
a[ks+1][m+2]=0;
a[ks+1][m]=1;
a[ks+2][m]=1;
l++;
max=max-1;
down=down+1;
goto end;
}
else
goto end;
}
case 1 :
{
if(a[ks][m]==0&&a[ks+1][m+2]==0&&m<=6)
{
a[ks+1][m]=0;
a[ks+2][m]=0;
a[ks][m]=1;
a[ks+1][m+2]=1;
l=0;
max=max+1;
down=down-1;
goto end;
}
else
goto end;
}
}
case 5 :
switch(l)
{
case 0 :
{
if(a[ks+2][m+1]==0&&a[ks+1][m+2]==0)
{
a[ks][m]=0;
a[ks][m+2]=0;
a[ks+2][m+1]=1;
a[ks+1][m+2]=1;
l++;
min=min+1;
down=down+1;
goto end;
}
else
goto end;
}
case 1 :
{
if(a[ks+1][m]==0)
{
a[ks+2][m+1]=0;
a[ks+1][m]=1;
a[ks+1][m+2]=1;
l++;
min=min-1;
down=down-1;
goto end;
}
else
goto end;
}
case 2 :
{
if(a[ks+2][m+1]==0)
{
a[ks+1][m+2]=0;
a[ks+2][m+1]=1;
l++;
max=max-1;
down=down+1;
goto end;
}
else
goto end;
}
case 3 :
{
if(a[ks][m]==0&&a[ks][m+2]==0)
{
a[ks+1][m]=0;
a[ks+2][m+1]=0;
a[ks][m]=1;
a[ks][m+2]=1;
l=0;
max=max+1;
down=down-1;
goto end;
}
else
goto end;
}
}
case 6 :
switch(l)
{
case 0 :
{
if(a[ks+1][m+1]==0&&a[ks+2][m+1]==0)
{
a[ks][m+1]=0;
a[ks+1][m-1]=0;
a[ks+1][m+1]=1;
a[ks+2][m+1]=1;
l++;
min=min+1;
down=down+1;
goto end;
}
else
goto end;
}
case 1 :
{
if(a[ks][m+1]==0&&a[ks+1][m-1]==0&&m>=2&&m<=7)
{
a[ks+1][m+1]=0;
a[ks+2][m+1]=0;
a[ks][m+1]=1;
a[ks+1][m-1]=1;
l=0;
min=min-1;
down=down-1;
goto end;
}
else
goto end;
}
}
}
end:;
v=4;
p=d;
d[0]=min;
d[1]=max;
d[2]=up;
d[3]=down;
d[4]=ks;
d[5]=m;
d[6]=v;
return p;
}
移动函数的复杂程度和旋转差不多,在这个函数里我定义了一个flag变量,用来判断方块是否可以进行移动,我利用之前定义的min,max,up,down来判断我即将要移动的方向上是否有方块,如果有就不能移动(注意我在下移进行判断的时候,如果方块不能下移了,则将方块所在位置的元素变为3),如果没有就可以移动,在进行下,左,右移动的时候ks,min,max,up,down都要相应的改变。
int *yidong(int a[][10],int m,char l,int min,int max,int up,int down,int ks)
{
int d[7],*p,flag=1;
switch(l)
{
case 'a' :
{
for(i=up;i<=down;i++)
{
for(j=min;j<=max;j++)
if(a[i][j]==1)
{
if(a[i][j-1]==0)
goto out;
else
{
flag=0;
goto und;
}
}
out:;
}
und:;
if(flag==1)
{
for(i=up;i<=down;i++)
for(j=min;j<=max;j++)
if(a[i][j]==1)
{
a[i][j-1]=1;
a[i][j]=0;
}
min=min-1;
max=max-1;
m=m-1;
}
break;
}
case 'd' :
{
for(i=up;i<=down;i++)
{
for(j=max;j>=min;j--)
if(a[i][j]==1)
{
if(a[i][j+1]==0)
goto eut;
else
{
flag=0;
goto uud;
}
}
eut:;
}
uud:;
if(flag==1)
{
for(i=up;i<=down;i++)
for(j=max;j>=min;j--)
if(a[i][j]==1)
{
a[i][j+1]=1;
a[i][j]=0;
}
min=min+1;
max=max+1;
m=m+1;
}
break;
}
case 's' :
{
for(j=min;j<=max;j++)
{
for(i=down;i>=up;i--)
if(a[i][j]==1)
{
if(a[i+1][j]==0)
goto rud;
else
{
flag=2;
goto tud;
}
}
rud:;
}
tud:;
if(flag==1)
{
for(j=min;j<=max;j++)
for(i=down;i>=up;i--)
if(a[i][j]==1)
{
a[i+1][j]=1;
a[i][j]=0;
}
up=up+1;
down=down+1;
ks=ks+1;
}
if(flag==2)
for(j=min;j<=max;j++)
for(i=down;i>=up;i--)
if(a[i][j]==1)
a[i][j]=3;
break;
}
}
d[0]=min;
d[1]=max;
d[2]=up;
d[3]=down;
d[4]=ks;
d[5]=m;
d[6]=flag;
p=d;
return p;
}
消除函数可以进行多排同时消除。
int xiaochu(int a[][10])
{
int uup=0,y;
for(i=23;i>=2;i--)
{
for(j=1;j<=8;j++)
if(a[i][j]==0)
goto rrd;
for(j=1;j<=8;j++)
for(y=i;y>=2;y--)
{
a[y][j]=a[y-1][j];
a[y-1][j]=0;
}
uup++;
i++;
rrd:;
}
return uup;
}
结束函数没什么好说的。
int jieshu(int a[][10])
{
int flag=0;
for(i=3,j=1;j<9;j++)
{
if(a[i][j]!=0)
{
flag=1;
break;
}
}
return flag;
}
主函数。
int main()
{
int flag=1,x,*p,*u,n,m,ks,min,max,up,down,v,uup,sum=0;
system("stty -icanon");
outloop:;
kaishi();
x=getchar();
printf("\n");
if(x=='1')
{
do
{
up=ks=1;
do
{
p=shengcheng(a,up);
flag=*(p+5);
}while(flag==1);
n=*p;
m=*(p+1);
min=*(p+2);
max=*(p+3);
down=*(p+4);
v=10;
jiemian(a,sum);
do
{
printf("\n");
l=getchar();
printf("\n");
if(l==' ')
{
u=xuanzhuan(a,n,m,min,max,up,down,ks,v);
min=*u;
max=*(u+1);
up=*(u+2);
down=*(u+3);
ks=*(u+4);
m=*(u+5);
v=*(u+6);
}
else
{
u=yidong(a,m,l,min,max,up,down,ks);
min=*u;
max=*(u+1);
up=*(u+2);
down=*(u+3);
ks=*(u+4);
m=*(u+5);
flag=*(u+6);
}
jiemian(a,sum);
printf("\n");
}while(flag!=2);
uup=xiaochu(a);
if(uup!=0)
{
sum+=10*uup;
jiemian(a,sum);
printf("\n");
}
flag=jieshu(a);
}while(flag==0);
}
if(x=='2')
{
printf("\n");
bangzhu();
x=getchar();
if(x=='3')
{
printf("\n");
goto outloop;
}
}
printf("\n 游戏结束\n 得分:%d\n",sum);
return 0;
}
主函数需要全面考虑,要将函数放在合适的位置,我有三个do-while循环,第一个do-while循环是用来判断生成的方块的位置是否合适,会不会出界,up和ks在刚开始生成的时候一定等于1。
up=ks=1;
do
{
p=shengcheng(a,up);
flag=*(p+5);
}while(flag==1);
n=*p;
m=*(p+1);
min=*(p+2);
max=*(p+3);
down=*(p+4);
v=10;
jiemian(a,sum);
第二个do-while循环是用来判断方块是否还能移动。
do
{
printf("\n");
l=getchar();
printf("\n");
if(l==' ')
{
u=xuanzhuan(a,n,m,min,max,up,down,ks,v);
min=*u;
max=*(u+1);
up=*(u+2);
down=*(u+3);
ks=*(u+4);
m=*(u+5);
v=*(u+6);
}
else
{
u=yidong(a,m,l,min,max,up,down,ks);
min=*u;
max=*(u+1);
up=*(u+2);
down=*(u+3);
ks=*(u+4);
m=*(u+5);
flag=*(u+6);
}
jiemian(a,sum);
printf("\n");
}while(flag!=2);
紧接着就是统分用的,我没有编写统分函数,而是直接根据消除函数返回值进行相应的加分。
uup=xiaochu(a);
if(uup!=0)
{
sum+=10*uup;
jiemian(a,sum);
printf("\n");
}
这个俄罗斯方块零零总总大概花了我一个星期的时间,我之前一直卡在我以前的失败案例上面的,后来终于走了出来。虽然写出来了吧,但是我觉得我的这个俄罗斯方块还是太LOW了点,必须得按着‘s’键才能使方块下降,而比较高级的俄罗斯方块则是随着时间自动下降的,我上网查了一下,貌似要实现什么多线程之类的,我看不懂,所以做不出来,除此之外还是有一个老问题,我用的Xcode无法实现清屏功能,看的眼睛花。所以我把代码发到网上来,希望能得到大神的指点,万分感谢!---------大一菜鸟。