俄罗斯方块C语言代码
发布时间:2025-05-11 17:33:38 发布人:远客网络
一、俄罗斯方块C语言代码
#defineZL4//坐标增量,不使游戏窗口靠边
inti,j,Ta,Tb,Tc;//Ta,Tb,Tc用于记住和转换方块变量的值
inta[60][60]={0};//标记游戏屏幕各坐标点:0,1,2分别为空、方块、边框
intb[4];//标记4个"口"方块:1有,0无,类似开关
intx,y,level,score,speed;//方块中心位置的x,y坐标,游戏等级、得分和游戏速度
intflag,next;//当前要操作的方块类型序号,下一个方块类型序号
voidgtxy(intm,intn);//以下声明要用到的自编函数
voidgflag();//获得下一方块序号
intifmov();//判断方块能否移动或变体
voidclNEXT();//清除边框外的NEXT方块
Tb=x;Tc=flag;//临存当前x坐标和序号,以备撤销操作
if(ifmov()==0){y--;prfk();dlHA();break;}//不可动放下,删行,跨出循环
for(i=y-2;i<y+2;i++){if(i==ZL){j=0;}}//方块触到框顶
if(j==0){system("cls");gtxy(10,10);printf("游戏结束!");getch();break;}
clNEXT();//清除框外的NEXT方块
voidgtxy(intm,intn)//控制光标移动
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),pos);
{gtxy(ZL+WID/2-5,ZL-2);printf("俄罗斯方块");//打印游戏名称
gtxy(ZL+WID+3,ZL+7);printf("*******NEXT:");//打印菜单信息
gtxy(ZL+WID+3,ZL+13);printf("**********");
gtxy(ZL+WID+3,ZL+15);printf("Esc:退出游戏");
gtxy(ZL+WID+3,ZL+17);printf("↑键:变体");
gtxy(ZL+WID+3,ZL+19);printf("空格:暂停游戏");
gtxy(ZL,ZL);printf("╔");gtxy(ZL+WID-2,ZL);printf("╗");//打印框角
gtxy(ZL,ZL+HEI);printf("╚");gtxy(ZL+WID-2,ZL+HEI);printf("╝");
a[ZL][ZL+HEI]=2;a[ZL+WID-2][ZL+HEI]=2;//记住有图案
for(i=2;i<WID-2;i+=2){gtxy(ZL+i,ZL);printf("═");}//打印上横框
for(i=2;i<WID-2;i+=2){gtxy(ZL+i,ZL+HEI);printf("═");a[ZL+i][ZL+HEI]=2;}//下框
for(i=1;i<HEI;i++){gtxy(ZL,ZL+i);printf("║");a[ZL][ZL+i]=2;}//左竖框记住有图案
for(i=1;i<HEI;i++){gtxy(ZL+WID-2,ZL+i);printf("║");a[ZL+WID-2][ZL+i]=2;}//右框
CONSOLE_CURSOR_INFOcursor_info={1,0};//以下是隐藏光标的设置
SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE),&cursor_info);
gflag();flag=next;//获得一个当前方块序号
voidgflag()//获得下一个方块的序号
{srand((unsigned)time(NULL));next=rand()%19+1;}
{gflag();Ta=flag;flag=next;//保存当前方块序号,将下一方块序号临时操作
x=ZL+WID+6;y=ZL+10;prfk();//给x,y赋值,在框外打印出下一方块
flag=Ta;x=ZL+WID/2;y=ZL-1;//取回当前方块序号,并给x,y赋值
{for(i=0;i<4;i++){b[i]=1;}//数组b[4]每个元素的值都为1
for(i=x-2;i<=x+4;i+=2)//打印方块
{for(j=y-2;j<=y+1;j++){if(a[i][j]==1&&j>ZL){gtxy(i,j);printf("□");}}}
gtxy(ZL+WID+3,ZL+1); printf("level:%d",level);//以下打印菜单信息
gtxy(ZL+WID+3,ZL+3); printf("score:%d",score);
gtxy(ZL+WID+3,ZL+5); printf("speed:%d",speed);
{for(i=0;i<4;i++){b[i]=0;}//数组b[4]每个元素的值都为0
for(i=x-2;i<=x+4;i+=2)//清除方块
{for(j=y-2;j<=y+1;j++){if(a[i][j]==0&&j>ZL){gtxy(i,j);printf("");}}}
{a[x][y]=b[0];//方块中心位置状态:1-有,0-无
switch(flag)//共6大类,19种小类型
{case1:{a[x][y-1]=b[1];a[x+2][y-1]=b[2];a[x+2][y]=b[3];break;}//田字方块
case2:{a[x-2][y]=b[1];a[x+2][y]=b[2];a[x+4][y]=b[3];break;}//直线方块:----
case3:{a[x][y-1]=b[1];a[x][y-2]=b[2];a[x][y+1]=b[3];break;}//直线方块:|
case4:{a[x-2][y]=b[1];a[x+2][y]=b[2];a[x][y+1]=b[3];break;}//T字方块
case5:{a[x][y-1]=b[1];a[x][y+1]=b[2];a[x-2][y]=b[3];break;}//T字顺时针转90度
case6:{a[x][y-1]=b[1];a[x-2][y]=b[2];a[x+2][y]=b[3];break;}//T字顺转180度
case7:{a[x][y-1]=b[1];a[x][y+1]=b[2];a[x+2][y]=b[3];break;}//T字顺转270度
case8:{a[x][y+1]=b[1];a[x-2][y]=b[2];a[x+2][y+1]=b[3];break;}//Z字方块
case9:{a[x][y-1]=b[1];a[x-2][y]=b[2];a[x-2][y+1]=b[3];break;}//Z字顺转90度
case10:{a[x][y-1]=b[1];a[x-2][y-1]=b[2];a[x+2][y]=b[3];break;}//Z字顺转180度
case11:{a[x][y+1]=b[1];a[x+2][y-1]=b[2];a[x+2][y]=b[3];break;}//Z字顺转270度
case12:{a[x][y-1]=b[1];a[x][y+1]=b[2];a[x-2][y-1]=b[3];break;}//7字方块
case13:{a[x-2][y]=b[1];a[x+2][y-1]=b[2];a[x+2][y]=b[3];break;}//7字顺转90度
case14:{a[x][y-1]=b[1];a[x][y+1]=b[2];a[x+2][y+1]=b[3];break;}//7字顺转180度
case15:{a[x-2][y]=b[1];a[x-2][y+1]=b[2];a[x+2][y]=b[3];break;}//7字顺转270度
case16:{a[x][y+1]=b[1];a[x][y-1]=b[2];a[x+2][y-1]=b[3];break;}//倒7字方块
case17:{a[x-2][y]=b[1];a[x+2][y+1]=b[2];a[x+2][y]=b[3];break;}//倒7字顺转90度
case18:{a[x][y-1]=b[1];a[x][y+1]=b[2];a[x-2][y+1]=b[3];break;}//倒7字顺转180度
case19:{a[x-2][y]=b[1];a[x-2][y-1]=b[2];a[x+2][y]=b[3];break;}//倒7字顺转270度
if(key==75){x-=2;}//按下左方向键,中心横坐标减2
if(key==77){x+=2;}//按下右方向键,中心横坐标加2
if(key==72)//按下向上方向键,方块变体
{if(flag>=2&&flag<=3){flag++;flag%=2;flag+=2;}
if(flag>=4&&flag<=7){flag++;flag%=4;flag+=4;}
if(flag>=8&&flag<=11){flag++;flag%=4;flag+=8;}
if(flag>=12&&flag<=15){flag++;flag%=4;flag+=12;}
if(flag>=16&&flag<=19){flag++;flag%=4;flag+=16;}}
{prfk();while(1){if(getch()==32){clfk();break;}}}//再按空格键,继续游戏
if(ifmov()==0){x=Tb;flag=Tc;}//如果不可动,撤销上面操作
else{prfk();Sleep(speed);clfk();Tb=x;Tc=flag;}//如果可动,执行操作
{if(a[x][y]!=0){return0;}//方块中心处有图案返回0,不可移动
else{if((flag==1&&(a[x][y-1]==0&&a[x+2][y-1]==0&&a[x+2][y]==0))||
(flag==2&&(a[x-2][y]==0&&a[x+2][y]==0&&a[x+4][y]==0))||
(flag==3&&(a[x][y-1]==0&&a[x][y-2]==0&&a[x][y+1]==0))||
(flag==4&&(a[x-2][y]==0&&a[x+2][y]==0&&a[x][y+1]==0))||
(flag==5&&(a[x][y-1]==0&&a[x][y+1]==0&&a[x-2][y]==0))||
(flag==6&&(a[x][y-1]==0&&a[x-2][y]==0&&a[x+2][y]==0))||
(flag==7&&(a[x][y-1]==0&&a[x][y+1]==0&&a[x+2][y]==0))||
(flag==8&&(a[x][y+1]==0&&a[x-2][y]==0&&a[x+2][y+1]==0))||
(flag==9&&(a[x][y-1]==0&&a[x-2][y]==0&&a[x-2][y+1]==0))||
(flag==10&&(a[x][y-1]==0&&a[x-2][y-1]==0&&a[x+2][y]==0))||
(flag==11&&(a[x][y+1]==0&&a[x+2][y-1]==0&&a[x+2][y]==0))||
(flag==12&&(a[x][y-1]==0&&a[x][y+1]==0&&a[x-2][y-1]==0))||
( flag==13&&( a[x-2][y]==0&& a[x+2][y-1]==0&& a[x+2][y]==0))||
( flag==14&&( a[x][y-1]==0&& a[x][y+1]==0&& a[x+2][y+1]==0))||
(flag==15&&( a[x-2][y]==0&& a[x-2][y+1]==0&& a[x+2][y]==0))||
(flag==16&&( a[x][y+1]==0&& a[x][y-1]==0&& a[x+2][y-1]==0))||
( flag==17&&( a[x-2][y]==0&& a[x+2][y+1]==0&& a[x+2][y]==0))||
(flag==18&&( a[x][y-1]==0&&a[x][y+1]==0&& a[x-2][y+1]==0))||
(flag==19&&( a[x-2][y]==0&& a[x-2][y-1]==0
&&a[x+2][y]==0))){return1;}
voidclNEXT()//清除框外的NEXT方块
{flag=next;x=ZL+WID+6;y=ZL+10;clfk();}
{intk,Hang=0;//k是某行方块个数,Hang是删除的方块行数
for(j=ZL+HEI-1;j>=ZL+1;j--)//当某行有WID/2-2个方块时,则为满行
{k=0;for(i=ZL+2;i<ZL+WID-2;i+=2)
{if(a[i][j]==1)//竖坐标从下往上,横坐标由左至右依次判断是否满行
if(k==WID/2-2){ for(k=ZL+2;k<ZL+WID-2;k+=2)
{a[k][j]=0;gtxy(k,j);printf("");Sleep(1);}
{for(i=ZL+2;i<ZL+WID-2;i+=2)//已删行数上面有方块,先清除再全部下移一行
{if(a[i][k]==1){a[i][k]=0;gtxy(i,k);printf("");a[i][k+1]=1;
j++;//方块下移后,重新判断删除行是否满行
score+=100*Hang;//每删除一行,得100分
if(Hang>0&&(score%500==0||score/500>level-1))//得分满500速度加快升一级
{speed-=20;level++;if(speed<200)speed+=20;}
二、c语言写俄罗斯方块代码
1、一、我们可以用编号,不同的编号代表不同的俄罗斯方块,根据编号把不同方块的画法写在代码中,这样19种。方块就得有19种相应的代码来描绘。而且这样扩展性不好,若以后设计了新的方块,则需要更改大量源代码。
2、二、我们很自然的想到可用字模点阵的形式来表示,即设置一个4行4列的数组,元素置1即代表这个位置有小方块,元素置0即代表这个位置无小方块,这个整个的4*4的数组组成俄罗斯方块的形状。
3、但我们还可以优化一下:不用4*4的数组,而是用16个bit位来表示这个点阵。这样存储起来比较方便,故我们用unsigned int的低16位来表示方块的点阵。我们可以用掩码与表示俄罗斯方块的位进行操作,来识别并在屏幕上画出方块。
4、详情见GUI.cpp中的DrawRock函数。
5、我们把俄罗斯方块点阵的数位存在rockArray中,我们可以事先把这19种方块的字模点阵自己转化成十六进制,然后在rockArray数组的初始化时赋值进去。但这样做未免有点太费力,且扩展性也不太好,若以后设计的新方块种类加入,要改变数组rockArray中的值。
6、我们可以考虑把所有俄罗斯方块的点阵存储在配置文件中,在程序初始化时读取文件,把这些点阵转换成unsigned int的变量存储在rockArray中。
三、求C语言俄罗斯方块代码
#defineZL4//坐标增量,不使游戏窗口靠边
inti,j,Ta,Tb,Tc;//Ta,Tb,Tc用于记住和转换方块变量的值
inta[60][60]={0};//标记游戏屏幕各坐标点:0,1,2分别为空、方块、边框
intb[4];//标记4个"口"方块:1有,0无,类似开关
intx,y,level,score,speed;//方块中心位置的x,y坐标,游戏等级、得分和游戏速度
intflag,next;//当前要操作的方块类型序号,下一个方块类型序号
voidgtxy(intm,intn);//以下声明要用到的自编函数
voidgflag();//获得下一方块序号
intifmov();//判断方块能否移动或变体
voidclNEXT();//清除边框外的NEXT方块
Tb=x;Tc=flag;//临存当前x坐标和序号,以备撤销操作
if(ifmov()==0){y--;prfk();dlHA();break;}//不可动放下,删行,跨出循环
for(i=y-2;i<y+2;i++){if(i==ZL){j=0;}}//方块触到框顶
if(j==0){system("cls");gtxy(10,10);printf("游戏结束!");getch();break;}
clNEXT();//清除框外的NEXT方块
voidgtxy(intm,intn)//控制光标移动
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),pos);
{gtxy(ZL+WID/2-5,ZL-2);printf("俄罗斯方块");//打印游戏名称
gtxy(ZL+WID+3,ZL+7);printf("*******NEXT:");//打印菜单信息
gtxy(ZL+WID+3,ZL+13);printf("**********");
gtxy(ZL+WID+3,ZL+15);printf("Esc:退出游戏");
gtxy(ZL+WID+3,ZL+17);printf("↑键:变体");
gtxy(ZL+WID+3,ZL+19);printf("空格:暂停游戏");
gtxy(ZL,ZL);printf("╔");gtxy(ZL+WID-2,ZL);printf("╗");//打印框角
gtxy(ZL,ZL+HEI);printf("╚");gtxy(ZL+WID-2,ZL+HEI);printf("╝");
a[ZL][ZL+HEI]=2;a[ZL+WID-2][ZL+HEI]=2;//记住有图案
for(i=2;i<WID-2;i+=2){gtxy(ZL+i,ZL);printf("═");}//打印上横框
for(i=2;i<WID-2;i+=2){gtxy(ZL+i,ZL+HEI);printf("═");a[ZL+i][ZL+HEI]=2;}//下框
for(i=1;i<HEI;i++){gtxy(ZL,ZL+i);printf("║");a[ZL][ZL+i]=2;}//左竖框记住有图案
for(i=1;i<HEI;i++){gtxy(ZL+WID-2,ZL+i);printf("║");a[ZL+WID-2][ZL+i]=2;}//右框
CONSOLE_CURSOR_INFOcursor_info={1,0};//以下是隐藏光标的设置
SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE),&cursor_info);
gflag();flag=next;//获得一个当前方块序号
voidgflag()//获得下一个方块的序号
{srand((unsigned)time(NULL));next=rand()%19+1;}
{gflag();Ta=flag;flag=next;//保存当前方块序号,将下一方块序号临时操作
x=ZL+WID+6;y=ZL+10;prfk();//给x,y赋值,在框外打印出下一方块
flag=Ta;x=ZL+WID/2;y=ZL-1;//取回当前方块序号,并给x,y赋值
{for(i=0;i<4;i++){b[i]=1;}//数组b[4]每个元素的值都为1
for(i=x-2;i<=x+4;i+=2)//打印方块
{for(j=y-2;j<=y+1;j++){if(a[i][j]==1&&j>ZL){gtxy(i,j);printf("□");}}}
gtxy(ZL+WID+3,ZL+1); printf("level:%d",level);//以下打印菜单信息
gtxy(ZL+WID+3,ZL+3); printf("score:%d",score);
gtxy(ZL+WID+3,ZL+5); printf("speed:%d",speed);
{for(i=0;i<4;i++){b[i]=0;}//数组b[4]每个元素的值都为0
for(i=x-2;i<=x+4;i+=2)//清除方块
{for(j=y-2;j<=y+1;j++){if(a[i][j]==0&&j>ZL){gtxy(i,j);printf("");}}}
{a[x][y]=b[0];//方块中心位置状态:1-有,0-无
switch(flag)//共6大类,19种小类型
{case1:{a[x][y-1]=b[1];a[x+2][y-1]=b[2];a[x+2][y]=b[3];break;}//田字方块
case2:{a[x-2][y]=b[1];a[x+2][y]=b[2];a[x+4][y]=b[3];break;}//直线方块:----
case3:{a[x][y-1]=b[1];a[x][y-2]=b[2];a[x][y+1]=b[3];break;}//直线方块:|
case4:{a[x-2][y]=b[1];a[x+2][y]=b[2];a[x][y+1]=b[3];break;}//T字方块
case5:{a[x][y-1]=b[1];a[x][y+1]=b[2];a[x-2][y]=b[3];break;}//T字顺时针转90度
case6:{a[x][y-1]=b[1];a[x-2][y]=b[2];a[x+2][y]=b[3];break;}//T字顺转180度
case7:{a[x][y-1]=b[1];a[x][y+1]=b[2];a[x+2][y]=b[3];break;}//T字顺转270度
case8:{a[x][y+1]=b[1];a[x-2][y]=b[2];a[x+2][y+1]=b[3];break;}//Z字方块
case9:{a[x][y-1]=b[1];a[x-2][y]=b[2];a[x-2][y+1]=b[3];break;}//Z字顺转90度
case10:{a[x][y-1]=b[1];a[x-2][y-1]=b[2];a[x+2][y]=b[3];break;}//Z字顺转180度
case11:{a[x][y+1]=b[1];a[x+2][y-1]=b[2];a[x+2][y]=b[3];break;}//Z字顺转270度
case12:{a[x][y-1]=b[1];a[x][y+1]=b[2];a[x-2][y-1]=b[3];break;}//7字方块
case13:{a[x-2][y]=b[1];a[x+2][y-1]=b[2];a[x+2][y]=b[3];break;}//7字顺转90度
case14:{a[x][y-1]=b[1];a[x][y+1]=b[2];a[x+2][y+1]=b[3];break;}//7字顺转180度
case15:{a[x-2][y]=b[1];a[x-2][y+1]=b[2];a[x+2][y]=b[3];break;}//7字顺转270度
case16:{a[x][y+1]=b[1];a[x][y-1]=b[2];a[x+2][y-1]=b[3];break;}//倒7字方块
case17:{a[x-2][y]=b[1];a[x+2][y+1]=b[2];a[x+2][y]=b[3];break;}//倒7字顺转90度
case18:{a[x][y-1]=b[1];a[x][y+1]=b[2];a[x-2][y+1]=b[3];break;}//倒7字顺转180度
case19:{a[x-2][y]=b[1];a[x-2][y-1]=b[2];a[x+2][y]=b[3];break;}//倒7字顺转270度
if(key==75){x-=2;}//按下左方向键,中心横坐标减2
if(key==77){x+=2;}//按下右方向键,中心横坐标加2
if(key==72)//按下向上方向键,方块变体
{if(flag>=2&&flag<=3){flag++;flag%=2;flag+=2;}
if(flag>=4&&flag<=7){flag++;flag%=4;flag+=4;}
if(flag>=8&&flag<=11){flag++;flag%=4;flag+=8;}
if(flag>=12&&flag<=15){flag++;flag%=4;flag+=12;}
if(flag>=16&&flag<=19){flag++;flag%=4;flag+=16;}}
{prfk();while(1){if(getch()==32){clfk();break;}}}//再按空格键,继续游戏
if(ifmov()==0){x=Tb;flag=Tc;}//如果不可动,撤销上面操作
else{prfk();Sleep(speed);clfk();Tb=x;Tc=flag;}//如果可动,执行操作
{if(a[x][y]!=0){return0;}//方块中心处有图案返回0,不可移动
else{if((flag==1&&(a[x][y-1]==0&&a[x+2][y-1]==0&&a[x+2][y]==0))||
(flag==2&&(a[x-2][y]==0&&a[x+2][y]==0&&a[x+4][y]==0))||
(flag==3&&(a[x][y-1]==0&&a[x][y-2]==0&&a[x][y+1]==0))||
(flag==4&&(a[x-2][y]==0&&a[x+2][y]==0&&a[x][y+1]==0))||
(flag==5&&(a[x][y-1]==0&&a[x][y+1]==0&&a[x-2][y]==0))||
(flag==6&&(a[x][y-1]==0&&a[x-2][y]==0&&a[x+2][y]==0))||
(flag==7&&(a[x][y-1]==0&&a[x][y+1]==0&&a[x+2][y]==0))||
(flag==8&&(a[x][y+1]==0&&a[x-2][y]==0&&a[x+2][y+1]==0))||
(flag==9&&(a[x][y-1]==0&&a[x-2][y]==0&&a[x-2][y+1]==0))||
(flag==10&&(a[x][y-1]==0&&a[x-2][y-1]==0&&a[x+2][y]==0))||
(flag==11&&(a[x][y+1]==0&&a[x+2][y-1]==0&&a[x+2][y]==0))||
(flag==12&&(a[x][y-1]==0&&a[x][y+1]==0&&a[x-2][y-1]==0))||
( flag==13&&( a[x-2][y]==0&& a[x+2][y-1]==0&& a[x+2][y]==0))||
( flag==14&&( a[x][y-1]==0&& a[x][y+1]==0&& a[x+2][y+1]==0))||
(flag==15&&( a[x-2][y]==0&& a[x-2][y+1]==0&& a[x+2][y]==0))||
(flag==16&&( a[x][y+1]==0&& a[x][y-1]==0&& a[x+2][y-1]==0))||
( flag==17&&( a[x-2][y]==0&& a[x+2][y+1]==0&& a[x+2][y]==0))||
(flag==18&&( a[x][y-1]==0&&a[x][y+1]==0&& a[x-2][y+1]==0))||
(flag==19&&( a[x-2][y]==0&& a[x-2][y-1]==0
&&a[x+2][y]==0))){return1;}
voidclNEXT()//清除框外的NEXT方块
{flag=next;x=ZL+WID+6;y=ZL+10;clfk();}
{intk,Hang=0;//k是某行方块个数,Hang是删除的方块行数
for(j=ZL+HEI-1;j>=ZL+1;j--)//当某行有WID/2-2个方块时,则为满行
{k=0;for(i=ZL+2;i<ZL+WID-2;i+=2)
{if(a[i][j]==1)//竖坐标从下往上,横坐标由左至右依次判断是否满行
if(k==WID/2-2){ for(k=ZL+2;k<ZL+WID-2;k+=2)
{a[k][j]=0;gtxy(k,j);printf("");Sleep(1);}
{for(i=ZL+2;i<ZL+WID-2;i+=2)//已删行数上面有方块,先清除再全部下移一行
{if(a[i][k]==1){a[i][k]=0;gtxy(i,k);printf("");a[i][k+1]=1;
j++;//方块下移后,重新判断删除行是否满行
score+=100*Hang;//每删除一行,得100分
if(Hang>0&&(score%500==0||score/500>level-1))//得分满500速度加快升一级
{speed-=20;level++;if(speed<200)speed+=20;}