#include #include #include #include #define FrameX 13 //游戏窗口左上角的X轴坐标为13 #define FrameY 3 //游戏窗口左上角的Y轴坐标为3 #define Frame_height 20 //游戏窗口的高度为20 #define Frame_width 18 //游戏窗口的宽度为18 /****全局变量****/ int i,j,Temp,Temp1,Temp2; //Temp,Temp1,Temp2用于记住和转换方块变量的值 int a[80][80]={0}; //标记游戏屏幕的图案:2,1,0 分别表示该位置为游戏边框、方块、无图案;初始化为无图案 int b[4]; //声明俄罗斯方块的结构体 struct Tetris { int x; //中心方块的x轴坐标 int y; //中心方块的y轴坐标 int flag; //标记方块类型的序号 int next; //下一个俄罗斯方块类型的序号 int speed; //俄罗斯方块移动的速度 int number; //产生俄罗斯方块的个数 int score; //游戏的分数 int level; //游戏的等级 } ; HANDLE hOut; //控制台句柄 /****函数声明****/ void HideCursor(); //隐藏光标 int color(int c); //控制文字颜色函数 void gotoxy(int x,int y); //获取屏幕光标位置 void Game(); //游戏界面 void Play(); //开始游戏 void explation(); //操作说明 void rule(); //游戏规则 void Make(struct Tetris *); //制作方块 void Print(struct Tetris *); //打印方块 void Clean(struct Tetris *); //清除痕迹 int If_move(struct Tetris *); //判断是否能移动,1动;0不动 void Shui_Ji(struct Tetris *); //随机产生方块 void Full(struct Tetris *); // 判断方块是否满行 /*隐藏控制台的光标*/ void HideCursor() { CONSOLE_CURSOR_INFO cursor_info = {1, 0}; SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info); } /**控制文字颜色函数 */ int color(int c) { SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),c); return 0; } /*获取屏幕光标位置 */ void gotoxy(int x,int y) { COORD pos; pos.X=x; //横坐标 pos.Y=y; //纵坐标 SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),pos); } /*首页 */ int main() { HideCursor(); /*图案*/ color(11); gotoxy(20,3); printf("俄 罗 斯 方 块"); gotoxy(15,6); printf(" ■"); gotoxy(15,7); printf("■■■"); color(14); gotoxy(26,6); printf("■■"); gotoxy(26,7); printf(" ■■"); color(13); gotoxy(40,5); printf("■"); gotoxy(40,6); printf("■"); gotoxy(40,7); printf("■"); gotoxy(40,8); printf("■"); color(10); gotoxy(50,6); printf("■■"); gotoxy(50,7); printf("■■"); color(12); gotoxy(60,6); printf(" ■"); gotoxy(60,7); printf("■■■"); color(9); gotoxy(75,5); printf("■ ■ ■ ■ ■■■■■") ; gotoxy(75,6); printf("■ ■ ■ ■ ■"); gotoxy(75,7); printf("■■■■■ ■ ■ ■"); gotoxy(75,8); printf("■ ■ ■ ■ ■"); gotoxy(75,9); printf("■ ■ ■■■ ■"); color(3); gotoxy(75,12); printf("湖 南 工 业 大 学"); gotoxy(75,14); printf(" 课 程 设 计 作 业"); color(6); gotoxy(75,16); printf(" 计算机类1806班"); gotoxy(75,17); printf(" 18408000638"); gotoxy(75,18); printf(" 张智宇 "); gotoxy(75,19); printf(" 2018年12月27日"); /*操作框*/ int n; int i,j=1; color(6); for(i=9;i<=20;i++) { for(j=15;j<=65;j++) { gotoxy(j,i); if(i==9||i==20) { printf("="); } else if(j==15||j==64) { printf("||"); } } } /*操作框文字 */ color(12); gotoxy(25,12); printf("1.开始游戏"); gotoxy(45,12); printf("2.按键说明"); gotoxy(25,17); printf("3.游戏规则"); gotoxy(45,17); printf("4.退出"); gotoxy(21,22); color(3); printf("请选择[1 2 3 4]:[ ]\b\b"); scanf("%d",&n); switch(n) { case 1: system("cls"); Game(); Play(); break; case 2: explation(); break; case 3: rule(); break; case 4: break; } return 0; } /*按键说明 */ void explation() { int i,j = 1; system("cls"); color(6); gotoxy(30,3); printf("按 键 说 明"); for (i = 6; i <= 18; i++) { for (j = 12; j <= 70; j++) { gotoxy(j, i); if (i == 6 || i == 18) printf("="); else if (j == 12 || j == 69) printf("||"); } } color(12); gotoxy(16,8); printf("1/通过 ← →方向键来移动方块"); gotoxy(16,10); printf("2/通过 ↑使方块旋转"); gotoxy(16,12); printf("3/通过 ↓加速方块下落"); gotoxy(16,14); printf("4/通过空格键暂停游戏"); gotoxy(16,16); printf("5/通过 Esc 键返回首页"); getch(); //按任意键返回主界面 system("cls"); main(); } /*游戏规则 */ void rule() { int i,j = 1; system("cls"); color(6); gotoxy(30,3); printf("游 戏 规 则"); for (i = 6; i <= 18; i++) { for (j = 12; j <= 70; j++) { gotoxy(j, i); if (i == 6 || i == 18) printf("="); else if (j == 12 || j == 69) printf("||"); } } color(12); gotoxy(16,7); printf("1/不同形状的小方块从屏幕上方落下,玩家通过调整"); gotoxy(16,9); printf(" 方块的位置和方向,使他们在屏幕底部拼出完整的"); gotoxy(16,11); printf(" 一行或几行"); color(14); gotoxy(16,13); printf("2/每消除一行,积分增加100"); color(11); gotoxy(16,15); printf("3/每累计1000分,会提升一个等级"); color(10); gotoxy(16,17); printf("4/提升等级会使方块下落速度加快,游戏难度加大"); getch(); //按任意键返回主界面 system("cls"); main(); } /*游戏界面 */ void Game() { gotoxy(FrameX+Frame_width-7,FrameY-2); color(11); printf("我的俄罗斯方块"); gotoxy(FrameX+2*Frame_width+3,FrameY+7); color(2); printf("***********"); gotoxy(FrameX+2*Frame_width+3,FrameY+6); color(3); printf("下一出现方块:"); gotoxy(FrameX+2*Frame_width+3,FrameY+13); color(2); printf("***********"); gotoxy(FrameX+2*Frame_width+3,FrameY+17); color(14); printf("← →键:移动 ↑键:旋转"); gotoxy(FrameX+2*Frame_width+3,FrameY+19); printf("空格:暂停游戏"); gotoxy(FrameX+2*Frame_width+3,FrameY+15); printf("Esc:返回首页"); color(6); for(i=0;i<=2*Frame_width-2;i+=2) { gotoxy(FrameX+i,FrameY); printf("■"); //打印上横框 } for(i=0;i<=2*Frame_width-2;i+=2) { gotoxy(FrameX+i,FrameY+Frame_height); printf("■"); //打印下横框 a[FrameX+i][FrameY+Frame_height]=2; //标记下横框为游戏边框,防止方块出界 } for(i=0;i<=Frame_height;i++) { gotoxy(FrameX,FrameY+i); printf("■"); //打印左边框 a[FrameX][FrameY+i]=2; //标记左竖框为游戏边框,防止方块出界 } for(i=0;i<=Frame_height;i++) { gotoxy(FrameX+2*Frame_width-2,FrameY+i); printf("■"); //打印右边框 a[FrameX+2*Frame_width-2][FrameY+i]=2; //标记右竖框为游戏边框,防止方块出界 } printf("\n"); } /*制作方块*/ void Make(struct Tetris *tetris) { a[tetris->x][tetris->y]=b[0]; //中心方块位置的图形状态 switch(tetris->flag) //共7大类,19种类型 { case 1: //田 { color(10); a[tetris->x][tetris->y+1]=b[1]; a[tetris->x+2][tetris->y+1]=b[2]; a[tetris->x+2][tetris->y]=b[3]; break; } case 2: //一 { color(12); a[tetris->x-2][tetris->y]=b[1]; a[tetris->x+2][tetris->y]=b[2]; a[tetris->x+4][tetris->y]=b[3]; break; } case 3: //1 { color(13); a[tetris->x][tetris->y-1]=b[1]; a[tetris->x][tetris->y-2]=b[2]; a[tetris->x][tetris->y+1]=b[3]; break; } case 4: //T { color(9); a[tetris->x+2][tetris->y]=b[1]; a[tetris->x-2][tetris->y]=b[2]; a[tetris->x][tetris->y+1]=b[3]; break; } case 5: //顺90 T { color(10); a[tetris->x-2][tetris->y]=b[1]; a[tetris->x][tetris->y-1]=b[2]; a[tetris->x][tetris->y+1]=b[3]; break; } case 6: //顺180 T { color(11); a[tetris->x][tetris->y-1]=b[1]; a[tetris->x+2][tetris->y]=b[2]; a[tetris->x-2][tetris->y]=b[3]; break; } case 7: // 顺270 T { color(12); a[tetris->x][tetris->y-1]=b[1]; a[tetris->x][tetris->y+1]=b[2]; a[tetris->x+2][tetris->y]=b[3]; break; } case 8: // Z { color(10); a[tetris->x-2][tetris->y]=b[1]; a[tetris->x][tetris->y+1]=b[2]; a[tetris->x+2][tetris->y+1]=b[3]; break; } case 9: //顺90 Z { color(5); a[tetris->x+2][tetris->y]=b[1]; a[tetris->x+2][tetris->y-1]=b[2]; a[tetris->x][tetris->y+1]=b[3]; break; } case 10: // 反Z { color(9); a[tetris->x+2][tetris->y]=b[1]; a[tetris->x][tetris->y+1]=b[2]; a[tetris->x-2][tetris->y+1]=b[3]; break; } case 11: //顺90 反Z { color(13); a[tetris->x+2][tetris->y]=b[1]; a[tetris->x+2][tetris->y+1]=b[2]; a[tetris->x][tetris->y-1]=b[3]; break; } case 12: // 7 { color(1); a[tetris->x][tetris->y-1 ]=b[1]; a[tetris->x][tetris->y+1]=b[2]; a[tetris->x-2][tetris->y-1]=b[3]; break; } case 13: // 顺90 7 { color(2); a[tetris->x+2][tetris->y-1]=b[1]; a[tetris->x-2][tetris->y]=b[2]; a[tetris->x+2][tetris->y]=b[3]; break; } case 14: // 顺180 7 { color(3); a[tetris->x][tetris->y-2]=b[1]; a[tetris->x][tetris->y-1]=b[2]; a[tetris->x+2][tetris->y]=b[3]; break; } case 15: // 顺270 7 { color(4); a[tetris->x+2][tetris->y]=b[1]; a[tetris->x+4][tetris->y]=b[2]; a[tetris->x][tetris->y+1]=b[3]; break; } case 16: // 反 7 { color(9); a[tetris->x+2][tetris->y-1]=b[1]; a[tetris->x][tetris->y+1]=b[2]; a[tetris->x][tetris->y-1]=b[3]; break; } case 17: // 顺90 反7 { color(10); a[tetris->x-2][tetris->y]=b[1]; a[tetris->x+2][tetris->y]=b[2]; a[tetris->x+2][tetris->y+1]=b[3]; break; } case 18: // 顺180 反7 { color(11); a[tetris->x][tetris->y+1]=b[1]; a[tetris->x][tetris->y-1]=b[2]; a[tetris->x-2][tetris->y+1]=b[3]; break; } case 19: // 顺270 反7 { color(12); a[tetris->x+2][tetris->y]=b[1]; a[tetris->x-2][tetris->y]=b[2]; a[tetris->x-2][tetris->y-1]=b[3]; break; } } } /*打印方块*/ void Print(struct Tetris *tetris) { for(i=0;i<4;i++) //让数组b[4]中的每个数都为1 { b[i]=1; } Make(tetris); for(i=tetris->x-2;i<=tetris->x+4;i+=2) { for(j=tetris->y-2;j<=tetris->y+1;j++) //循环方块所以可能出现的位置 { if(a[i][j]==1&&j>FrameY) //如果这个位置上有方块 { gotoxy(i,j); printf("■"); //打印边框内的方块 } } } gotoxy(FrameX+2*Frame_width+3,FrameY+1); color(4); printf("等级: "); color(12); printf("%d",tetris->level); gotoxy(FrameX+2*Frame_width+3,FrameY+3); color(4); printf("得分:"); color(12); printf("%d",tetris->score); gotoxy(FrameX+2*Frame_width+3,FrameY+5); color(4); printf("速度:"); color(12); printf("%d ms",tetris->speed); } /* 开始游戏*/ void Play() { int n; struct Tetris t,*tetris=&t; char ch; tetris->number=0; tetris->speed=250; tetris->score=0; tetris->level=1; HideCursor(); while(1) { Shui_Ji(tetris); Temp=tetris->flag; tetris->x=FrameX+2*Frame_width+6; tetris->y=FrameY+10; tetris->flag = tetris->next; Print(tetris); tetris->x=FrameX+Frame_width; tetris->y=FrameY-1; tetris->flag=Temp; //按键操作 while(1) { loop:Print(tetris); Sleep(tetris->speed); //延时 Clean(tetris); Temp1=tetris->x; Temp2=tetris->flag; //记住当前俄罗斯方块序号 if(kbhit()) //判断是否有键盘输入,有则用ch↓接收 { ch=getch(); if(ch==75) //←键则向左动,中心横坐标减2 { tetris->x-=2; } if(ch==77) //→键则向右动,中心横坐标加2 { tetris->x+=2; } if(ch==80) //↓键则加速下落 { if(If_move(tetris)!=0) { tetris->y+=2; } if(If_move(tetris)==0) { tetris->y=FrameY+Frame_height-2; } } if(ch==72) //↑键则变体,即当前方块顺时针转90度 { if( tetris->flag>=2 && tetris->flag<=3 ) //如果是直线方块 { tetris->flag++; tetris->flag%=2; tetris->flag+=2; } if( tetris->flag>=4 && tetris->flag<=7 ) //如果是T字方块 { tetris->flag++; tetris->flag%=4; tetris->flag+=4; } if( tetris->flag>=8 && tetris->flag<=9 ) //如果是Z字方块 { tetris->flag++; tetris->flag%=2; tetris->flag+=8; } if( tetris->flag>=10 && tetris->flag<=11 ) //如果是反Z字方块 { tetris->flag++; tetris->flag%=2; tetris->flag+=10; } if( tetris->flag>=12 && tetris->flag<=15 ) //如果是7字方块 { tetris->flag++; tetris->flag%=4; tetris->flag+=12; } if( tetris->flag>=16 && tetris->flag<=19 ) //如果是反7字方块 { tetris->flag++; tetris->flag%=4; tetris->flag+=16; } } if(ch == 32) //按空格键,暂停 { Print(tetris); while(1) { if(kbhit()) //再按空格键,继续游戏 { ch=getch(); if(ch == 32) { goto loop; } } } } if(ch == 27) //esc { system("cls"); memset(a,0,6400*sizeof(int)); //初始化a数组 main(); } if(If_move(tetris)==0) { tetris->x=Temp1; tetris->flag=Temp2; } else //如果可动,执行操作 { goto loop; } } tetris->y++; if(If_move(tetris)==0) { tetris->y--; Print(tetris); Full(tetris); break; } } for(i=tetris->y-2;iy+2;i++) { if(i==FrameY) { system("cls"); gotoxy(29,7); printf("\n"); color(6); printf(" @=================================|||||======================================@ \n"); printf(" || ■■ ■ ■ ■ ■■■■■ || \n"); printf(" || ■ ■ ■ ■ ■■ ■■ ■ || \n"); printf(" || ■ ■ ■ ■ ■ ■ ■ ■ || \n"); printf(" || ■ ■■■ ■ ■ ■ ■■ ■ ■■■■■ || \n"); printf(" || ■ ■ ■■■■■ ■ ■ ■ ■ || \n"); printf(" || ■ ■ ■ ■ ■ ■ ■ || \n"); printf(" || ■■ ■ ■ ■ ■ ■■■■■ || \n"); printf(" |* *| \n"); color(4); printf(" |* *| \n"); printf(" || ■■ ■ ■ ■■■■■ ■■■■ || \n"); printf(" || ■ ■ ■ ■ ■ ■ ■ || \n"); printf(" || ■ ■ ■ ■ ■ ■ ■ || \n"); printf(" || ■ ■ ■ ■ ■■■■■ ■■■■ || \n"); printf(" || ■ ■ ■ ■ ■ ■ ■ || \n"); printf(" || ■ ■ ■ ■ ■ ■ ■ || \n"); printf(" || ■■ ■ ■■■■■ ■ ■ || \n"); printf(" @============================================================================@ \n"); if(MessageBox(NULL,"游戏结束.\n要重新来一局么?","Game Over",MB_YESNO|MB_ICONQUESTION)==IDYES) { system("cls"); memset(a,0,6400*sizeof(int)); Game(); Play(); } else exit(0); } } tetris->flag = tetris->next; tetris->x=FrameX+2*Frame_width+6; tetris->y=FrameY+10; Clean(tetris); } } /*清除痕迹*/ void Clean(struct Tetris *tetris) { for(i=0;i<4;i++) //数组b[4]中有4个元素,循环这4个元素,让每个元素的值都为0 { b[i]=0; //数组b[4]的每个元素的值都为0 } Make(tetris); for(i=tetris->x-2;i<=tetris->x+4;i+=2) // X为中心方块 { for(j=tetris->y-2;j<=tetris->y+1;j++) { if(a[i][j]==0&&j>FrameY) //如果这个位置上没有图案,并且处于游戏界面当中 { gotoxy(i,j); printf(" "); //清除方块 } } } } /* 随机产生俄罗斯方块*/ void Shui_Ji(struct Tetris *tetris) { tetris->number++; //记住产生方块的个数 srand(time(NULL)); //初始化随机数 if(tetris->number==1) { tetris->flag = rand()%19+1; //记住第一个方块的序号 } tetris->next = rand()%19+1; //记住下一个方块的序号 } /*判断方块是否可以移动 */ int If_move(struct Tetris *tetris) { if(a[tetris->x][tetris->y]!=0) { return 0; } else { if( ( //田 tetris->flag==1 && ( a[tetris->x][tetris->y+1]==0&& a[tetris->x+2][tetris->y+1]==0&& a[tetris->x+2][tetris->y]==0) ) || ( //一 tetris->flag==2 && ( a[tetris->x-2][tetris->y]==0&& a[tetris->x+2][tetris->y]==0&& a[tetris->x+4][tetris->y]==0) ) || ( //1 tetris->flag==3 && ( a[tetris->x][tetris->y-1]==0&& a[tetris->x][tetris->y+1]==0&& a[tetris->x][tetris->y-2]==0) ) || ( //T tetris->flag==4 && ( a[tetris->x+2][tetris->y]==0&& a[tetris->x-2][tetris->y]==0&& a[tetris->x][tetris->y+1]==0) ) || ( //顺90 T tetris->flag==5 && ( a[tetris->x-2][tetris->y]==0&& a[tetris->x][tetris->y-1]==0&& a[tetris->x][tetris->y+1]==0) ) || ( //顺180 T tetris->flag==6 && ( a[tetris->x][tetris->y-1]==0&& a[tetris->x+2][tetris->y]==0&& a[tetris->x-2][tetris->y]==0) ) || ( //顺270 T tetris->flag==7 && ( a[tetris->x][tetris->y-1]==0&& a[tetris->x][tetris->y+1]==0&& a[tetris->x+2][tetris->y]==0) ) || ( //Z tetris->flag==8 && ( a[tetris->x-2][tetris->y]==0&& a[tetris->x][tetris->y+1]==0&& a[tetris->x+2][tetris->y+1]==0) ) || ( //顺90 Z tetris->flag==9 && ( a[tetris->x+2][tetris->y]==0&& a[tetris->x+2][tetris->y-1]==0&& a[tetris->x][tetris->y+1]==0) ) || ( //反 Z tetris->flag==10 && ( a[tetris->x+2][tetris->y]==0&& a[tetris->x][tetris->y+1]==0&& a[tetris->x-2][tetris->y+1]==0) ) || ( //顺90 反Z tetris->flag==11 && ( a[tetris->x+2][tetris->y]==0&& a[tetris->x+2][tetris->y+1]==0&& a[tetris->x][tetris->y-1]==0) ) || ( //7 tetris->flag==12 && ( a[tetris->x-2][tetris->y-1]==0&& a[tetris->x][tetris->y-1]==0&& a[tetris->x][tetris->y+1]==0) ) || ( //顺90 7 tetris->flag==13 && ( a[tetris->x-2][tetris->y]==0&& a[tetris->x+2][tetris->y]==0&& a[tetris->x+2][tetris->y-1]==0) ) || ( //顺180 7 tetris->flag==14 && ( a[tetris->x][tetris->y-2]==0&& a[tetris->x][tetris->y-1]==0&& a[tetris->x+2][tetris->y]==0) ) || ( //顺270 7 tetris->flag==15 && ( a[tetris->x+2][tetris->y]==0&& a[tetris->x+4][tetris->y]==0&& a[tetris->x][tetris->y+1]==0) ) || ( // 反 7 tetris->flag==16 && ( a[tetris->x+2][tetris->y-1]==0&& a[tetris->x][tetris->y+1]==0&& a[tetris->x][tetris->y-1]==0) ) || ( // 顺90 反7 tetris->flag==17 && ( a[tetris->x-2][tetris->y]==0&& a[tetris->x+2][tetris->y+1]==0&& a[tetris->x+2][tetris->y]==0) ) || ( //顺180 反7 tetris->flag==18 && ( a[tetris->x][tetris->y+1]==0&& a[tetris->x][tetris->y-1]==0&& a[tetris->x-2][tetris->y+1]==0) ) || ( //顺270 反7 tetris->flag==19 && ( a[tetris->x+2][tetris->y]==0&& a[tetris->x-2][tetris->y]==0&& a[tetris->x-2][tetris->y-1]==0) ) ) { return 1; } } return 0; } /*判断方块是否满行 */ void Full(struct Tetris *tetris) { int k,del_rows=0; for(j=FrameY+Frame_height-1;j>=FrameY+1;j--) { k=0; for(i=FrameX+2;iFrameY;k--) { for(i=FrameX+2;iscore+=100*del_rows; if( del_rows>0 && ( tetris->score%1000==0 || tetris->score/1000>tetris->level-1 ) ) { tetris->speed-=20; tetris->level++; } }