最近爲了複習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;
}