如何用C语言写俄罗斯方块程序?
#包含?& ltstdio.h & gt
#包含?& ltwindows.h & gt
#包含?& ltconio.h & gt
#包含?& lttime.h & gt
#定义?ZL?4 //坐标增量,?不要把游戏窗口拉到一边。
#定义?WID?36 ?//游戏窗口的宽度
#定义?黑?20 ?//游戏窗口的高度
int?I,j,Ta,Tb,Tc;//?Ta,Tb,Tc用于记忆和转换box变量的值。
int?a[60][60]= { 0 };?//标记游戏画面的坐标点:0,1,2分别为空、正方形、边框。
int?b[4];?//标记四个“口”框:1是,0否,类似于一个开关。
int?x,y,?水平,分数,速度;?//盒子中心的x,y坐标,游戏等级,分数,游戏速度。
int?旗帜,下一个;?//当前要操作的块类型序号,以及下一个块类型序号。
作废?gtxy(int?m,?int?n);?//下面声明了要使用的自定义函数。
作废?gflag(?);?//获取下一个块号
作废?csh(?);?//初始化接口
作废?开始(?);?//开始部分
作废?prfk?(?);?//打印框
作废?clfk(?);?//清除该框
作废?mkfk(?);?//制作一个盒子
作废?keyD(?);?//按键操作
int?ifmov(?);?//判断框是否可以移动或更改。
void clHA(?);?//清除一整行框
作废?clNEXT(?);?//清除边框外的下一个框。
int?主(?)
{?csh(?);?
?while(1)
{开始(?);?//开始部分
?while(1)
?{?prfk(?);?
睡眠(速度);?//延迟
?clfk(?);
?TB = x;Tc =标志;?//保存当前的X坐标和序列号,以备取消。
?keyD(?);?
?y++;?//框向下移动。
如果?(ifmov(?)==0)?{?y-;?prfk(?);?dlHA(?);?打破;}?//不掉线,删线,步出循环。
?}
?for(I = y-2;我& lty+2;i++){?如果?(我==ZL)?{?j = 0;?}?}?//盒子接触盒子的顶部。
如果?(j==0)?{?系统(“cls”);gtxy(10,10);Printf("游戏结束!");?getch();?打破;?}?
clNEXT(?);?//清除框外的下一个框。
}
?回归?0;
}
作废?gtxy(int?m,?int?n)?//控制光标移动
{COORD?pos?//定义变量
位置。x?=?m;?//横坐标
位置。y?=?n;//纵坐标
SetConsoleCursorPosition(GetStdHandle(STD _ OUTPUT _ HANDLE),?pos);?
}
作废?csh(?)//初始化接口
{gtxy(ZL+WID/2-5,ZL-2);?Printf(《俄罗斯方块》);?//打印游戏的名称
gtxy(ZL+WID+3,ZL+7);?printf("*******?下一个:“);?//打印菜单信息
gtxy(ZL+WID+3,ZL+13);?printf(" * * * * * * * * * * *);
gtxy(ZL+WID+3,ZL+15);?printf("Esc?:退出游戏”);
gtxy(ZL+WID+3,ZL+17);?printf(" write key:variant ");
gtxy(ZL+WID+3,ZL+19);?Printf ("space:暂停游戏");
gtxy(ZL ZL);?printf("╔”);?gtxy(ZL+WID-2,ZL);?printf("╗”);?//打印框角度
gtxy(ZL,ZL+黑);?printf("╚”);?gtxy(ZL+WID-2,ZL+黑);?printf("╝”);
a[ZL][ZL+黑]= 2;?a[ZL+WID-2][ZL+黑]= 2;?//记住是有模式的。
for(I = 2;我& ltWID-2;i+=2)?{ gtxy(ZL+我,ZL);?printf("═”);?}?//打印顶部水平框架
for(I = 2;我& ltWID-2;i+=2)?{ gtxy(ZL+我,ZL+黑);?printf("═”);?a[ZL+我][ZL+黑]= 2;?}?//下框
for(I = 1;我& lt黑;i++)?{?gtxy(ZL、ZL+I);?printf("║”);?a[ZL][ZL+I]= 2;?}?//记住左边的竖框有图案。
for(I = 1;我& lt黑;i++)?{gtxy(ZL+WID-2,ZL+我);?printf("║”);?a[ZL+WID-2][ZL+我]= 2;?}?//右框
CONSOLE_CURSOR_INFO?cursor_info={1,0}//以下是隐藏光标的设置。
SetConsoleCursorInfo(GetStdHandle(STD _ OUTPUT _ HANDLE),& ampcursor _ info);
level = 1;?得分= 0;?速度= 400;
gflag(?);?flag = next?//获取当前块号。
}
作废?gflag(?) ?//获取下一个块的序列号。
{?srand((无符号)时间(空));?下一个?=?rand()% 19+1;}
作废?开始(?)?//开始部分
{?gflag(?);?Ta =旗帜;?flag = next?//保存当前块号,临时操作下一个块号。
x = ZL+WID+6;?y = ZL+10;?prfk(?);?//给x和y赋值,打印出框外的下一个框。
flag = Ta?x = ZL+WID/2;?y = ZL-1;?//检索当前块号,并给x和y赋值。
}
作废?prfk?(?)?//打印俄罗斯方块
{?for(I = 0;我& lt4;i++)?{ b[I]= 1;?}?//数组b[4]的每个元素的值是1。
mkfk?(?);?//制作俄罗斯方块
对于(?我=?x-2;?我& lt= x+4;?i+=2?)?//打印框
{?for(j = y-2;j & lt=?y+1;j++)?{?如果(?a[i][j]==1?& amp& amp?j & gtZL?){?gtxy(i,j);?printf("□");?}?}?}
gtxy(ZL+WID+3,ZL+1);?printf("级别?:?%d”,级别);?//打印下面的菜单信息。
gtxy(ZL+WID+3,ZL+3);?printf("分数?:?%d”,得分);
gtxy(ZL+WID+3,ZL+5);?printf("速度?:?%d”,速度);
}
作废?clfk(?)?//清除俄罗斯方块
{?for(I = 0;我& lt4;i++)?{?b[I]= 0;?}?//数组b[4]的每个元素的值都是0。
mkfk?(?);?//制作俄罗斯方块
对于(?I = x-2;?我& lt= x+4;?i+=2?)?//清除该框
{?for(j = y-2;j & lt= y+1;j++){?如果(?a[i][j]==0?& amp& amp?j & gtZL?){?gtxy(i,j);?printf("?);?}?}?}
}
作废?mkfk(?)?//制作俄罗斯方块
{?a[x][?y]= b[0];?//框中心位置状态:?1-是,0-无
开关(标志)/* * * 6大类,19小类。
{?案子?1:?{?a[x][y-1]= b[1];?a[x+2][y-1]= b[2];?a[x+2][y]= b[3];?打破;?}?//田字广场
案子?2:?{?a[x-2][y]= b[1];?a[x+2][y]= b[2];?a[x+4][y]= b[3];?打破;?}?//直框:-
案子?3:?{?a[x][y-1]= b[1];?a[x][y-2]= b[2];?a[x][y+1]= b[3];?打破;?}?//线性框:?|
案子?4:?{?a[x-2][y]= b[1];?a[x+2][y]= b[2];?a[x][y+1]= b[3];?打破;?}?//T形盒
案子?5:?{?a[x][y-1]= b[1];?a[x][y+1]= b[2];?a[x-2][y]= b[3];?打破;?}?//T字顺时针转90度。
案子?6:?{?a[x][y-1]= b[1];?a[x-2][y]= b[2];?a[x+2][y]= b[3];?打破;?}?//T型正转180度
案子?7:?{?a[x][y-1]= b[1];?a[x][y+1]= b[2];?a[x+2][y]= b[3];?打破;?}?//T形依次旋转270度。
案子?8:?{?a[x][y+1]= b[1];?a[x-2][y]= b[2];?a[x+2][y+1]= b[3];?打破;?}?//Z框
案子?9:?{?a[x][y-1]= b[1];?a[x-2][y]= b[2];?a[x-2][y+1]= b[3];?打破;?}?//Z旋转90度。
案子?10:?{?a[x][y-1]= b[1];?a[x-2][y-1]= b[2];?a[x+2][y]= b[3];?打破;?}?//Z形顺时针旋转180度。
案子?11:?{?a[x][y+1]= b[1];?a[x+2][y-1]= b[2];?a[x+2][?y]= b[3];?打破;?}?//Z形向前旋转270度。
案子?12:?{?a[x][y-1]= b[1];?a[x][y+1]= b[2];?a[x-2][y-1]= b[3];?打破;?}?//7字框
案子?13:?{ a[x-2][y]= b[1];?a[x+2][y-1]= b[2];?a[x+2][y]= b[3];?打破;?}?//7字转90度。
案子?14:?{?a[x][y-1]= b[1];?a[x][y+1]= b[2];?a[x+2][y+1]= b[3];?打破;?}?//7字转180度。
案子?15:?{?a[x-2][y]= b[1];?a[x-2][y+1]= b[2];?a[x+2][y]= b[3];?打破;?}?//7字转270度。
案子?16:?{?a[x][y+1]= b[1];?a[x][y-1]= b[2];?a[x+2][y-1]= b[3];?打破;?}?//倒置的7字符正方形
案子?17:?{?a[x-2][y]= b[1];?a[x+2][y+1]= b[2];?a[x+2][y]= b[3];?打破;?}?//将倒置的7字翻转90度。
案子?18:?{?a[x][y-1]= b[1];?a[x][y+1]= b[2];?a[x-2][y+1]= b[3];?打破;?}?//倒7字转180度。
案子?19:?{?a[x-2][y]= b[1];?a[x-2][y-1]= b[2];?a[x+2][y]= b[3];?打破;?}?//将倒置的7字向前旋转270度。
}
}
作废?keyD(?)?//按键操作
{?如果?(kbhit(?))
{?int?关键;
key = getch();
如果?(key==224)
{?key = getch();
如果?(key==75)?{?x-= 2;?}?//按左箭头键,中心的水平轴会减少2。
如果?(key==77)?{?x+= 2;?}?//按右箭头键,在中心的水平轴上加2。
如果?(key==72)?//按向上箭头键更改框。
{?如果?(flag & gt=2?& amp& amp?标志& lt=3?)?{?flag++;?flag % = 2;?flag+= 2;?}
如果?(?flag & gt=4?& amp& amp?标志& lt=7?)?{?flag++;?flag % = 4;?flag+= 4;?}
如果?(flag & gt=8?& amp& amp?标志& lt=11?)?{?flag++;?flag % = 4;?flag+= 8;?}
如果?(flag & gt=12?& amp& amp?标志& lt=15?)?{?flag++;?flag % = 4;?flag+= 12;?}
如果?(?flag & gt=16?& amp& amp?标志& lt=19?)?{?flag++;?flag % = 4;?flag+= 16;?}?}
}
?如果?(key==32)?//按空格键暂停。
{?prfk(?);?而(1)?{?如果?(getch(?)==32)?{?clfk(?);打破;}?}?}?//再次按空格键继续游戏。
?如果?(ifmov(?)==0)?{?x = Tb?flag = Tc?}?//如果不动,取消上述操作。
?不然呢?{?prfk(?);?睡眠(速度);?clfk(?);?TB = x;Tc =标志;} ?//如果是可移动的,则执行操作。
}
}
int?ifmov(?)//判断是否可以移动
{?如果?(a[x][y]!=0)?{?回归?0;?}?//正方形中心有一个图案,返回0,不能移动。
else{?如果?(?(flag==1?& amp& amp?(?a[x][?y-1]==0?& amp& amp?a[x+2][y-1]==0?& amp& amp?a[x+2][y]==0?)?)?|| ?
(flag==2?& amp& amp?(?a[x-2][y]==0?& amp& amp?a[x+2][y]==0?& amp& amp?a[x+4][y]==0?)?)?||?
(flag==3?& amp& amp?(?a[x][y-1]==0?& amp& amp?a[x][y-2]==0?& amp& amp?a[x][y+1]==0?)?)?||
(flag==4?& amp& amp?(?a[x-2][y]==0?& amp& amp?a[x+2][y]==0?& amp& amp?a[x][y+1]==0?)?)?||
(flag==5?& amp& amp?(?a[x][y-1]==0?& amp& amp?a[x][y+1]==0?& amp& amp?a[x-2][y]==0?)?)?||
(flag==6?& amp& amp?(?a[x][?y-1]==0?& amp& amp?a[x-2][y]==0?& amp& amp?a[x+2][y]==0?)?)?||
(flag==7?& amp& amp?(?a[x][y-1]==0?& amp& amp?a[x][y+1]==0?& amp& amp?a[x+2][y]==0?)?)?||
(flag==8?& amp& amp?(?a[x][y+1]==0?& amp& amp?a[x-2][y]==0?& amp& amp?a[x+2][y+1]==0?)?)?||
(flag==9?& amp& amp?(?a[x][y-1]==0?& amp& amp?a[x-2][y]==0?& amp& amp?a[x-2][y+1]==0?)?)?||
(flag==10?& amp& amp?(?a[x][y-1]==0?& amp& amp?a[x-2][y-1]==0?& amp& amp?a[x+2][y]==0?)?)?||
(flag==11?& amp& amp?(?a[x][y+1]==0?& amp& amp?a[x+2][y-1]==0?& amp& amp?a[x+2][y]==0?)?)?||
(flag==12?& amp& amp?(?a[x][y-1]==0?& amp& amp?a[x][y+1]==0?& amp& amp?a[x-2][y-1]==0?)?)?||
(flag = = 13 & amp;& amp(a[x-2][y]= = 0 & amp;& ampa[x+2][y-1]= = 0 & amp;& ampa[x+2][y]==0 ) ) ||
(flag = = 14 & amp;& amp(a[x][y-1]= = 0 & amp;& ampa[x][y+1]= = 0 & amp;& ampa[x+2][y+1]==0 ) ) ||
?(flag = = 15 & amp;& amp(a[x-2][y]= = 0 & amp;& ampa[x-2][y+1]= = 0 & amp;& ampa[x+2][y]==0 ) ) ||
?(flag = = 16 & amp;& amp(a[x][y+1]= = 0 & amp;& ampa[x][y-1]= = 0 & amp;& ampa[x+2][y-1]==0 ) ) ||
?(flag = = 17 & amp;& amp(a[x-2][y]= = 0 & amp;& ampa[x+2][y+1]= = 0 & amp;& ampa[x+2][y]==0 ) ) ||
(flag = = 18 & amp;& amp(a[x][y-1]= = 0 & amp;& ampa[x][y+1]= = 0 & amp;& ampa[x-2][y+1]==0 ) ) ||
?(flag = = 19 & amp;& amp(a[x-2][y]= = 0 & amp;& ampa[x-2][y-1]==0
?& amp& amp?a[x+2][y]==0?)?)?)?{?回归?1;?}
}
回归?0;?//其他条件返回0。
}
作废?clNEXT(?) ?//清除框外的下一个框。
{?旗帜?=?接下来;?x = ZL+WID+6;?y = ZL+10;?clfk(?);?}
void clHA(?) ?//清除一整行框
{?int?k,?hang = 0;?//k是一行中方块的个数。Hang是删除的方形行数。
for(j = ZL+HEI-1;j & gt= ZL+1;j -)?//当一条线有WID/2-2个方块时,它就是满的。
{?k = 0;?for(I = ZL+2;我& ltZL+WID-2;i+=2)
{?如果?(a[i][j]==1)//纵坐标从下到上,横坐标从左到右依次判断行是否满。
{?k++;?//接下来,删除该行。
?如果?(k==WID/2-2)?{ ?for(k = ZL+2;k & ltZL+WID-2;k+=2)?
?{?a[k][j]= 0;?gtxy(k,j);?printf("?);?睡眠(1);?}
?for(k = j-1;k & gtZL;k -)
?{?for(I = ZL+2;我& ltZL+WID-2;i+=2)?//删除的行上有方框。首先清除它们,然后将它们全部向下移动一行。
{?if(a[i][k]==1)?{?a[I][k]= 0;?gtxy(i,k);?printf("?);a[I][k+1]= 1;?
?gtxy(i,k+1);?printf("□");?}?}
}
?j++;?//盒子下移后,重新判断删除的行是否已满。
?hang++;?//记录删除框中的行数。
}
?}
}
}
得分+= 100 *杭;?//每删除一行,获得100积分。
如果?(?Hang & gt0?& amp& amp?(分数%500==0?||?得分/500 & gt;?level-1?)?) ?//500分的话,加速上一关。
{?速度-= 20;?level++;?如果(速度& lt200)速度+= 20;}?
}