最近为了复习TC中的图形编程,自己写了一个俄罗斯方块的程序,它能够实现实现一般俄罗斯方块程序的功能,现将源代码贴出来,供大家一起分享,由于本人的水平有限,有什么问题欢迎请大家提出来。而且现在这个程序中方块的下降速度不能改变,谁有好的解决方法请与我联系,我的QQ是:496271185
#include <graphics.h>
#include <time.h>
#define CNT_R 30 /*容器行数*/
#define CNT_C 14 /*容器列数*/
#define CS 10 /*方块的大小*/
#define BX 10 /*容器左上角的x坐标*/
#define BY 10 /*容器左上角的y坐标*/
#define BSR 30*10 /*容器的大小*/
#define BSC 14*10 /*容器的大小*/
#define INIT_X 80 /*方块初始化X坐标*/
#define INIT_Y 10 /*方块初始化Y坐标*/
/*定义要响应的按键*/
#define DOWN 0X5000 /*↓键*/
#define UP 0X4800 /*↑键*/
#define LEFT 0X4B00 /*←键*/
#define RIGHT 0X4D00 /*→键*/
#define ESC 0X11b /*退出键*/
#define LSCORE 100 /*消除一行所得的分数*/
#define SCX 200 /*显示分数的位置,X坐标*/
#define SCY 100 /*显示分数的位置,Y坐标*/
/*定义方块,共有15种*/
int b[][4][4] = {1, 1, 0, 0,
1, 1, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
1, 1, 0, 0,
1, 1, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
1, 1, 0, 0,
1, 1, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
1, 1, 0, 0,
1, 1, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
1, 1, 1, 1,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
1, 0, 0, 0,
1, 0, 0, 0,
1, 0, 0, 0,
1, 0, 0, 0,
1, 1, 1, 1,
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
1, 0, 0, 0,
1, 0, 0, 0,
1, 0, 0, 0,
1, 0, 0, 0,
1, 0, 0, 0,
1, 1, 0, 0,
0, 1, 0, 0,
0, 0, 0, 0,
0, 1, 1, 0,
1, 1, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
1, 0, 0, 0,
1, 1, 0, 0,
0, 1, 0, 0,
0, 0, 0, 0,
0, 1, 1, 0,
1, 1, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 1, 0, 0,
1, 1, 0, 0,
1, 0, 0, 0,
0, 0, 0, 0,
1, 1, 0, 0,
0, 1, 1, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 1, 0, 0,
1, 1, 0, 0,
1, 0, 0, 0,
0, 0, 0, 0,
1, 1, 0, 0,
0, 1, 1, 0,
0, 0, 0, 0,
0, 0, 0, 0,
1, 1, 0, 0,
0, 1, 0, 0,
0, 1, 0, 0,
0, 0, 0, 0,
0, 0, 1, 0,
1, 1, 1, 0,
0, 0, 0, 0,
0, 0, 0, 0,
1, 0, 0, 0,
1, 0, 0, 0,
1, 1, 0, 0,
0, 0, 0, 0,
1, 1, 1, 0,
1, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
1, 1, 0, 0,
1, 0, 0, 0,
1, 0, 0, 0,
0, 0, 0, 0,
1, 1, 1, 0,
0, 0, 1, 0,
0, 0, 0, 0,
0, 0, 0, 0,
0, 1, 0, 0,
0, 1, 0, 0,
1, 1, 0, 0,
0, 0, 0, 0,
1, 0, 0, 0,
1, 1, 1, 0,
0, 0, 0, 0,
0, 0, 0, 0};
int xy[24][2]={2, 2,
2, 2,
2, 2,
2, 2,
4, 1,
1, 4,
4, 1,
1, 4,
2, 3,
3, 2,
2, 3,
3, 2,
2, 3,
3, 2,
2, 3,
3, 2,
2, 3,
3, 2,
2, 3,
3, 2,
2, 3,
3, 2,
2, 3,
3, 2};
int box[CNT_R][CNT_C]; /*定义容器*/
int X=INIT_X, Y=INIT_Y; /*方块的当前位置,全局变量*/
int key; /*保存按键消息,全局变量*/
int k; /*当前的方块代号*/
time_t oldtm, newtm; /*保存时间*/
int count = 0;/*计数器,记录已经消除的行数*/
char score[100];
int ShowCube(int x, int y, int tag);/*已测试*/
int InitBox(); /*已测试*/
int CreatCube();/*已测试*/
int IsOk(int x, int y);/*已测试*/
int InPut();/*已测试*/
int MoveDown();/*已测试*/
int MoveLeft();/*已测试*/
int MoveRight();/*已测试*/
int ChangeUp();/*已测试*/
int Run();/*已测试*/
int ShowBox(); /*已测试*/
int ClearBar(int x, int y, int b[4][4]);/*已测试*/
int Bar(int x, int y, int b[4][4]);/*已测试*/
int TimeIsOk();/*已测试*/
int DelLine();/*消除行*/
int PrintScore();/*显示分数*/
int Sound();/*发声*/
int MsgBox();/*消息框*/
int Help();/*帮助信息*/
/*初始化容器*/
int InitBox()
{
int i, j;
for(i=0; i<CNT_R; ++i)
for(j=0; j<CNT_C; ++j)
box[i][j] = 0;
PrintScore();
Help();
ShowBox();
return 0;
}
/*输出分数*/
int PrintScore()
{
Sound();
setcolor(BLACK);
setfillstyle(1, BLACK);
bar(SCX-5, SCY-5, SCX+100, SCY+15);
setcolor(4);
sprintf(score, "SCORE: %d", count*LSCORE);
outtextxy(SCX, SCY, score);
return 0;
}
int Help()
{
moveto(SCX-5, SCY+20);
outtext("You can press ESC key to exit the game.");
moveto(SCX-5, SCY+40);
outtext("You can press LEFT key to move the cube to the left.");
moveto(SCX-5, SCY+60);
outtext("You can press RIGHT key to move the cube to the right.");
moveto(SCX-5, SCY+80);
outtext("You can press DOWN key to move the cube to the bottom.");
moveto(SCX-5, SCY+100);
outtext("You can press UP key to change the shape of cube.");
return 0;
}
/**检测当前方块是否引发消除行的动作,如果是,则消除响应的行*/
int DelLine()
{
int end, r, c, i, j;
r=(Y-BY)/CS;/*从方块当前所在的行开始检测*/
end = (r+3)<CNT_R ? r+3 : CNT_R-1;/*end指向结束的行*/
for(; r<=end; ++r){ /*控制行*/
for(c=0; c<CNT_C; ++c){/*控制列*/
if(box[r][c]==0) break; /*如果某行中出现了空格,转到下一行的*/
}
if(c>=CNT_C) {/*当前的行应该消除*/
/*将当前行到初始行之间的行向下移动*/
for(i=r-1; i>=0; --i)/*将第i行复制到第i+1行*/
for(j=0; j<CNT_C; ++j)
box[i+1][j]=box[i][j];
for(j=0; j<CNT_C; ++j)
box[0][j]=0; /*消除第一行*/
count++;
PrintScore();
ShowBox();
}
}
return 0;
}
/*产生方块并显示*/
int CreatCube()
{
time_t t = time(0);
srand(t);
k = rand()%24; /*随机产生方块的代号*/
if(IsOk(INIT_X, INIT_Y)){
Bar(INIT_X, INIT_Y, b[k]); /*显示产生的方块*/
oldtm = time(0); /*获得初始时间*/
X = INIT_X;
Y = INIT_Y;
}else {
MsgBox();
getch();
exit(0);
}
return 0;
}
/*消息框*/
int MsgBox()
{
char *msg="GAME OVER!";
setcolor(3);
setfillstyle(1, 3);
bar(120, 140, 520, 340);
setcolor(4);
outtextxy(300, 200, msg);
moveto(270, 220);
sprintf(msg, "Your score is : %d", LSCORE*count);
outtext(msg);
moveto(180, 240);
outtext("Please press any key to EXIT this game!");
return 0;
}
/*判断方块是否能够到达*/
int IsOk(int x, int y)
{
int i,j;
if(x<BX || x>(BX+BSC-CS*xy[k][0])) return -1; /*超出左右边界,该位置不能到达*/
for(i=0; i<xy[k][1]; ++i)
for(j=0; j<xy[k][0]; ++j)
if((box[((y-BY)/CS)+i][((x-BX)/CS)+j]+b[k][i][j])==2 || y>(BX+BSR-CS*xy[k][1])) { /*超出下边界或者与已有方块全部或者部分重叠,不能到
达*/
return 0;
}
return 1; /*该位置可以到达*/
}
/*将当前方块的有用信息写入box*/
int InPut()
{
int i, j;
for(i=0; i<xy[k][1]; ++i)
for(j=0; j<xy[k][0]; ++j)
box[((Y-BY)/CS)+i][((X-BX)/CS)+j] |= b[k][i][j] ; /*对box进行更新*/
return 0;
}
/*方块向下运动*/
int MoveDown()
{
if(IsOk(X, Y+CS)==1){
ClearBar(X, Y, b[k]);
Y+=CS;
Bar(X, Y, b[k]);
}else if(IsOk(X, Y+CS)==0){ /*方块向下运动不了了*/
InPut();/*将b[k]数据写入box*/
ShowBox();
DelLine();/*消除行*/
CreatCube(); /*产生新的方块*/
}
return 0;
}
/*方块向左运动*/
int MoveLeft()
{
if(IsOk(X-CS, Y)==1) {
ClearBar(X, Y, b[k]);
X-=CS;
Bar(X, Y, b[k]);}
return 0;
}
/*方块向右运动*/
int MoveRight()
{
if(IsOk(X+CS, Y)==1) {
ClearBar(X, Y, b[k]);
X+=CS;
Bar(X, Y, b[k]);}
return 0;
}
/*方块变形*/
int ChangeUp()
{
int oldk;
oldk = k;
++k;
k = k%4 ? (k/4)*4+k%4 : k-4;
if(IsOk(X, Y)==1){
ClearBar(X, Y, b[oldk]);
Bar(X, Y, b[k]);
}
else k = oldk;
return 0;
}
/*方块自行向下运动*/
int Run()
{
if(IsOk(X, Y+CS)==1){/*如果下一个位置能够到达*/
ClearBar(X, Y, b[k]);
Y+=CS;
Bar(X, Y, b[k]);
}else if(IsOk(X, Y+CS)==-1||IsOk(X, Y+CS)==0){ /*下一个位置不能到达*/
InPut();/*将b[k]数据写入box*/
ShowBox();/**/
DelLine();/*消除行*/
CreatCube(); /*产生新的方块*/
}
return 0;
}
/*显示小方块*/
int ShowCube(int x, int y, int tag)
{ int color,bkcolor;
if(tag==0) {
color=8;
bkcolor=WHITE;
}else if(tag==1){
color=4;
bkcolor=2;
}
setcolor(bkcolor);
setfillstyle(1, bkcolor);
bar(x, y, x+CS, y+CS);
setcolor(color);
moveto(x, y);
lineto(x+CS, y);
lineto(x+CS, y+CS);
lineto(x, y+CS);
lineto(x, y);
return 0;
}
/*显示容器*/
int ShowBox()
{
int i, j;
int x=BX, y=BY;
for(i=0; i<CNT_R; ++i){
for(j=0; j<CNT_C; ++j){
if(box[i][j]==0) ShowCube(x, y, 0);
else if(box[i][j]==1) ShowCube(x, y, 1);
x+=CS;
}
x=BX;
y+=CS;
}
return 0;
}
/*消除方块*/
int ClearBar(int x, int y, int b[4][4])
{
int i, j;
moveto(x, y);
for(i=0; i<4; ++i)
for(j=0; j<4; ++j){
if(b[i][j] == 0) ;
else if(b[i][j] == 1){
ShowCube(x+CS*j, y+CS*i, 0);
}
}
return 0;
}
/*画方块*/
int Bar(int x, int y, int b[4][4])
{
int i, j;
moveto(x, y);
for(i=0; i<4; ++i)
for(j=0; j<4; ++j){
if(b[i][j] == 0) ;
else if(b[i][j] == 1){
ShowCube(x+CS*j, y+CS*i, 1);
}
}
return 0;
}
int TimeIsOk()
{
newtm = time(0);
if(newtm-oldtm >=1) {
oldtm = newtm;
return 1;
}
else return 0;
}
int Sound()
{
sound(587);
delay(10000);
sound(659);
delay(10000);
sound(698);
delay(10000);
sound(880);
delay(100000);
sound(523);
delay(10000);
sound(980);
delay(100000);
sound(784);
delay(1000);
sound(523);
delay(1000);
nosound();
return 0;
}
int main()
{
int gd = DETECT, gm;
registerbgidriver(EGAVGA_driver);
initgraph(&gd, &gm, "");
InitBox();
while(1){
if(!kbhit()&&TimeIsOk()){
Run();
}else if(kbhit()){
if((key=bioskey(0))!=ESC){
switch(key){
case DOWN: MoveDown();break;
case UP: ChangeUp();break;
case LEFT: MoveLeft();break;
case RIGHT: MoveRight();break;
}
}
else {
MsgBox();
getch();
exit(0);
}
}
}
getch();
closegraph();
return 0;
}