俄罗斯方块c语言
Ⅰ 怎样用c语言编写俄罗斯方块程序
俄罗斯方块C源代码
#include<stdio.h>
#include<windows.h>
#include<conio.h>
#include<time.h>
#defineZL4 //坐标增量,不使游戏窗口靠边
#defineWID36 //游戏窗口的宽度
#defineHEI20 //游戏窗口的高度
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(); //获得下一方块序号
voidcsh(); //初始化界面
voidstart(); //开始部分
voidprfk(); //打印方块
voidclfk(); //清除方块
voidmkfk(); //制作方块
voidkeyD(); //按键操作
intifmov(); //判断方块能否移动或变体
void clHA(); //清除满行的方块
voidclNEXT(); //清除边框外的NEXT方块
intmain()
{csh();
while(1)
{start();//开始部分
while(1)
{prfk();
Sleep(speed); //延时
clfk();
Tb=x;Tc=flag;//临存当前x坐标和序号,以备撤销操作
keyD();
y++;//方块向下移动
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方块
}
return0;
}
voidgtxy(intm,intn)//控制光标移动
{COORDpos;//定义变量
pos.X=m;//横坐标
pos.Y=n;//纵坐标
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),pos);
}
voidcsh()//初始化界面
{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);
level=1;score=0;speed=400;
gflag();flag=next;//获得一个当前方块序号
}
voidgflag() //获得下一个方块的序号
{srand((unsigned)time(NULL));next=rand()%19+1; }
voidstart()//开始部分
{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赋值
}
voidprfk()//打印俄罗斯方块
{for(i=0;i<4;i++){b[i]=1;}//数组b[4]每个元素的值都为1
mkfk();//制作俄罗斯方块
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);
}
voidclfk()//清除俄罗斯方块
{for(i=0;i<4;i++){b[i]=0;}//数组b[4]每个元素的值都为0
mkfk();//制作俄罗斯方块
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("");}}}
}
voidmkfk()//制作俄罗斯方块
{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度
}
}
voidkeyD()//按键操作
{if(kbhit())
{intkey;
key=getch();
if(key==224)
{key=getch();
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;}}
}
if(key==32)//按空格键,暂停
{prfk();while(1){if(getch()==32){clfk();break;}}} //再按空格键,继续游戏
if(ifmov()==0){x=Tb;flag=Tc;} //如果不可动,撤销上面操作
else{prfk();Sleep(speed);clfk();Tb=x;Tc=flag;} //如果可动,执行操作
}
}
intifmov()//判断能否移动
{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;}
}
return0; //其它情况返回0
}
voidclNEXT() //清除框外的NEXT方块
{flag=next;x=ZL+WID+6;y=ZL+10;clfk();}
void clHA() //清除满行的方块
{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)//竖坐标从下往上,横坐标由左至右依次判断是否满行
{k++; //下面将操作删除行
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(k=j-1;k>ZL;k--)
{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;
gtxy(i,k+1);printf("□");}}
}
j++;//方块下移后,重新判断删除行是否满行
Hang++;//记录删除方块的行数
}
}
}
}
score+=100*Hang; //每删除一行,得100分
if(Hang>0&&(score%500==0||score/500>level-1)) //得分满500速度加快升一级
{speed-=20;level++;if(speed<200)speed+=20; }
}
Ⅱ 求一份用C语言编写的俄罗斯方块的源代码!
俄罗斯方块C源代码
#include<stdio.h>
#include<windows.h>
#include<conio.h>
#include<time.h>
#defineZL4 //坐标增量,不使游戏窗口靠边
#defineWID36 //游戏窗口的宽度
#defineHEI20 //游戏窗口的高度
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(); //获得下一方块序号
voidcsh(); //初始化界面
voidstart(); //开始部分
voidprfk(); //打印方块
voidclfk(); //清除方块
voidmkfk(); //制作方块
voidkeyD(); //按键操作
intifmov(); //判断方块能否移动或变体
void clHA(); //清除满行的方块
voidclNEXT(); //清除边框外的NEXT方块
intmain()
{csh();
while(1)
{start();//开始部分
while(1)
{prfk();
Sleep(speed); //延时
clfk();
Tb=x;Tc=flag;//临存当前x坐标和序号,以备撤销操作
keyD();
y++;//方块向下移动
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方块
}
return0;
}
voidgtxy(intm,intn)//控制光标移动
{COORDpos;//定义变量
pos.X=m;//横坐标
pos.Y=n;//纵坐标
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),pos);
}
voidcsh()//初始化界面
{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);
level=1;score=0;speed=400;
gflag();flag=next;//获得一个当前方块序号
}
voidgflag() //获得下一个方块的序号
{srand((unsigned)time(NULL));next=rand()%19+1; }
voidstart()//开始部分
{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赋值
}
voidprfk()//打印俄罗斯方块
{for(i=0;i<4;i++){b[i]=1;}//数组b[4]每个元素的值都为1
mkfk();//制作俄罗斯方块
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);
}
voidclfk()//清除俄罗斯方块
{for(i=0;i<4;i++){b[i]=0;}//数组b[4]每个元素的值都为0
mkfk();//制作俄罗斯方块
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("");}}}
}
voidmkfk()//制作俄罗斯方块
{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度
}
}
voidkeyD()//按键操作
{if(kbhit())
{intkey;
key=getch();
if(key==224)
{key=getch();
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;}}
}
if(key==32)//按空格键,暂停
{prfk();while(1){if(getch()==32){clfk();break;}}} //再按空格键,继续游戏
if(ifmov()==0){x=Tb;flag=Tc;} //如果不可动,撤销上面操作
else{prfk();Sleep(speed);clfk();Tb=x;Tc=flag;} //如果可动,执行操作
}
}
intifmov()//判断能否移动
{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;}
}
return0; //其它情况返回0
}
voidclNEXT() //清除框外的NEXT方块
{flag=next;x=ZL+WID+6;y=ZL+10;clfk();}
void clHA() //清除满行的方块
{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)//竖坐标从下往上,横坐标由左至右依次判断是否满行
{k++; //下面将操作删除行
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(k=j-1;k>ZL;k--)
{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;
gtxy(i,k+1);printf("□");}}
}
j++;//方块下移后,重新判断删除行是否满行
Hang++;//记录删除方块的行数
}
}
}
}
score+=100*Hang; //每删除一行,得100分
if(Hang>0&&(score%500==0||score/500>level-1)) //得分满500速度加快升一级
{speed-=20;level++;if(speed<200)speed+=20; }
}
Ⅲ 用c语言编写俄罗斯方块的程序
这里把游戏的关键设计放在三个盒子和一个坐标上:
大盒子:一个两维数组,记录着方块点阵的开与关(把游戏的舞台想象
成一个点阵),在下面也把这个东西称为地图
两个5*5小盒子:两维数组,一个盛放着正在下落的方块,一个盛放在
下一个下落的方块(即next),当然这两个也必须想象成一个点阵:如长条
的点阵为:
00000
00100
00100
00100
00100
现在你只要有这么一个概念:一个不断定时下落的小盒子从大盒子顶
部下降到底部,之后再将next盒子放在下落盒子,再进行下一轮的下落...
中间的控制等尚不要太着急.
现在面临着一个问题:
下落的盒子和地图之间要怎么联系起来?
一个好的方法是再定义一个坐标:x,y,保存着小盒子左上角在地图上对应
的下标(位置),即当x
=
0,
y
=
0时,小盒子处于地图的左上部.如此,当
小盒子需要移动时,即只须要改变x,y的值.
现在说说旋转.
小盒子保存着当前下落形状的点阵,那么旋转就只须要将这个点阵旋
转90度:例如:
00000
00000
00100
00000
00100
->
01111
00100
00000
00100
00000
这一点实现起来还是不太难的.
判断碰撞
通常这种情况只须要在有移动小盒或旋转盒子时发生:也即点阵非空
是互斥的,当小盒要向下移(x++)时,如果小盒里的点阵与地图上的点阵(非
空的地方)重叠,则不能下移,(卡住了),旋转则转换后的形状与地图有冲
突则要放弃旋转.
到了这里,你应该有一个大概的了解了,至于怎样在屏幕上画出来,这
个是比较简单的,下面的代码会慢慢与你解释.
*/
/*接下一贴*/
Ⅳ 谁能提供个俄罗斯方块的C语言代码谢谢
(1)由于c的随机性函数不好,所以每次游戏开始根据bios时间设置种子。
(2)得分越高,方块下降速度越快(每200分为单位)。
(3)每下落一个方块加1分,每消除一行加10分,两行加30分,三行加70分,四行加150分。初试分数为100分。
游戏控制:
up-旋转;空格-下落到底; 左右下方向键-控制方向。P-开始或暂停游戏。 ESC-退出。
特点:
(1)由于tc不支持中文,所以基本都是英文注释。
(2)函数命名尽可能规范的表达其内部处理目的和过程。
(3)代码加上注释仅有577行。(我下载过的两个俄罗斯方块代码一个在1087行,一个在993行,我的比它们代码少)。
(4)除了消除空格时算法比较复杂,其他算法都比较简单易读。
(5)绘图效率和局部代码效率扔有待提高。
(6)FrameTime参数可能依据不同硬件环境进行具体设置,InitGame需要正确的TC路径。
/********************************/
/* Desc: 俄罗斯方块游戏 */
/* By: hoodlum1980 */
/* Email: [email protected] */
/* Date: 2008.03.12 22:30 */
/********************************/
#include <stdio.h>
#include <bios.h>
#include <dos.h>
#include <graphics.h>
#include <string.h>
#include <stdlib.h>
#define true 1
#define false 0
#define BoardWidth 12
#define BoardHeight 23
#define _INNER_HELPER /*inner helper method */
/*Scan Codes Define*/
enum KEYCODES
{
K_ESC =0x011b,
K_UP =0x4800, /* upward arrow */
K_LEFT =0x4b00,
K_DOWN =0x5000,
K_RIGHT =0x4d00,
K_SPACE =0x3920,
K_P =0x1970
};
/* the data structure of the block */
typedef struct tagBlock
{
char c[4][4]; /* cell fill info array, 0-empty, 1-filled */
int x; /* block position cx [ 0,BoardWidht -1] */
int y; /* block position cy [-4,BoardHeight-1] */
char color; /* block color */
char size; /* block max size in width or height */
char name; /* block name (the block's shape) */
} Block;
/* game's global info */
int FrameTime= 1300;
int CellSize= 18;
int BoardLeft= 30;
int BoardTop= 30;
/* next block grid */
int NBBoardLeft= 300;
int NBBoardTop= 30;
int NBCellSize= 10;
/* score board position */
int ScoreBoardLeft= 300;
int ScoreBoardTop=100;
int ScoreBoardWidth=200;
int ScoreBoardHeight=35;
int ScoreColor=LIGHTCYAN;
/* infor text postion */
int InfoLeft=300;
int InfoTop=200;
int InfoColor=YELLOW;
int BorderColor=DARKGRAY;
int BkGndColor=BLACK;
int GameRunning=true;
int TopLine=BoardHeight-1; /* top empty line */
int TotalScore=100;
char info_score[20];
char info_help[255];
char info_common[255];
/* our board, Board[x][y][0]-isFilled, Board[x][y][1]-fillColor */
unsigned char Board[BoardWidth][BoardHeight][2];
char BufferCells[4][4]; /* used to judge if can rotate block */
Block curBlock; /* current moving block */
Block nextBlock; /* next Block to appear */
/* function list */
int GetKeyCode();
int CanMove(int dx,int dy);
int CanRotate();
int RotateBlock(Block *block);
int MoveBlock(Block *block,int dx,int dy);
void DrawBlock(Block *block,int,int,int);
void EraseBlock(Block *block,int,int,int);
void DisplayScore();
void DisplayInfo(char* text);
void GenerateBlock(Block *block);
void NextBlock();
void InitGame();
int PauseGame();
void QuitGame();
/*Get Key Code */
int GetKeyCode()
{
int key=0;
if(bioskey(1))
{
key=bioskey(0);
}
return key;
}
/* display text! */
void DisplayInfo(char *text)
{
setcolor(BkGndColor);
outtextxy(InfoLeft,InfoTop,info_common);
strcpy(info_common,text);
setcolor(InfoColor);
outtextxy(InfoLeft,InfoTop,info_common);
}
/* create a new block by key number,
* the block anchor to the top-left corner of 4*4 cells
*/
void _INNER_HELPER GenerateBlock(Block *block)
{
int key=(random(13)*random(17)+random(1000)+random(3000))%7;
block->size=3;/* because most blocks' size=3 */
memset(block->c,0,16);
switch(key)
{
case 0:
block->name='T';
block->color=RED;
block->c[1][0]=1;
block->c[1][1]=1, block->c[2][1]=1;
block->c[1][2]=1;
break;
case 1:
block->name='L';
block->color=YELLOW;
block->c[1][0]=1;
block->c[1][1]=1;
block->c[1][2]=1, block->c[2][2]=1;
break;
case 2:
block->name='J';
block->color=LIGHTGRAY;
block->c[1][0]=1;
block->c[1][1]=1;
block->c[1][2]=1, block->c[0][2]=1;
break;
case 3:
block->name='z';
block->color=CYAN;
block->c[0][0]=1, block->c[1][0]=1;
block->c[1][1]=1, block->c[2][1]=1;
break;
case 4:
block->name='5';
block->color=LIGHTBLUE;
block->c[1][0]=1, block->c[2][0]=1;
block->c[0][1]=1, block->c[1][1]=1;
break;
case 5:
block->name='o';
block->color=BLUE;
block->size=2;
block->c[0][0]=1, block->c[1][0]=1;
block->c[0][1]=1, block->c[1][1]=1;
break;
case 6:
block->name='I';
block->color=GREEN;
block->size=4;
block->c[1][0]=1;
block->c[1][1]=1;
block->c[1][2]=1;
block->c[1][3]=1;
break;
}
}
/* get next block! */
void NextBlock()
{
/* the nextBlock to curBlock */
curBlock.size=nextBlock.size;
curBlock.color=nextBlock.color;
curBlock.x=(BoardWidth-4)/2;
curBlock.y=-curBlock.size;
memcpy(curBlock.c,nextBlock.c,16);
/* generate nextBlock and show it */
EraseBlock(&nextBlock,NBBoardLeft,NBBoardTop,NBCellSize);
GenerateBlock(&nextBlock);
nextBlock.x=1,nextBlock.y=0;
DrawBlock(&nextBlock,NBBoardLeft,NBBoardTop,NBCellSize);
}
/* rotate the block, update the block struct data */
int _INNER_HELPER RotateCells(char c[4][4],char blockSize)
{
char temp,i,j;
switch(blockSize)
{
case 3:
temp=c[0][0];
c[0][0]=c[2][0], c[2][0]=c[2][2], c[2][2]=c[0][2], c[0][2]=temp;
temp=c[0][1];
c[0][1]=c[1][0], c[1][0]=c[2][1], c[2][1]=c[1][2], c[1][2]=temp;
break;
case 4: /* only 'I' block arived here! */
c[1][0]=1-c[1][0], c[1][2]=1-c[1][2], c[1][3]=1-c[1][3];
c[0][1]=1-c[0][1], c[2][1]=1-c[2][1], c[3][1]=1-c[3][1];
break;
}
}
/* judge if the block can move toward the direction */
int CanMove(int dx,int dy)
{
int i,j,tempX,tempY;
for(i=0;i<curBlock.size;i++)
{
for(j=0;j<curBlock.size;j++)
{
if(curBlock.c[i][j])
{
/* cannot move leftward or rightward */
tempX = curBlock.x + i + dx;
if(tempX<0 || tempX>(BoardWidth-1)) return false; /* make sure x is valid! */
/* cannot move downward */
tempY = curBlock.y + j + dy;
if(tempY>(BoardHeight-1)) return false; /* y is only checked lower bound, maybe negative!!!! */
/* the cell already filled, we must check Y's upper bound before check cell ! */
if(tempY>=0 && Board[tempX][tempY][0]) return false;
}
}
}
return true;
}
/* judge if the block can rotate */
int CanRotate()
{
int i,j,tempX,tempY;
/* update buffer */
memcpy(BufferCells, curBlock.c, 16);
RotateCells(BufferCells,curBlock.size);
for(i=0;i<curBlock.size;i++)
{
for(j=0;j<curBlock.size;j++)
{
if(BufferCells[i][j])
{
tempX=curBlock.x+i;
tempY=curBlock.y+j;
if(tempX<0 || tempX>(BoardWidth-1))
return false;
if(tempY>(BoardHeight-1))
return false;
if(tempY>=0 && Board[tempX][tempY][0])
return false;
}
}
}
return true;
}
/* draw the block */
void _INNER_HELPER DrawBlock(Block *block,int bdLeft,int bdTop,int cellSize)
{
int i,j;
setfillstyle(SOLID_FILL,block->color);
for(i=0;i<block->size;i++)
{
for(j=0;j<block->size;j++)
{
if(block->c[i][j] && (block->y+j)>=0)
{
floodfill(
bdLeft+cellSize*(i+block->x)+cellSize/2,
bdTop+cellSize*(j+block->y)+cellSize/2,
BorderColor);
}
}
}
}
/* Rotate the block, if success, return true */
int RotateBlock(Block *block)
{
char temp,i,j;
int b_success;
if(curBlock.size==2)
return;
if(( b_success=CanRotate()))
{
EraseBlock(block,BoardLeft,BoardTop,CellSize);
memcpy(curBlock.c,BufferCells,16);
DrawBlock(block,BoardLeft,BoardTop,CellSize);
}
return b_success;
}
/* erase a block, only fill the filled cell with background color */
void _INNER_HELPER EraseBlock(Block *block,int bdLeft,int bdTop,int cellSize)
{
int i,j;
setfillstyle(SOLID_FILL,BkGndColor);
for(i=0;i<block->size;i++)
{
for(j=0;j<block->size;j++)
{
if(block->c[i][j] && (block->y+j>=0))
{
floodfill(
bdLeft+cellSize*(i+block->x)+cellSize/2,
bdTop+cellSize*(j+block->y)+cellSize/2,
BorderColor);
}
}
}
}
/* move by the direction if can, donothing if cannot
* return value: true - success, false - cannot move toward this direction
*/
int MoveBlock(Block *block,int dx,int dy)
{
int b_canmove=CanMove(dx,dy);
if(b_canmove)
{
EraseBlock(block,BoardLeft,BoardTop,CellSize);
curBlock.x+=dx;
curBlock.y+=dy;
DrawBlock(block,BoardLeft,BoardTop,CellSize);
}
return b_canmove;
}
/* drop the block to the bottom! */
int DropBlock(Block *block)
{
EraseBlock(block,BoardLeft,BoardTop,CellSize);
while(CanMove(0,1))
{
curBlock.y++;
}
DrawBlock(block,BoardLeft,BoardTop,CellSize);
return 0;/* return value is assign to the block's alive */
}
/* init the graphics mode, draw the board grid */
void InitGame()
{
int i,j,gdriver=DETECT,gmode;
struct time sysTime;
/* draw board cells */
memset(Board,0,BoardWidth*BoardHeight*2);
memset(nextBlock.c,0,16);
strcpy(info_help,"P: Pause Game. --by hoodlum1980");
initgraph(&gdriver,&gmode,"c:\\tc\\");
setcolor(BorderColor);
for(i=0;i<=BoardWidth;i++)
{
line(BoardLeft+i*CellSize, BoardTop, BoardLeft+i*CellSize, BoardTop+ BoardHeight*CellSize);
}
for(i=0;i<=BoardHeight;i++)
{
line(BoardLeft, BoardTop+i*CellSize, BoardLeft+BoardWidth*CellSize, BoardTop+ i*CellSize);
}
/* draw board outer border rect */
rectangle(BoardLeft-CellSize/4, BoardTop-CellSize/4,
BoardLeft+BoardWidth*CellSize+CellSize/4,
BoardTop+BoardHeight*CellSize+CellSize/4);
/* draw next block grids */
for(i=0;i<=4;i++)
{
line(NBBoardLeft+i*NBCellSize, NBBoardTop, NBBoardLeft+i*NBCellSize, NBBoardTop+4*NBCellSize);
line(NBBoardLeft, NBBoardTop+i*NBCellSize, NBBoardLeft+4*NBCellSize, NBBoardTop+ i*NBCellSize);
}
/* draw score rect */
rectangle(ScoreBoardLeft,ScoreBoardTop,ScoreBoardLeft+ScoreBoardWidth,ScoreBoardTop+ScoreBoardHeight);
DisplayScore();
/* set new seed! */
gettime(&sysTime);
srand(sysTime.ti_hour*3600+sysTime.ti_min*60+sysTime.ti_sec);
GenerateBlock(&nextBlock);
NextBlock(); /* create first block */
setcolor(DARKGRAY);
outtextxy(InfoLeft,InfoTop+20,"Up -rotate Space-drop");
outtextxy(InfoLeft,InfoTop+35,"Left-left Right-right");
outtextxy(InfoLeft,InfoTop+50,"Esc -exit");
DisplayInfo(info_help);
}
/* set the isFilled and fillcolor data to the board */
void _INNER_HELPER FillBoardData()
{
int i,j;
for(i=0;i<curBlock.size;i++)
{
for(j=0;j<curBlock.size;j++)
{
if(curBlock.c[i][j] && (curBlock.y+j)>=0)
{
Board[curBlock.x+i][curBlock.y+j][0]=1;
Board[curBlock.x+i][curBlock.y+j][1]=curBlock.color;
}
}
}
}
/* draw one line of the board */
void _INNER_HELPER PaintBoard()
{
int i,j,fillcolor;
for(j=max((TopLine-4),0);j<BoardHeight;j++)
{
for(i=0;i<BoardWidth;i++)
{
fillcolor=Board[i][j][0]? Board[i][j][1]:BkGndColor;
setfillstyle(SOLID_FILL,fillcolor);
floodfill(BoardLeft+i*CellSize+CellSize/2,BoardTop+j*CellSize+CellSize/2,BorderColor);
}
}
}
/* check if one line if filled full and increase the totalScore! */
void _INNER_HELPER CheckBoard()
{
int i,j,k,score=10,sum=0,topy,lines=0;
/* we find the top empty line! */
j=topy=BoardHeight-1;
do
{
sum=0;
for(i=0;i< BoardWidth; i++)
{
sum+=Board[i][topy][0];
}
topy--;
} while(sum>0 && topy>0);
/* remove the full filled line (max remove lines count = 4) */
do
{
sum=0;
for(i=0;i< BoardWidth; i++)
sum+=Board[i][j][0];
if(sum==BoardWidth)/* we find this line is full filled, remove it! */
{
/* move the cells data down one line */
for(k=j; k > topy;k--)
{
for(i=0;i<BoardWidth;i++)
{
Board[i][k][0]=Board[i][k-1][0];
Board[i][k][1]=Board[i][k-1][1];
}
}
/*make the top line empty! */
for(i=0;i<BoardWidth;i++)
{
Board[i][topy][0]=0;
Board[i][topy][1]=0;
}
topy++; /* move the topline downward one line! */
lines++; /* lines <=4 */
TotalScore+=score;
score*=2; /* adding: 10, 30, 70, 150 */
}
else
j--;
} while(sum>0 && j>topy && lines<4);
/* speed up the game when score is high, minimum is 400 */
FrameTime=max(1200-100*(TotalScore/200), 400);
TopLine=topy;/* update the top line */
/* if no lines remove, only add 1: */
if(lines==0)
TotalScore++;
}
/* display the score */
void _INNER_HELPER DisplayScore()
{
setcolor(BkGndColor);
outtextxy(ScoreBoardLeft+5,ScoreBoardTop+5,info_score);
setcolor(ScoreColor);
sprintf(info_score,"Score: %d",TotalScore);
outtextxy(ScoreBoardLeft+5,ScoreBoardTop+5,info_score);
}
/* we call this function when a block is inactive. */
void UpdateBoard()
{
FillBoardData();
CheckBoard();
PaintBoard();
DisplayScore();
}
/* pause the game, and timer handler stop move down the block! */
int PauseGame()
{
int key=0;
DisplayInfo("Press P to Start or Resume!");
while(key!=K_P && key!=K_ESC)
{
while(!(key=GetKeyCode())){}
}
DisplayInfo(info_help);
return key;
}
/* quit the game and do cleaning work. */
void QuitGame()
{
closegraph();
}
/* the entry point function. */
void main()
{
int i,flag=1,j,key=0,tick=0;
InitGame();
if(PauseGame()==K_ESC)
goto GameOver;
/* wait until a key pressed */
while(key!=K_ESC)
{
/* wait until a key pressed */
while(!(key=GetKeyCode()))
{
tick++;
if(tick>=FrameTime)
{
/* our block has dead! (can't move down), we get next block */
if(!MoveBlock(&curBlock,0,1))
{
UpdateBoard();
NextBlock();
if(!CanMove(0,1))
goto GameOver;
}
tick=0;
}
delay(100);
}
switch(key)
{
case K_LEFT:
MoveBlock(&curBlock,-1,0);
break;
case K_RIGHT:
MoveBlock(&curBlock,1,0);
break;
case K_DOWN:
MoveBlock(&curBlock,0,1);
break;
case K_UP:
RotateBlock(&curBlock);
break;
case K_SPACE:
DropBlock(&curBlock);
break;
case K_P:
PauseGame();
break;
}
}
GameOver:
DisplayInfo("GAME OVER! Press any key to exit!");
getch(); /* wait the user Press any key. */
QuitGame();
}
----------------------------------【代码文件结尾】--------------------------------------------------
Ⅳ 求C语言俄罗斯方块代码
俄罗斯方块C源代码
#include<stdio.h>
#include<windows.h>
#include<conio.h>
#include<time.h>
#defineZL4 //坐标增量,不使游戏窗口靠边
#defineWID36 //游戏窗口的宽度
#defineHEI20 //游戏窗口的高度
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(); //获得下一方块序号
voidcsh(); //初始化界面
voidstart(); //开始部分
voidprfk(); //打印方块
voidclfk(); //清除方块
voidmkfk(); //制作方块
voidkeyD(); //按键操作
intifmov(); //判断方块能否移动或变体
void clHA(); //清除满行的方块
voidclNEXT(); //清除边框外的NEXT方块
intmain()
{csh();
while(1)
{start();//开始部分
while(1)
{prfk();
Sleep(speed); //延时
clfk();
Tb=x;Tc=flag;//临存当前x坐标和序号,以备撤销操作
keyD();
y++;//方块向下移动
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方块
}
return0;
}
voidgtxy(intm,intn)//控制光标移动
{COORDpos;//定义变量
pos.X=m;//横坐标
pos.Y=n;//纵坐标
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),pos);
}
voidcsh()//初始化界面
{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);
level=1;score=0;speed=400;
gflag();flag=next;//获得一个当前方块序号
}
voidgflag() //获得下一个方块的序号
{srand((unsigned)time(NULL));next=rand()%19+1; }
voidstart()//开始部分
{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赋值
}
voidprfk()//打印俄罗斯方块
{for(i=0;i<4;i++){b[i]=1;}//数组b[4]每个元素的值都为1
mkfk();//制作俄罗斯方块
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);
}
voidclfk()//清除俄罗斯方块
{for(i=0;i<4;i++){b[i]=0;}//数组b[4]每个元素的值都为0
mkfk();//制作俄罗斯方块
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("");}}}
}
voidmkfk()//制作俄罗斯方块
{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度
}
}
voidkeyD()//按键操作
{if(kbhit())
{intkey;
key=getch();
if(key==224)
{key=getch();
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;}}
}
if(key==32)//按空格键,暂停
{prfk();while(1){if(getch()==32){clfk();break;}}} //再按空格键,继续游戏
if(ifmov()==0){x=Tb;flag=Tc;} //如果不可动,撤销上面操作
else{prfk();Sleep(speed);clfk();Tb=x;Tc=flag;} //如果可动,执行操作
}
}
intifmov()//判断能否移动
{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;}
}
return0; //其它情况返回0
}
voidclNEXT() //清除框外的NEXT方块
{flag=next;x=ZL+WID+6;y=ZL+10;clfk();}
void clHA() //清除满行的方块
{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)//竖坐标从下往上,横坐标由左至右依次判断是否满行
{k++; //下面将操作删除行
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(k=j-1;k>ZL;k--)
{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;
gtxy(i,k+1);printf("□");}}
}
j++;//方块下移后,重新判断删除行是否满行
Hang++;//记录删除方块的行数
}
}
}
}
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、用C语言绘制图形界面
EasyX图形库(http://www.easyx.cn)即TC的图形库在VC下的移植。
包含库#include <graphics.h>
先初始化图形窗口
initgraph(WINDOW_WIDTH, WINDOW_HIGH) ;WINDOW_WIDTH为窗口的宽带,WINDOW_HIGH为窗口的高度。
清空绘图设备
cleardevice();
设置画笔颜色
setcolor(RED) ;
设置线条风格
setlinestyle(PS_SOLID, NULL, 0);
画矩形
rectangle
还有画线、显示文字等函数,可以参照其帮助文档。
注意:由于我们用的是EasyX图形库,故源文件后缀要为.cpp,但其中内容都是C的语法。
2、存储表示出俄罗斯方块的形状
一、我们可以用编号,不同的编号代表不同的俄罗斯方块,根据编号把不同方块的画法写在代码中,这样19种
方块就得有19种相应的代码来描绘。而且这样扩展性不好,若以后设计了新的方块,则需要更改大量源代码。
二、我们很自然的想到可用字模点阵的形式来表示,即设置一个4行4列的数组,元素置1即代表这个位置有小
方块,元素置0即代表这个位置无小方块,这个整个的4*4的数组组成俄罗斯方块的形状。
1000
1000
1100
0000
我们把俄罗斯方块点阵的数位存在rockArray中,我们可以事先把这19种方块的字模点阵自己转化成十六进制,然后在rockArray数组的初始化时赋值进去。
但这样做未免有点太费力,且扩展性也不太好,若以后设计的新方块种类加入,要改变数组rockArray中的值。
我们可以考虑把所有俄罗斯方块的点阵存储在配置文件中,在程序初始化时读取文件,把这些点阵转换成unsigned int的变量存储在rockArray中。
这样,以后我们增添新的方块形状只需要在配置文件中增加新的点阵即可。
@###
@###
@@##
####(为使得看起来更醒目,我们用@表示1,用#表示0)
3、让图形动起来
在某位置处用函数DrawRock在屏幕上画出俄罗斯方块,然后再擦除掉(即用背景色在原位置处重绘一次方块),最后在下落的下一个位置处用函数DrawRock在屏幕上画出俄罗斯方块,如此循环,中间用计时器间隔一段时间以控制下落的速度。
同理,按下屏幕的左右键也是如此,只是在按下键盘时把方块的位置重新计算了。
那么按下上方向键时,如何让方块翻转呢?
我们在配置文件中就把方块的顺时针翻转形态放在了一起:
@###
@###
@@##
####
@@@#
@###
####
####
@@##
#@##
#@##
####
##@#
@@@#
####
####
我们每按一次上方向键改变一次方块的形状即可。若一直按上键,形状应该是循环地翻滚。
我们想到了循环链表的数据结构可实现这个效果。
可是我们若把这些一种类的方块的各种形态串成循环链表形式,那么每次重新生成方块时我们就难以随机地生成方块了。
故还是得用数组来存储,但又要有循环链表的功能,于是我们想到了静态循环链表。
我们用结构体来作为一个方块在rockArray中的元素
typedef struct ROCK
{ //用来表示方块的形状(每一个字节是8位,用每4位表示方块中的一行)
unsigned int rockShapeBits ;
int nextRockIndex ; //下一个方块,在数组中的下标
} RockType ;
这样,当我们按下上方向键时,把传入函数DrawRock中的rockIndex变为当前方块结构体中的nextRockIndex即可。
Ⅶ 求一个简单的c语言写的俄罗斯方块程序
刚学c的时候编的,所以程序规范性以及代码的执行效率都不高,而且程序超长。但应该没有太难的语句。
#include<stdio.h>
#include<string.h>
#include<bios.h>
#include<stdlib.h>
#include<time.h>
#include<dos.h>
int dx[4],dy[4]; /*定义全局变量*/
int zt1,zt2,str[15][19];
/*str[15][19]是把整个屏幕分为15*19个方格,每一个方格用一个数组单元表示,
如果=15,则这个方格已被占用,=0,则还是空的*/
int cx[8][5][4],cy[8][5][4]; /*该变量表示每种状态下,旋转时坐标的改变*/
int x,y,j,ji,c;
int maxzt[8]=; /*各个种类的方块分别有几种状态*/
cir() /*旋转的处理函数*/
{ dx[0]=dx[0]+cx[zt1][zt2][0];dy[0]=dy[0]+cy[zt1][zt2][0];
dx[2]=dx[2]+cx[zt1][zt2][2];dy[2]=dy[2]+cy[zt1][zt2][2];
dx[3]=dx[3]+cx[zt1][zt2][3];dy[3]=dy[3]+cy[zt1][zt2][3];
}
jiance() /*检测旋转或移动能否进行的函数,能则j=1,不能j=0*/
{ j=1;
for(ji=0;ji<4;ji++)
{ x=dx[ji];y=dy[ji];
if(str[x][y]!=' ') j=0;
}
c=bioskey(1);
if(c!=0) c=bioskey(0);
}
main()
{ int dotx[4],doty[4],score; /*dotx[]doty[]表示一个方块个点的坐标*/
int ddx,ddy;
int rzt1,rzt2,i,u,t=1;
int a[5],b[11],o,p,an,bn;
int rotx[4],roty[4],spd=0;
begin: system("cls"); /*游戏初始化阶段*/
printf("londing...");
for(i=0;i<12;i++) /*变量初始阶段*/
{ for(u=0;u<19;u++)
str[i][u]=' ';
}
for(i=0;i<12;i++)
for(u=0;u<19;u++)
cx[1][1][0]=1;cx[1][1][2]=-1;cx[1][1][3]=-2; /*对旋转变量进行赋值*/
cy[1][1][0]=1;cy[1][1][2]=-1;cy[1][1][3]=-2;
cx[1][2][0]=-1;cx[1][2][2]=1;cx[1][2][3]=2;
cy[1][2][0]=-1;cy[1][2][2]=1;cy[1][2][3]=2;
cx[2][1][0]=0;cx[2][1][2]=0;cx[2][1][3]=0;
cy[2][1][0]=0;cy[2][1][2]=0;cy[2][1][3]=0;
cx[3][1][0]=1;cx[3][1][2]=-1;cx[3][1][3]=1;
cy[3][1][0]=-1;cy[3][1][2]=1;cy[3][1][3]=1;
cx[3][2][0]=1;cx[3][2][2]=-1;cx[3][2][3]=-1;
cy[3][2][0]=1;cy[3][2][2]=-1;cy[3][2][3]=1;
cx[3][3][0]=-1;cx[3][3][2]=1;cx[3][3][3]=-1;
cy[3][3][0]=1;cy[3][3][2]=-1;cy[3][3][3]=-1;
cx[3][4][0]=-1;cx[3][4][2]=1;cx[3][4][3]=1;
cy[3][4][0]=-1;cy[3][4][2]=1;cy[3][4][3]=-1;
cx[4][1][0]=-1;cx[4][1][2]=1;cx[4][1][3]=2;
cy[4][1][0]=1;cy[4][1][2]=1;cy[4][1][3]=0;
cx[4][2][0]=1;cx[4][2][2]=-1;cx[4][2][3]=-2;
cy[4][2][0]=-1;cy[4][2][2]=-1;cy[4][2][3]=0;
cx[5][1][0]=1;cx[5][1][2]=1;cx[5][1][3]=0;
cy[5][1][0]=-1;cy[5][1][2]=1;cy[5][1][3]=2;
cx[5][2][0]=-1;cx[5][2][2]=-1;cx[5][2][3]=0;
cy[5][2][0]=1;cy[5][2][2]=-1;cy[5][2][3]=-2;
cx[6][1][0]=1;cx[6][1][2]=-1;cx[6][1][3]=0;
cy[6][1][0]=-1;cy[6][1][2]=1;cy[6][1][3]=2;
cx[6][2][0]=1;cx[6][2][2]=-1;cx[6][2][3]=-2;
cy[6][2][0]=1;cy[6][2][2]=-1;cy[6][2][3]=0;
cx[6][3][0]=-1;cx[6][3][2]=1;cx[6][3][3]=0;
cy[6][3][0]=1;cy[6][3][2]=-1;cy[6][3][3]=-2;
cx[6][4][0]=-1;cx[6][4][2]=1;cx[6][4][3]=2;
cy[6][4][0]=-1;cy[6][4][2]=1;cy[6][4][3]=0;
cx[7][1][0]=-1;cx[7][1][2]=1;cx[7][1][3]=2;
cy[7][1][0]=1;cy[7][1][2]=-1;cy[7][1][3]=0;
cx[7][2][0]=-1;cx[7][2][2]=1;cx[7][2][3]=0;
cy[7][2][0]=-1;cy[7][2][2]=1;cy[7][2][3]=2;
cx[7][3][0]=1;cx[7][3][2]=-1;cx[7][3][3]=-2;
cy[7][3][0]=-1;cy[7][3][2]=1;cy[7][3][3]=0;
cx[7][4][0]=1;cx[7][4][2]=-1;cx[7][4][3]=0;
cy[7][4][0]=1;cy[7][4][2]=-1;cy[7][4][3]=-2;
srand(time(0)); /*对随机数函数rand()进行初始化*/
zt1=rand()%7+1; /*生成第一、二个方块*/
if(zt1==2) zt2=1;
if(zt1==1||zt1==4||zt1==5) zt2=rand()%2+1;
if(zt1==3||zt1==6||zt1==7) zt2=rand()%4+1;
rzt1=rand()%7+1;
if(rzt1==2) rzt2=1;
if(rzt1==1||rzt1==4||rzt1==5) rzt2=rand()%2+1;
if(rzt1==3||rzt1==6||rzt1==7) rzt2=rand()%4+1;
score=0;
for(o=1;o<11;o++) b[o]=0;
switch(zt1*10+zt2)
/*zt1和zt2分别代表方块的种类和状态,这步是根据这两个变量确定方块的四个点的坐标*/
{ case 11: dotx[0]=4;dotx[1]=5;dotx[2]=6;dotx[3]=7;
doty[0]=2;doty[1]=2;doty[2]=2;doty[3]=2;
break;
case 12: dotx[0]=5;dotx[1]=5;dotx[2]=5;dotx[3]=5;
doty[0]=4;doty[1]=3;doty[2]=2;doty[3]=1;
break;
case 21: dotx[0]=5;dotx[1]=6;dotx[2]=5;dotx[3]=6;
doty[0]=1;doty[1]=1;doty[2]=2;doty[3]=2;
break;
case 31: dotx[0]=4;dotx[1]=5;dotx[2]=6;dotx[3]=5;
doty[0]=2;doty[1]=2;doty[2]=2;doty[3]=1;
break;
case 32: dotx[0]=5;dotx[1]=5;dotx[2]=5;dotx[3]=6;
doty[0]=1;doty[1]=2;doty[2]=3;doty[3]=2;
break;
case 33: dotx[0]=6;dotx[1]=5;dotx[2]=4;dotx[3]=5;
doty[0]=1;doty[1]=1;doty[2]=1;doty[3]=2;
break;
case 34: dotx[0]=6;dotx[1]=6;dotx[2]=6;dotx[3]=5;
doty[0]=3;doty[1]=2;doty[2]=1;doty[3]=2;
break;
case 41: dotx[0]=6;dotx[1]=5;dotx[2]=5;dotx[3]=4;
doty[0]=2;doty[1]=2;doty[2]=1;doty[3]=1;
break;
case 42: dotx[0]=5;dotx[1]=5;dotx[2]=6;dotx[3]=6;
doty[0]=3;doty[1]=2;doty[2]=2;doty[3]=1;
break;
case 51: dotx[0]=4;dotx[1]=5;dotx[2]=5;dotx[3]=6;
doty[0]=2;doty[1]=2;doty[2]=1;doty[3]=1;
break;
case 52: dotx[0]=5;dotx[1]=5;dotx[2]=6;dotx[3]=6;
doty[0]=1;doty[1]=2;doty[2]=2;doty[3]=3;
break;
case 61: dotx[0]=4;dotx[1]=5;dotx[2]=6;dotx[3]=6;
doty[0]=2;doty[1]=2;doty[2]=2;doty[3]=1;
break;
case 62: dotx[0]=5;dotx[1]=5;dotx[2]=5;dotx[3]=6;
doty[0]=1;doty[1]=2;doty[2]=3;doty[3]=3;
break;
case 63: dotx[0]=6;dotx[1]=5;dotx[2]=4;dotx[3]=4;
doty[0]=1;doty[1]=1;doty[2]=1;doty[3]=2;
break;
case 64: dotx[0]=6;dotx[1]=6;dotx[2]=6;dotx[3]=5;
doty[0]=3;doty[1]=2;doty[2]=1;doty[3]=1;
break;
case 71: dotx[0]=6;dotx[1]=5;dotx[2]=4;dotx[3]=4;
doty[0]=2;doty[1]=2;doty[2]=2;doty[3]=1;
break;
case 72: dotx[0]=5;dotx[1]=5;dotx[2]=5;dotx[3]=6;
doty[0]=3;doty[1]=2;doty[2]=1;doty[3]=1;
break;
case 73: dotx[0]=4;dotx[1]=5;dotx[2]=6;dotx[3]=6;
doty[0]=1;doty[1]=1;doty[2]=1;doty[3]=2;
break;
case 74: dotx[0]=6;dotx[1]=6;dotx[2]=6;dotx[3]=5;
doty[0]=1;doty[1]=2;doty[2]=3;doty[3]=3;
break;
}
switch(rzt1*10+rzt2) /*确定第二个方块各个点的坐标*/
{ case 11: rotx[0]=4;rotx[1]=5;rotx[2]=6;rotx[3]=7;
roty[0]=2;roty[1]=2;roty[2]=2;roty[3]=2;
break;
case 12: rotx[0]=5;rotx[1]=5;rotx[2]=5;rotx[3]=5;
roty[0]=4;roty[1]=3;roty[2]=2;roty[3]=1;
break;
case 21: rotx[0]=5;rotx[1]=6;rotx[2]=5;rotx[3]=6;
roty[0]=1;roty[1]=1;roty[2]=2;roty[3]=2;
break;
case 31: rotx[0]=4;rotx[1]=5;rotx[2]=6;rotx[3]=5;
roty[0]=2;roty[1]=2;roty[2]=2;roty[3]=1;
break;
case 32: rotx[0]=5;rotx[1]=5;rotx[2]=5;rotx[3]=6;
roty[0]=1;roty[1]=2;roty[2]=3;roty[3]=2;
break;
case 33: rotx[0]=6;rotx[1]=5;rotx[2]=4;rotx[3]=5;
roty[0]=1;roty[1]=1;roty[2]=1;roty[3]=2;
break;
case 34: rotx[0]=6;rotx[1]=6;rotx[2]=6;rotx[3]=5;
roty[0]=3;roty[1]=2;roty[2]=1;roty[3]=2;
break;
case 41: rotx[0]=6;rotx[1]=5;rotx[2]=5;rotx[3]=4;
roty[0]=2;roty[1]=2;roty[2]=1;roty[3]=1;
break;
case 42: rotx[0]=5;rotx[1]=5;rotx[2]=6;rotx[3]=6;
roty[0]=3;roty[1]=2;roty[2]=2;roty[3]=1;
break;
case 51: rotx[0]=4;rotx[1]=5;rotx[2]=5;rotx[3]=6;
roty[0]=2;roty[1]=2;roty[2]=1;roty[3]=1;
break;
case 52: rotx[0]=5;rotx[1]=5;rotx[2]=6;rotx[3]=6;
roty[0]=1;roty[1]=2;roty[2]=2;roty[3]=3;
break;
case 61: rotx[0]=4;rotx[1]=5;rotx[2]=6;rotx[3]=6;
roty[0]=2;roty[1]=2;roty[2]=2;roty[3]=1;
break;
case 62: rotx[0]=5;rotx[1]=5;rotx[2]=5;rotx[3]=6;
roty[0]=1;roty[1]=2;roty[2]=3;roty[3]=3;
break;
case 63: rotx[0]=6;rotx[1]=5;rotx[2]=4;rotx[3]=4;
roty[0]=1;roty[1]=1;roty[2]=1;roty[3]=2;
break;
case 64: rotx[0]=6;rotx[1]=6;rotx[2]=6;rotx[3]=5;
roty[0]=3;roty[1]=2;roty[2]=1;roty[3]=1;
break;
case 71: rotx[0]=6;rotx[1]=5;rotx[2]=4;rotx[3]=4;
roty[0]=2;roty[1]=2;roty[2]=2;roty[3]=1;
break;
case 72: rotx[0]=5;rotx[1]=5;rotx[2]=5;rotx[3]=6;
roty[0]=3;roty[1]=2;roty[2]=1;roty[3]=1;
break;
case 73: rotx[0]=4;rotx[1]=5;rotx[2]=6;rotx[3]=6;
roty[0]=1;roty[1]=1;roty[2]=1;roty[3]=2;
break;
case 74: rotx[0]=6;rotx[1]=6;rotx[2]=6;rotx[3]=5;
roty[0]=1;roty[1]=2;roty[2]=3;roty[3]=3;
break;
}
system("cls"); /*显示初始阶段*/
printf("\n\n\n"); /*游戏区域下移3*/
for(u=0;u<19;u++)
{ for(i=0;i<12;i++)
printf("%c",str[i][u]);
printf("\n");
}
gotoxy(16,5);printf("--------");
gotoxy(16,12);printf("--------");
for(i=6;i<12;i++)
for(i=6;i<12;i++)
for(i=0;i<4;i++)
{ gotoxy(rotx[i]+14,roty[i]+6);printf("%c",15);
}
begin2: delay(26000); /*游戏开始,延迟1*/
speed: delay(10000); /*加速,延迟2*/
gotoxy(16,14);printf("Score:%d",score);
for(i=0;i<4;i++)
{ gotoxy(dotx[i]+1,doty[i]+4);printf(" ");
ddx=dotx[i];ddy=doty[i];
str[ddx][ddy]=' ';
}
an=an-0.4; /*表示按键是否一直按着,用于方块落地后的移动*/
c=bioskey(1); /*按键处理部分*/
/*bioskey(1)是用来检测是否按下案件的函数*/
if(c!=0)
{ c=bioskey(0);
if(c==8292||c==19712)
{ for(i=0;i<4;i++)
jiance();
for(i=0;i<4;i++)
dotx[i]=(j)? dx[i] : dotx[i];
an=(j||bn);
}
if(c==7777||c==19200)
{ for(i=0;i<4;i++)
jiance();
for(i=0;i<4;i++)
dotx[i]=(j)? dx[i] : dotx[i];
an=(j||bn);
}
if(c==6512) /*暂停的处理*/
{ while(1)
{ c=bioskey(0);
if(c==6512) break;
}
goto begin3;
}
if(c==8051||c==20480) spd=1; /*加速(spd==1表示加速状态)*/
if(c==4471||c==18432) /*旋转的处理*/
{ for(i=0;i<4;i++)
/*dx[]与dy[]是临时变量,这样一旦判断为不能旋转,就可方便的回复旋转前的坐标*/
cir(); /*旋转*/
jiance(); /*判断旋转是否能进行*/
for(i=0;i<4;i++)
/*根据jiance()得到的j值,判断是对dotx[]与doty[]赋旋转后的还是旋转前的值*/
if(j==1) /*如果旋转可已经行,就对原方块的状态进行改变*/
{ an=(j||bn);zt2=zt2+1;
if(zt2>maxzt[zt1]) zt2=1;
goto overif; /*结束旋转的处理*/
}
for(i=0;i<4;i++)
/*如果不能旋转,再判断坐标右移一个后能否旋转*/
cir();
jiance();
for(i=0;i<4;i++)
if(j==1)
{ an=(j||bn);zt2=zt2+1;
if(zt2>maxzt[zt1]) zt2=1;
goto overif;
}
if(dotx[2]==1) goto overif;
for(i=0;i<4;i++)
/*判断坐标左移一个后能否旋转*/
cir();
jiance();
for(i=0;i<4;i++)
if(j==1)
{ an=(j||bn);zt2=zt2+1;
if(zt2>maxzt[zt1]) zt2=1;
goto overif;
}
overif: ;
}
}
begin3: for(i=0;i<4;i++) /*方块下移的处理*/
jiance();
bn=j;
for(i=0;i<4;i++)
doty[i]=(j)? dy[i] : doty[i];
for(i=0;i<4;i++)
{ gotoxy(dotx[i]+1,doty[i]+4);printf("%c",15);
ddx=dotx[i];ddy=doty[i];
str[ddx][ddy]=15;
}
if(j==1&&spd==1)
if(j==1||an>0) goto begin2;
for(u=17;u>0;u--) /*方块停止下移(方块移动到底了)的处理*/
{ for(i=1;i<11;i++) /*判断每一行是否排满*/
if(str[i][u]==15) b[i]=1;
if (b[1]+b[2]+b[3]+b[4]+b[5]+b[6]+b[7]+b[8]+b[9]+b[10]<10)
{ for(o=1;o<11;o++) b[o]=0;
continue;
}
for(o=1;o<11;o++) b[o]=0;
a[t]=u;t++;
}
score+=(t)*(t-1)/2;
for(i=1;i<11;i++)
if(str[i][1]==15) b[i]=1;
if (b[1]+b[2]+b[3]+b[4]+b[5]+b[6]+b[7]+b[8]+b[9]+b[10]>0 &&t==1) goto over;
for(o=1;o<11;o++) b[o]=0;
if(t==1) goto ran;
switch(t) /*消除方块的处理,t=要消除的函数+1*/
/*将要消除的行中,最上面一行,上面的方格整体下移,下面的case 4,3,2类似*/
case 4: for(u=a[3];u>1;u--)
case 3: for(u=a[2];u>1;u--)
case 2: for(u=a[1];u>1;u--)
}
t=1;
for(u=1;u<18;u++)
{ for(i=1;i<11;i++)
{ gotoxy(i+1,u+4);
printf("%c",str[i][u]);
}
}
ran: zt1=rzt1;zt2=rzt2;rzt1=rand()%7+1; /*生成下两个方块*/
if(rzt1==2) rzt2=1;
if(rzt1==1||rzt1==4||rzt1==5) rzt2=rand()%2+1;
if(rzt1==3||rzt1==6||rzt1==7) rzt2=rand()%4+1;
for(i=0;i<4;i++)
{ dotx[i]=rotx[i];doty[i]=roty[i];
gotoxy(dotx[i]+1,doty[i]+4);printf("%c",15);
}
switch(rzt1*10+rzt2)
{ case 11: rotx[0]=4;rotx[1]=5;rotx[2]=6;rotx[3]=7;
roty[0]=2;roty[1]=2;roty[2]=2;roty[3]=2;
break;
case 12: rotx[0]=5;rotx[1]=5;rotx[2]=5;rotx[3]=5;
roty[0]=4;roty[1]=3;roty[2]=2;roty[3]=1;
break;
case 21: rotx[0]=5;rotx[1]=6;rotx[2]=5;rotx[3]=6;
roty[0]=1;roty[1]=1;roty[2]=2;roty[3]=2;
break;
case 31: rotx[0]=4;rotx[1]=5;rotx[2]=6;rotx[3]=5;
roty[0]=2;roty[1]=2;roty[2]=2;roty[3]=1;
break;
case 32: rotx[0]=5;rotx[1]=5;rotx[2]=5;rotx[3]=6;
roty[0]=1;roty[1]=2;roty[2]=3;roty[3]=2;
break;
case 33: rotx[0]=6;rotx[1]=5;rotx[2]=4;rotx[3]=5;
roty[0]=1;roty[1]=1;roty[2]=1;roty[3]=2;
break;
case 34: rotx[0]=6;rotx[1]=6;rotx[2]=6;rotx[3]=5;
roty[0]=3;roty[1]=2;roty[2]=1;roty[3]=2;
break;
case 41: rotx[0]=6;rotx[1]=5;rotx[2]=5;rotx[3]=4;
roty[0]=2;roty[1]=2;roty[2]=1;roty[3]=1;
break;
case 42: rotx[0]=5;rotx[1]=5;rotx[2]=6;rotx[3]=6;
roty[0]=3;roty[1]=2;roty[2]=2;roty[3]=1;
break;
case 51: rotx[0]=4;rotx[1]=5;rotx[2]=5;rotx[3]=6;
roty[0]=2;roty[1]=2;roty[2]=1;roty[3]=1;
break;
case 52: rotx[0]=5;rotx[1]=5;rotx[2]=6;rotx[3]=6;
roty[0]=1;roty[1]=2;roty[2]=2;roty[3]=3;
break;
case 61: rotx[0]=4;rotx[1]=5;rotx[2]=6;rotx[3]=6;
roty[0]=2;roty[1]=2;roty[2]=2;roty[3]=1;
break;
case 62: rotx[0]=5;rotx[1]=5;rotx[2]=5;rotx[3]=6;
roty[0]=1;roty[1]=2;roty[2]=3;roty[3]=3;
break;
case 63: rotx[0]=6;rotx[1]=5;rotx[2]=4;rotx[3]=4;
roty[0]=1;roty[1]=1;roty[2]=1;roty[3]=2;
break;
case 64: rotx[0]=6;rotx[1]=6;rotx[2]=6;rotx[3]=5;
roty[0]=3;roty[1]=2;roty[2]=1;roty[3]=1;
break;
case 71: rotx[0]=6;rotx[1]=5;rotx[2]=4;rotx[3]=4;
roty[0]=2;roty[1]=2;roty[2]=2;roty[3]=1;
break;
case 72: rotx[0]=5;rotx[1]=5;rotx[2]=5;rotx[3]=6;
roty[0]=3;roty[1]=2;roty[2]=1;roty[3]=1;
break;
case 73: rotx[0]=4;rotx[1]=5;rotx[2]=6;rotx[3]=6;
roty[0]=1;roty[1]=1;roty[2]=1;roty[3]=2;
break;
case 74: rotx[0]=6;rotx[1]=6;rotx[2]=6;rotx[3]=5;
roty[0]=1;roty[1]=2;roty[2]=3;roty[3]=3;
break;
}
for(i=6;i<12;i++) /*刷新一下用来显示下一个方块的那个区域*/
for(i=6;i<12;i++)
for(u=17;u<23;u++)
for(i=0;i<4;i++)
c=bioskey(1);an=0;
if(c!=0) c=bioskey(0);
if(spd==1)
goto begin2;
over: system("cls");
gotoxy(36,11);printf("GAME OVER");
bioskey(0);
system("cls");
printf("Your score is %d\n\n",score);
printf("Press 'Q' to exit\nIf you want to play again,please press other keys.");
score=0;
c=bioskey(0);
if(c!=4209) goto begin;
}
另外,团IDC网上有许多产品团购,便宜有口碑
Ⅷ 一个简单的c语言写的俄罗斯方块程序
1、考虑怎么存储俄罗斯方块
俄罗斯方块的形状一共有19种类型,如果拿数组来表示的话,可能会比较会浪费空间(网上有很多实现代码)
考虑到每种方块形状的范围是4 *4的小方块,用 字模点阵的方式来存储,即设置一个4行4列的数组,元素置1即代表这个位置有小
方块,元素置0即代表这个位置无小方块,这个整个的4*4的数组组成俄罗斯方块的形状。
1000
1000
1100
0000
上述4*4来表示L形状的方块。
4*4 =16 bit 正好为short类型,所以每一个方块可以用一个short类型的数据来表示。
我们把俄罗斯方块点阵的数位存在rockArray中,我们可以事先把这19种方块的字模点阵自己转化成十六进制,然后在rockArray数组的初始化时赋值进去。
但是这种方式扩展性不好,每当有一种新方块时需要改动,
所以可以写一个配置文件来表示19种方块。(RockShape.ini)
@###@###@@######1234
从配置文件中读取方块的类型的代码在(Init.h的ReadRock函数中)在下面3中解释下代码如何实现
2如何画出方块
可以使用EasyX库来画出简单的图形,
EasyX库是在VC下实现TC的简单绘图功能的一个库,这个库很容易学会(直接 网络EasyX库,里面有详细的教程)
那么如何画出方块,方块已经存储到一个short类型中了
从short中读取出,可以用一个掩码mask = 1来与short的每个bit位相与,结果为1,则画出一个小方块;
函数声明:
void DisplayRock(int rockIdx, RockLocation_t* LocatePtr, bool displayed)1
参数1:表示在数组中的下标,取出short类型的方块表示数据
参数2:表示当前坐标,即画出方块的左上角的坐标x,y
参数3:true表示画出该方块,false 表示擦除该方块。
//方块在图形窗口中的位置(即定位4*4大块的左上角坐标) typedef struct LOCATE
{ int left; int top;
} RockLocation_t;123456
3如何实现同一种类型方块的翻转,
在按‘↑’时应该翻转同一种类型的方块,
比如下面的横杆和竖杆
@###@###@###@###@@@@############****1234567891011
可以假想成静态循环链表来实现这种方式
使同一种类型的方块循环起来,
用一个struct结构来表示一种方块
typedef struct ROCK
{ //用来表示方块的形状(每一个字节是8位,用每4位表示方块中的一行)
unsigned short rockShapeBits; int nextRockIndex; //下一个方块,在数组中的下标 } RockType;123456
定义一个RockType类型的数组来存储19种方块
RockType RockArray[19] = { (0, 0) };
当我们按“↑”时,把传入画方块函数DrawRock中的rockIndex变为当前方块结构体中的nextRockIndex即可。
简单解释下ReadRock函数的实现:当读取到空行的时候表示 一种方块已经读取完毕,当读取到****行时 表示同一种类型的方块读取完毕,具体看代码实现,代码中具体的注释
4、主要游戏实现的逻辑
贴一个预览图吧
注:上述预览图的游戏控制区和游戏显示区在Draw.h的DrawGameWindow()函数实现的
(1)在初始位置画出方块,在预览区画出下一次的方块
(2)方块有两种行为:响应键盘命令UserHitKeyBoard(),自由下落
如果敲击键盘了(w ,a ,s ,d, )空格表示暂停,如果在规定时间内没有敲击键盘的话,方块自由下落一个单位
if (kbhit()) //如果敲击键盘了 就处理按键
{
userHit = getch();
UserHitKeyBoard(userHit, &curRockIndex, &curRockLocation);
} //没有 就自动下移一个单位 :不能用else,因为可能按键不是上下左右
DWORD newtime = GetTickCount(); if (newtime - oldtime >= (unsigned int)(300) && moveAbled == TRUE)
{
oldtime = newtime;
DisplayRock(curRockIndex, &curRockLocation, false);
curRockLocation.top += ROCK_SQUARE_WIDTH; //下落一格
}1234567891011121314
(3)当方块落地(即不能下移了)时,判断是否满行,如果满行则消除,然后再判断游戏是否结束,游戏结束的话,直接退出游戏
判断满行:FullLine()函数,从最底下的一行开始判断,直到遇到一行空行,
while (count != xROCK_SQUARE_NUM ) //遇到空行 14
{
linefull = true; count = 0; for (int i = 1; i <= xROCK_SQUARE_NUM; ++i)
{ if (game_board[idx][i] == 0)
{
linefull = false; count++;
}
} if (linefull) //满行,消除当前行,更新分数
{
DelCurLine(idx);//消除满行
game_socres += 3;
UpdateSocres(game_socres);
idx++;//因为下面要减1
}
idx--;
}
(4)消除满行
将要删除的满行擦除:即将方块化成与背景色相同的,该代码为黑色
然后将上面的一行向下移,移一行删除一行,直到遇到空行
具体看代码的具体实现 game.h
void DelCurLine(int rowIdx)
(4)判断方块是否能移动
在game.h中实现
bool MoveAble(int rockIndex, RockLocation_t* currentLocatePtr, int f_direction)1
**比较当前位置的坐标(左上角)开始,能否放下rockIndex的方块。
注:f_direction为”↑”的话,则传入的rockIndex为下一个方块**
如果不能移动的话,给游戏game_board设置标记表示该位置被占有
//全局变量-游戏板的状态描述(即表示当前界面哪些位置有方块) //0表示没有,1表示有(多加了两行和两列,形成一个围墙,便于判断方块是否能够移动) int game_board[yROCK_SQUARE_NUM + 2][xROCK_SQUARE_NUM + 2] = { 0 };123
实现过程遇到的一些问题
(1)在快速下落的时候,可能方块会掉出围墙的范围内,
快速下落是使方块每次下落2个单位距离。
在判断不能下落时,使当前坐标的top即y减去一个单位的距离
(2)遇到多行满行时消除不了,
在判断满行时,循环找出满行,找出一个满行,就消除一行,然后继续判断是否满行,直到遇到空行
Ⅸ 俄罗斯方块的c语言源代码 api实现
TC下面的
/************************************
* Desc: 俄罗斯方块游戏
* By: hoodlum1980
* Email: [email protected]
* Date: 2008.03.12 22:30
************************************/
#include <stdio.h>
#include <bios.h>
#include <dos.h>
#include <graphics.h>
#include <string.h>
#include <stdlib.h>
#define true 1
#define false 0
#define BoardWidth 12
#define BoardHeight 23
#define _INNER_HELPER /*inner helper method */
/*Scan Codes Define*/
enum KEYCODES
{
K_ESC =0x011b,
K_UP =0x4800, /* upward arrow */
K_LEFT =0x4b00,
K_DOWN =0x5000,
K_RIGHT =0x4d00,
K_SPACE =0x3920,
K_P =0x1970
};
/* the data structure of the block */
typedef struct tagBlock
{
char c[4][4]; /* cell fill info array, 0-empty, 1-filled */
int x; /* block position cx [ 0,BoardWidht -1] */
int y; /* block position cy [-4,BoardHeight-1] */
char color; /* block color */
char size; /* block max size in width or height */
char name; /* block name (the block's shape) */
} Block;
/* game's global info */
int FrameTime= 1300;
int CellSize= 18;
int BoardLeft= 30;
int BoardTop= 30;
/* next block grid */
int NBBoardLeft= 300;
int NBBoardTop= 30;
int NBCellSize= 10;
/* score board position */
int ScoreBoardLeft= 300;
int ScoreBoardTop=100;
int ScoreBoardWidth=200;
int ScoreBoardHeight=35;
int ScoreColor=LIGHTCYAN;
/* infor text postion */
int InfoLeft=300;
int InfoTop=200;
int InfoColor=YELLOW;
int BorderColor=DARKGRAY;
int BkGndColor=BLACK;
int GameRunning=true;
int TopLine=BoardHeight-1; /* top empty line */
int TotalScore=100;
char info_score[20];
char info_help[255];
char info_common[255];
/* our board, Board[x][y][0]-isFilled, Board[x][y][1]-fillColor */
unsigned char Board[BoardWidth][BoardHeight][2];
char BufferCells[4][4]; /* used to judge if can rotate block */
Block curBlock; /* current moving block */
Block nextBlock; /* next Block to appear */
/* function list */
int GetKeyCode();
int CanMove(int dx,int dy);
int CanRotate();
int RotateBlock(Block *block);
int MoveBlock(Block *block,int dx,int dy);
void DrawBlock(Block *block,int,int,int);
void EraseBlock(Block *block,int,int,int);
void DisplayScore();
void DisplayInfo(char* text);
void GenerateBlock(Block *block);
void NextBlock();
void InitGame();
int PauseGame();
void QuitGame();
/*Get Key Code */
int _INNER_HELPER GetKeyCode()
{
int key=0;
if(bioskey(1))
{
key=bioskey(0);
}
return key;
}
/* display text! */
void _INNER_HELPER DisplayInfo(char *text)
{
setcolor(BkGndColor);
outtextxy(InfoLeft,InfoTop,info_common);
strcpy(info_common,text);
setcolor(InfoColor);
outtextxy(InfoLeft,InfoTop,info_common);
}
/* create a new block by key number,
* the block anchor to the top-left corner of 4*4 cells
*/
void _INNER_HELPER GenerateBlock(Block *block)
{
int key=(random(13)*random(17)+random(1000)+random(3000))%7;
block->size=3;/* because most blocks' size=3 */
memset(block->c,0,16);
switch(key)
{
case 0:
block->name='T';
block->color=RED;
block->c[1][0]=1;
block->c[1][1]=1, block->c[2][1]=1;
block->c[1][2]=1;
break;
case 1:
block->name='L';
block->color=YELLOW;
block->c[1][0]=1;
block->c[1][1]=1;
block->c[1][2]=1, block->c[2][2]=1;
break;
case 2:
block->name='J';
block->color=LIGHTGRAY;
block->c[1][0]=1;
block->c[1][1]=1;
block->c[1][2]=1, block->c[0][2]=1;
break;
case 3:
block->name='z';
block->color=CYAN;
block->c[0][0]=1, block->c[1][0]=1;
block->c[1][1]=1, block->c[2][1]=1;
break;
case 4:
block->name='5';
block->color=LIGHTBLUE;
block->c[1][0]=1, block->c[2][0]=1;
block->c[0][1]=1, block->c[1][1]=1;
break;
case 5:
block->name='o';
block->color=BLUE;
block->size=2;
block->c[0][0]=1, block->c[1][0]=1;
block->c[0][1]=1, block->c[1][1]=1;
break;
case 6:
block->name='I';
block->color=GREEN;
block->size=4;
block->c[1][0]=1;
block->c[1][1]=1;
block->c[1][2]=1;
block->c[1][3]=1;
break;
}
}
/* get next block! */
void NextBlock()
{
/* the nextBlock to curBlock */
curBlock.size=nextBlock.size;
curBlock.color=nextBlock.color;
curBlock.x=(BoardWidth-4)/2;
curBlock.y=-curBlock.size;
memcpy(curBlock.c,nextBlock.c,16);
/* generate nextBlock and show it */
EraseBlock(&nextBlock,NBBoardLeft,NBBoardTop,NBCellSize);
GenerateBlock(&nextBlock);
nextBlock.x=1,nextBlock.y=0;
DrawBlock(&nextBlock,NBBoardLeft,NBBoardTop,NBCellSize);
}
/* rotate the block, update the block struct data */
int _INNER_HELPER RotateCells(char c[4][4],char blockSize)
{
char temp,i,j;
switch(blockSize)
{
case 3:
temp=c[0][0];
c[0][0]=c[2][0], c[2][0]=c[2][2], c[2][2]=c[0][2], c[0][2]=temp;
temp=c[0][1];
c[0][1]=c[1][0], c[1][0]=c[2][1], c[2][1]=c[1][2], c[1][2]=temp;
break;
case 4: /* only 'I' block arived here! */
c[1][0]=1-c[1][0], c[1][2]=1-c[1][2], c[1][3]=1-c[1][3];
c[0][1]=1-c[0][1], c[2][1]=1-c[2][1], c[3][1]=1-c[3][1];
break;
}
}
/* judge if the block can move toward the direction */
int CanMove(int dx,int dy)
{
int i,j,tempX,tempY;
for(i=0;i<curBlock.size;i++)
{
for(j=0;j<curBlock.size;j++)
{
if(curBlock.c[i][j])
{
/* cannot move leftward or rightward */
tempX = curBlock.x + i + dx;
if(tempX<0 || tempX>(BoardWidth-1)) return false; /* make sure x is valid! */
/* cannot move downward */
tempY = curBlock.y + j + dy;
if(tempY>(BoardHeight-1)) return false; /* y is only checked lower bound, maybe negative!!!! */
/* the cell already filled, we must check Y's upper bound before check cell ! */
if(tempY>=0 && Board[tempX][tempY][0]) return false;
}
}
}
return true;
}
/* judge if the block can rotate */
int CanRotate()
{
int i,j,tempX,tempY;
/* update buffer */
memcpy(BufferCells, curBlock.c, 16);
RotateCells(BufferCells,curBlock.size);
for(i=0;i<curBlock.size;i++)
{
for(j=0;j<curBlock.size;j++)
{
if(BufferCells[i][j])
{
tempX=curBlock.x+i;
tempY=curBlock.y+j;
if(tempX<0 || tempX>(BoardWidth-1))
return false;
if(tempY>(BoardHeight-1))
return false;
if(tempY>=0 && Board[tempX][tempY][0])
return false;
}
}
}
return true;
}
/* draw the block */
void _INNER_HELPER DrawBlock(Block *block,int bdLeft,int bdTop,int cellSize)
{
int i,j;
setfillstyle(SOLID_FILL,block->color);
for(i=0;i<block->size;i++)
{
for(j=0;j<block->size;j++)
{
if(block->c[i][j] && (block->y+j)>=0)
{
floodfill(
bdLeft+cellSize*(i+block->x)+cellSize/2,
bdTop+cellSize*(j+block->y)+cellSize/2,
BorderColor);
}
}
}
}
/* Rotate the block, if success, return true */
int RotateBlock(Block *block)
{
char temp,i,j;
int b_success;
if(block->size==2)
return true;
if(( b_success=CanRotate()))
{
EraseBlock(block,BoardLeft,BoardTop,CellSize);
memcpy(curBlock.c,BufferCells,16);
DrawBlock(block,BoardLeft,BoardTop,CellSize);
}
return b_success;
}
/* erase a block, only fill the filled cell with background color */
void _INNER_HELPER EraseBlock(Block *block,int bdLeft,int bdTop,int cellSize)
{
int i,j;
setfillstyle(SOLID_FILL,BkGndColor);
for(i=0;i<block->size;i++)
{
for(j=0;j<block->size;j++)
{
if(block->c[i][j] && (block->y+j>=0))
{
floodfill(
bdLeft+cellSize*(i+block->x)+cellSize/2,
bdTop+cellSize*(j+block->y)+cellSize/2,
BorderColor);
}
}
}
}
/* move by the direction if can, donothing if cannot
* return value: true - success, false - cannot move toward this direction
*/
int MoveBlock(Block *block,int dx,int dy)
{
int b_canmove=CanMove(dx,dy);
if(b_canmove)
{
EraseBlock(block,BoardLeft,BoardTop,CellSize);
curBlock.x+=dx;
curBlock.y+=dy;
DrawBlock(block,BoardLeft,BoardTop,CellSize);
}
return b_canmove;
}
/* drop the block to the bottom! */
int DropBlock(Block *block)
{
EraseBlock(block,BoardLeft,BoardTop,CellSize);
while(CanMove(0,1))
{
curBlock.y++;
}
DrawBlock(block,BoardLeft,BoardTop,CellSize);
return 0;/* return value is assign to the block's alive */
}
/* init the graphics mode, draw the board grid */
void InitGame()
{
int i,j,gdriver=DETECT,gmode;
struct time sysTime;
/* draw board cells */
memset(Board,0,BoardWidth*BoardHeight*2);
memset(nextBlock.c,0,16);
strcpy(info_help,"P: Pause Game. --by hoodlum1980");
initgraph(&gdriver,&gmode,"");
setcolor(BorderColor);
for(i=0;i<=BoardWidth;i++)
{
line(BoardLeft+i*CellSize, BoardTop, BoardLeft+i*CellSize, BoardTop+ BoardHeight*CellSize);
}
for(i=0;i<=BoardHeight;i++)
{
line(BoardLeft, BoardTop+i*CellSize, BoardLeft+BoardWidth*CellSize, BoardTop+ i*CellSize);
}
/* draw board outer border rect */
rectangle(BoardLeft-CellSize/4, BoardTop-CellSize/4,
BoardLeft+BoardWidth*CellSize+CellSize/4,
BoardTop+BoardHeight*CellSize+CellSize/4);
/* draw next block grids */
for(i=0;i<=4;i++)
{
line(NBBoardLeft+i*NBCellSize, NBBoardTop, NBBoardLeft+i*NBCellSize, NBBoardTop+4*NBCellSize);
line(NBBoardLeft, NBBoardTop+i*NBCellSize, NBBoardLeft+4*NBCellSize, NBBoardTop+ i*NBCellSize);
}
/* draw score rect */
rectangle(ScoreBoardLeft,ScoreBoardTop,ScoreBoardLeft+ScoreBoardWidth,ScoreBoardTop+ScoreBoardHeight);
DisplayScore();
/* set new seed! */
gettime(&sysTime);
srand(sysTime.ti_hour*3600+sysTime.ti_min*60+sysTime.ti_sec);
GenerateBlock(&nextBlock);
NextBlock(); /* create first block */
setcolor(DARKGRAY);
outtextxy(InfoLeft,InfoTop+20,"Up -rotate Space-drop");
outtextxy(InfoLeft,InfoTop+35,"Left-left Right-right");
outtextxy(InfoLeft,InfoTop+50,"Esc -exit");
DisplayInfo(info_help);
}
/* set the isFilled and fillcolor data to the board */
void _INNER_HELPER FillBoardData()
{
int i,j;
for(i=0;i<curBlock.size;i++)
{
for(j=0;j<curBlock.size;j++)
{
if(curBlock.c[i][j] && (curBlock.y+j)>=0)
{
Board[curBlock.x+i][curBlock.y+j][0]=1;
Board[curBlock.x+i][curBlock.y+j][1]=curBlock.color;
}
}
}
}
/* draw one line of the board */
void _INNER_HELPER PaintBoard()
{
int i,j,fillcolor;
for(j=max((TopLine-4),0);j<BoardHeight;j++)
{
for(i=0;i<BoardWidth;i++)
{
fillcolor=Board[i][j][0]? Board[i][j][1]:BkGndColor;
setfillstyle(SOLID_FILL,fillcolor);
floodfill(BoardLeft+i*CellSize+CellSize/2,BoardTop+j*CellSize+CellSize/2,BorderColor);
}
}
}
/* check if one line if filled full and increase the totalScore! */
void _INNER_HELPER CheckBoard()
{
int i,j,k,score=10,sum=0,topy,lines=0;
/* we find the top empty line! */
j=topy=BoardHeight-1;
do
{
sum=0;
for(i=0;i< BoardWidth; i++)
{
sum+=Board[i][topy][0];
}
topy--;
} while(sum>0 && topy>0);
/* remove the full filled line (max remove lines count = 4) */
do
{
sum=0;
for(i=0;i< BoardWidth; i++)
sum+=Board[i][j][0];
if(sum==BoardWidth)/* we find this line is full filled, remove it! */
{
/* move the cells data down one line */
for(k=j; k > topy;k--)
{
for(i=0;i<BoardWidth;i++)
{
Board[i][k][0]=Board[i][k-1][0];
Board[i][k][1]=Board[i][k-1][1];
}
}
/*make the top line empty! */
for(i=0;i<BoardWidth;i++)
{
Board[i][topy][0]=0;
Board[i][topy][1]=0;
}
topy++; /* move the topline downward one line! */
lines++; /* lines <=4 */
TotalScore+=score;
score*=2; /* adding: 10, 30, 70, 150 */
}
else
j--;
} while(sum>0 && j>topy && lines<4);
/* speed up the game when score is high, minimum is 400 */
FrameTime=max(1200-100*(TotalScore/200), 400);
TopLine=topy;/* update the top line */
/* if no lines remove, only add 1: */
if(lines==0)
TotalScore++;
}
/* display the score */
void _INNER_HELPER DisplayScore()
{
setcolor(BkGndColor);
outtextxy(ScoreBoardLeft+5,ScoreBoardTop+5,info_score);
setcolor(ScoreColor);
sprintf(info_score,"Score: %d",TotalScore);
outtextxy(ScoreBoardLeft+5,ScoreBoardTop+5,info_score);
}
/* we call this function when a block is inactive. */
void UpdateBoard()
{
FillBoardData();
CheckBoard();
PaintBoard();
DisplayScore();
}
/* pause the game, and timer handler stop move down the block! */
int PauseGame()
{
int key=0;
DisplayInfo("Press P to Start or Resume!");
while(key!=K_P && key!=K_ESC)
{
while(!(key=GetKeyCode())){}
}
DisplayInfo(info_help);
return key;
}
/* quit the game and do cleaning work. */
void QuitGame()
{
closegraph();
}
/* the entry point function. */
void main()
{
int i,flag=1,j,key=0,tick=0;
InitGame();
if(PauseGame()==K_ESC)
goto GameOver;
/* wait until a key pressed */
while(key!=K_ESC)
{
/* wait until a key pressed */
while(!(key=GetKeyCode()))
{
tick++;
if(tick>=FrameTime)
{
/* our block has dead! (can't move down), we get next block */
if(!MoveBlock(&curBlock,0,1))
{
UpdateBoard();
NextBlock();
if(!CanMove(0,1))
goto GameOver;
}
tick=0;
}
delay(100);
}
switch(key)
{
case K_LEFT:
MoveBlock(&curBlock,-1,0);
break;
case K_RIGHT:
MoveBlock(&curBlock,1,0);
break;
case K_DOWN:
MoveBlock(&curBlock,0,1);
break;
case K_UP:
RotateBlock(&curBlock);
break;
case K_SPACE:
DropBlock(&curBlock);
break;
case K_P:
PauseGame();
break;
}
}
GameOver:
DisplayInfo("GAME OVER! Press any key to exit!");
getch(); /* wait the user Press any key. */
QuitGame();
}