Dec C++中常用的快捷键:
给代码行加注释:
删除代码行: 只能删除光标所在的代码行
1.俄罗斯方块游戏开发设计细节:
随机产生下滑方块,自动提速,积分,满行消除,方块形状变化,下一方块提示
2、系统功能设计
2.1系统功能结构
2.2业务流程图
3.使用Dev C++创建项目
文件->新建->项目->选择"Basic"选项卡中的第二项-Console Application(控制台应用程序)->C语言
4.预处理模块
预处理指定:#if #ifdef #ifndef #else #endif(条件编译) #define(宏定义) #include(文件引用) #line(行控制) #error(错误指定) #pragma(和实现相关的杂注)
5.游戏欢迎界面
按键盘数字‘1’开始游戏,按”2“查看游戏功能键,按"3"查看本游戏规则,按"4"退出游戏
5.1设计字体颜色
int color(int c){SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),c);//更改字体颜色return 0;}
在c语言中,SetConsoleTextAttribute()是设置控制台窗口字体颜色和背景色的函数
函数原型是:
BOOL SetConsoleTextAttribute(HANDLE consolehwnd,WORD wAttributes);consolehwnd = GetStdHandles(STD_OUTPUT_HANDLE);
GetStdHandle是获得输入,输出或错误的屏幕缓冲区的句柄
参数列表
参数值含 义STD_INPUT_HANDLE标准输入的句柄STD_OUTPUT_HANDLE标准输出的句柄STD_ERROR_HANDLE标准错误的句柄
wAttributes是设置颜色的参数
5.2设置文字显示位置
void gotoxy(int x,int y){COORD pos;pos.X =x; //横坐标pos.Y =y; //纵坐标SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),pos); }
SetConsoleCursorPosition()函数用来获取控制台的光标位置
COORD pos是一个结构体变量
5.3标题部分设计
void title(){color(15);//亮白色gotoxy(28,3);printf("俄 罗 斯 方 块n"); //输出标题color(11); //亮蓝色gotoxy(18,5); // ■printf("■"); // ■■gotoxy(18,6); // ■printf("■■");gotoxy(18,7); printf("■"); color(14); //黄色gotoxy(26,6); //■■printf("■■"); // ■■gotoxy(28,7);printf("■■");color(10); //绿色gotoxy(36,6); //■■printf("■■"); //■■gotoxy(36,7);printf("■■");color(13); //粉色gotoxy(45,5); //■printf("■"); //■gotoxy(45,6); //■printf("■"); //■gotoxy(45,7);printf("■");gotoxy(45,8);printf("■");color(12); //亮红色gotoxy(56,6); //■printf("■"); //■■■gotoxy(52,7); printf("■■■");}
5.4 设计菜单选项的边框
void welcome(){int n;int i,j=1;color(14);for(i=9;i<=20;i++) //循环y纵坐标,打印输出上,下边框 {for(j=15;j<=60;j++) //循环x横坐标,打印输出左,右边框 {gotoxy(j,i);if(i==9||i==20) printf("="); //输出上,下边框===else if(j==15||j==59) printf("||"); //输出左,右边框|| }}color(12);gotoxy(25,12);printf("1.开始游戏"); gotoxy(40,12);printf("2.按键说明"); gotoxy(25,17);printf("3.游戏规则"); gotoxy(40,17);printf("4.开始游戏"); gotoxy(21,22);color(3);printf("请选择[1,2,3,4]: bb");color(14);scanf("%d",&n); //输入选项switch(n){case 1:system("cls");break;case 2:break;case 3:break;case 4:break;} }
6.游戏主窗体设计
在界面绘制部分,一部分是左边的方块下落界面,另一部分是右边的得分记录,出现块展示和主要按键说明界面
void DrawGameframe(){gotoxy(frameX+frame_width-5,frameY-2); //打印游戏名称color(11);printf("俄罗斯方块");gotoxy(frameX+2*frame_width+3,frameY+7);color(2);printf("**********"); //打印下一个出现方块的上边框 gotoxy(frameX+2*frame_width+13,frameY+7);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:退出游戏");gotoxy(frameX,frameY);color(12);printf("╔");gotoxy(frameX+2*frame_width-2,frameY);printf("╗");gotoxy(frameX,frameY+frame_height);printf("╚");printf("╔");gotoxy(frameX+2*frame_width-2,frameY+frame_height);printf("╝");for(i=2;i<2*frame_width-2;i+=2){gotoxy(frameX+i,frameY);printf("=="); //打印上横框 }for(i=2;i<2*frame_width-2;i+=2){gotoxy(frameX+i,frameY+frame_height);printf("=="); //打印下横框 a[frameX+i][frameY+frame_height]=2; //标记下横框为游戏边框,防止方块出界 }for(i=1;i
按1 进入游戏界面
俄罗斯方块是要下落到下方边框才可,此时要做一个判断
定义一个数组a[80][80]用来标记游戏屏幕的图案,只有3个值 分别为2,1,0.
2表示数组a所示的位置为游戏边框
1表示数组a所示位置有方块
0表示无图案
只要分别找到游戏的左,右,下边框的数组表示,让其数组值为2,就可以成功设置边界
边界代码:
a[frameX+i][frameY+frame_height]=2; //标记下横框为游戏边框,防止方块出界 a[frameX][frameY+i]=2;//标记左竖框为游戏边框,防止边框出界 a[frameX+2*frame_width-2][frameY+i]=2;//标记右竖框为游戏边框,防止方块出界
7.游戏逻辑设计
1.制造方块不断下落的现象
2.在方块下落的时候,判断方块能不能放置在下方位置;或者能否继续左右移动
3.判断是否满行,满行即删除满行的方块
4.随机产生俄罗斯方块
7.1 判断俄罗斯方块是否可以移动
首先要判断中心方块移动的位置是否为空位置,即a[tetris->x][tetris->y]是否为方块或者墙壁
int ifMove(struct Tetris *tetris){if(a[tetris->x][tetris->y]!=0)//当中心块位置上有图案时,返回值为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 ) )||(tetris->flag==3 && (a[tetris->x][tetris->y-1]==0 && a[tetris->x][tetris->y-2]==0 && a[tetris->x][tetris->y+1]==0 ) )||(tetris->flag==4 && (a[tetris->x-2][tetris->y]==0 && a[tetris->x+2][tetris->y]==0 && a[tetris->x][tetris->y+1]==0 ) )||(tetris->flag==5 && (a[tetris->x][tetris->y-1]==0 && a[tetris->x][tetris->y+1]==0 && a[tetris->x-2][tetris->y]==0 ) )||(tetris->flag==6 && (a[tetris->x][tetris->y-1]==0 && a[tetris->x-2][tetris->y]==0 && a[tetris->x+2][tetris->y]==0 ) )||(tetris->flag==7 && (a[tetris->x][tetris->y-1]==0 && a[tetris->x][tetris->y+1]==0 && a[tetris->x+2][tetris->y]==0 ) )||(tetris->flag==8 && (a[tetris->x][tetris->y+1]==0 && a[tetris->x-2][tetris->y]==0 && a[tetris->x+2][tetris->y+1]==0 ) )||(tetris->flag==9 && (a[tetris->x][tetris->y-1]==0 && a[tetris->x-2][tetris->y]==0 && a[tetris->x-2][tetris->y+1]==0 ) )||(tetris->flag==10 && (a[tetris->x][tetris->y-1]==0 && a[tetris->x-2][tetris->y-1]==0 && a[tetris->x+2][tetris->y]==0 ) )||(tetris->flag==11 && (a[tetris->x][tetris->y+1]==0 && a[tetris->x-2][tetris->y-1]==0 && a[tetris->x-2][tetris->y]==0 ) )||(tetris->flag==12 && (a[tetris->x][tetris->y-1]==0 && a[tetris->x][tetris->y+1]==0 && a[tetris->x-2][tetris->y-1]==0 ) )||(tetris->flag==15 && (a[tetris->x-2][tetris->y]==0 && a[tetris->x-2][tetris->y+1]==0 && a[tetris->x+2][tetris->y]==0 ) )||(tetris->flag==14 && (a[tetris->x][tetris->y-1]==0 && a[tetris->x][tetris->y+1]==0 && a[tetris->x+2][tetris->y+1]==0 ) )||(tetris->flag==13 && (a[tetris->x-2][tetris->y]==0 && a[tetris->x+2][tetris->y-1]==0 && a[tetris->x+2][tetris->y]==0 ) )||(tetris->flag==16 && (a[tetris->x][tetris->y+1]==0 && a[tetris->x][tetris->y-1]==0 && a[tetris->x+2][tetris->y-1]==0 ) )||(tetris->flag==19 && (a[tetris->x-2][tetris->y]==0 && a[tetris->x-2][tetris->y-1]==0 && a[tetris->x+2][tetris->y]==0 ) )||(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 ) )||(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 ) )){return 1;}}return 0;}
7.2清除俄罗斯方块下落的痕迹
只要在输出位置之前加上“ ”即可
void CleanTetris(struct Tetris *tetris){for(i=0;i<4;i++) //数组b[4]中有4个元素,循环这4个元素,让每个元素的值都为0{b[i]=0;} MakeTetris(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(" "); //清除方块 }} } }
7.3判断方块是否满行
因为游戏界面的宽度是frame_width,所以除去两个竖边框,那么在满行时,方块所占的宽度就是frame_width-2
7.4随机产生俄罗斯方块类型的序号
需要使用随机函数rand()来获得随机的方块类型序号
已经定义好每种类型的方块都有各自的flag,也就是序号,从1到19
rand()是一个随机数函数,每次执行同一个程序时,调用rand()函数所得的随机数序列是固定的
令rand()函数的返回值更具有随机性,通常需要为随机数生成器提供一粒新的随机种子、C语言提供了srand()函数,可以为随机数生成器播散种子,只要种子不同,rand()函数就会产生不同的随机序列。srand()函数被称为随机数生成器的初始化器。
srand()函数位于time.h头文件中。需引用time.h头文件
使用rand()函数获得随机数的步骤可以总结为:
(1)调用srand(time(NULL))设置随机数种子,初始化随机数。
(2)调用rand()函数获得一个或一系列随机数。
用于获取1~19之间的随机数:
srand(time(NULL)); //设置随机数种子,初始化随机数tetris->flag=rand()%19+1; //记住第一个方块的序号
8.各种按键的操作
使用kbhit()和getch()函数来接收键盘按键
所在头文件conio.h
在c语言中可以通过kbhit()函数来检测当前是否有键盘输入
getch()函数用来从控制台读取一个字符
if(kbhit()) //判断是否有键盘输入{ ch=getch(); //ch接收键盘的按键}
ch=getch()是指在按下键盘后,会把该键字符所对应的ASCII码赋值给ch,然后将ch的值分别和我们用到的键盘字符的ASCII码值进行对比。
完整程序:
#include#include //控制DOS界面#include //接收键盘输入、输出(kbhit(),getch()) #include //获取随机数#define frameX 13 //游戏窗口左上角的x轴坐标 #define frameY 3//游戏窗口左上角的y轴坐标 #define frame_height 20 //游戏窗口的高度 #define frame_width 18//游戏窗口的宽度int i,j,Temp,Temp1,Temp2; //temp,temp1,temp2用于记住和转换方块变量的值//标记游戏屏幕的图案:2,1,0分别表示该位置为游戏边框,方块,无图案;初始化为无图案int a[80][80]={0};int b[4]; //1表示由方块,0表示无方块struct Tetris //声明俄罗斯方块的结构体 {int x; //中心方块的x轴坐标 int y; //中心方块的y轴坐标 int flag; //标记方块类型的序号 int next; //下一个俄罗斯方块类型的序号int speed; //俄罗斯方块移动的速度int number;//产生俄罗斯方块的个数int score; //游戏的分数int level; //游戏的等级 };HANDLE hOut; //控制台句柄 void gotoxy(int x,int y); //光标移动到指定位置void DrawGameframe(); //绘制游戏边框void Flag(struct Tetris *); //随机产生方块类型的序号void MakeTetris(struct Tetris *); //制作俄罗斯方块void PrintTetris(struct Tetris *); //打印俄罗斯方块void CleanTetris(struct Tetris *); //清除俄罗斯方块的痕迹int ifMove(struct Tetris *); //判断是否能移动,返回值为1,能移动;void Del_Fullline(struct Tetris *); //判断是否满行,并删除满行的俄罗斯方块void Gameplay(); //开始游戏void regulation(); //游戏规则void explation(); //按键说明void welcome(); //欢迎界面void Replay(struct Tetris * tetris); //重新开始游戏void title(); //欢迎界面上方的标题void flower(); //字符花装饰void close(); //关闭游戏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); }void title(){color(15);//亮白色gotoxy(28,3);printf("俄 罗 斯 方 块n"); //输出标题color(11); //亮蓝色gotoxy(18,5); // ■printf("■"); // ■■gotoxy(18,6); // ■printf("■■");gotoxy(18,7); printf("■"); color(14); //黄色gotoxy(26,6); //■■printf("■■"); // ■■gotoxy(28,7);printf("■■");color(10); //绿色gotoxy(36,6); //■■printf("■■"); //■■gotoxy(36,7);printf("■■");color(13); //粉色gotoxy(45,5); //■printf("■"); //■gotoxy(45,6); //■printf("■"); //■gotoxy(45,7);printf("■");gotoxy(45,8);printf("■");color(12); //亮红色gotoxy(56,6); //■printf("■"); //■■■gotoxy(52,7); printf("■■■");}void welcome(){int n;int i,j=1;color(14);for(i=9;i<=20;i++) //循环y纵坐标,打印输出上,下边框 {for(j=15;j<=60;j++) //循环x横坐标,打印输出左,右边框 {gotoxy(j,i);if(i==9||i==20) printf("="); //输出上,下边框===else if(j==15||j==59) printf("||"); //输出左,右边框|| }}color(12);gotoxy(25,12);printf("1.开始游戏"); gotoxy(40,12);printf("2.按键说明"); gotoxy(25,17);printf("3.游戏规则"); gotoxy(40,17);printf("4.退出"); gotoxy(21,22);color(3);printf("请选择[1,2,3,4]: bb");color(14);scanf("%d",&n); //输入选项switch(n){case 1:system("cls");DrawGameframe(); //绘制游戏边界 Gameplay(); break;case 2:explation(); break;case 3:regulation();break;case 4:close();break;} }void DrawGameframe(){gotoxy(frameX+frame_width-5,frameY-2); //打印游戏名称color(11);printf("俄罗斯方块");gotoxy(frameX+2*frame_width+3,frameY+7);color(2);printf("**********"); //打印下一个出现方块的上边框 gotoxy(frameX+2*frame_width+13,frameY+7);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:退出游戏");gotoxy(frameX,frameY);color(12);printf("╔");gotoxy(frameX+2*frame_width-2,frameY);printf("╗");gotoxy(frameX,frameY+frame_height);printf("╚");printf("╔");gotoxy(frameX+2*frame_width-2,frameY+frame_height);printf("╝");for(i=2;i<2*frame_width-2;i+=2){gotoxy(frameX+i,frameY);printf("=="); //打印上横框 }for(i=2;i<2*frame_width-2;i+=2){gotoxy(frameX+i,frameY+frame_height);printf("=="); //打印下横框 a[frameX+i][frameY+frame_height]=2; //标记下横框为游戏边框,防止方块出界 }for(i=1;ix][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(13);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: //竖向直线方块 ■{// ■ // ■ // ■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(11);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: // ■{// ■■// ■color(11);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 6: // ■{ // ■■■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: //■{ // ■■// ■color(11);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:// ■■{ // ■■color(14);a[tetris->x][tetris->y+1]=b[1];a[tetris->x-2][tetris->y]=b[2];a[tetris->x+2][tetris->y+1]=b[3];break;}case 9: //顺时针的Z字块 ■{ // ■■ // ■color(14);a[tetris->x][tetris->y-1]=b[1];a[tetris->x-2][tetris->y]=b[2];a[tetris->x-2][tetris->y+1]=b[3];break;}case 10: //反转Z ■■{ // ■■color(14);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 11: //顺时针的反转Z ■{ // ■■ // ■ color(14);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 12: //7字方块 ■■{ // ■ // ■ color(12);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: //7字方块 ■{ // ■■■ // color(12);a[tetris->x-2][tetris->y]=b[1];a[tetris->x+2][tetris->y-1]=b[2];a[tetris->x+2][tetris->y]=b[3];break;}case 14: //7字方块 ■{ // ■ // ■■ color(12);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 15: //7字方块 ■■■{ // ■color(12);a[tetris->x-2][tetris->y]=b[1];a[tetris->x-2][tetris->y+1]=b[2];a[tetris->x+2][tetris->y]=b[3];break;}case 16: //7字方块 ■■{ // ■ // ■ color(9);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 17: //7字方块 ■■■{ // ■ color(9);a[tetris->x-2][tetris->y]=b[1];a[tetris->x+2][tetris->y+1]=b[2];a[tetris->x+2][tetris->y]=b[3];break;}case 18: //7字方块 ■{ // ■ // ■■ color(9);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: //7字方块 ■{ // ■■■ color(9);a[tetris->x-2][tetris->y]=b[1];a[tetris->x-2][tetris->y-1]=b[2];a[tetris->x+2][tetris->y]=b[3];break;}}} //■横向占2个字符,纵向占1个字符 void PrintTetris(struct Tetris *tetris){for(i=0;i<4;i++){b[i]=1;}MakeTetris(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("level:");color(12);printf(" %d",tetris->level); //输出等级gotoxy(frameX+2*frame_width+3,frameY+3);color(4);printf("score:");color(12);printf(" %d",tetris->score); //输出分数gotoxy(frameX+2*frame_width+3,frameY+5);color(4);printf("speed:");color(12);printf(" %dms",tetris->speed); //输出速度 }int ifMove(struct Tetris *tetris){if(a[tetris->x][tetris->y]!=0)//当中心块位置上有图案时,返回值为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 ) )||(tetris->flag==3 && (a[tetris->x][tetris->y-1]==0 && a[tetris->x][tetris->y-2]==0 && a[tetris->x][tetris->y+1]==0 ) )||(tetris->flag==4 && (a[tetris->x-2][tetris->y]==0 && a[tetris->x+2][tetris->y]==0 && a[tetris->x][tetris->y+1]==0 ) )||(tetris->flag==5 && (a[tetris->x][tetris->y-1]==0 && a[tetris->x][tetris->y+1]==0 && a[tetris->x-2][tetris->y]==0 ) )||(tetris->flag==6 && (a[tetris->x][tetris->y-1]==0 && a[tetris->x-2][tetris->y]==0 && a[tetris->x+2][tetris->y]==0 ) )||(tetris->flag==7 && (a[tetris->x][tetris->y-1]==0 && a[tetris->x][tetris->y+1]==0 && a[tetris->x+2][tetris->y]==0 ) )||(tetris->flag==8 && (a[tetris->x][tetris->y+1]==0 && a[tetris->x-2][tetris->y]==0 && a[tetris->x+2][tetris->y+1]==0 ) )||(tetris->flag==9 && (a[tetris->x][tetris->y-1]==0 && a[tetris->x-2][tetris->y]==0 && a[tetris->x-2][tetris->y+1]==0 ) )||(tetris->flag==10 && (a[tetris->x][tetris->y-1]==0 && a[tetris->x-2][tetris->y-1]==0 && a[tetris->x+2][tetris->y]==0 ) )||(tetris->flag==11 && (a[tetris->x][tetris->y+1]==0 && a[tetris->x-2][tetris->y-1]==0 && a[tetris->x-2][tetris->y]==0 ) )||(tetris->flag==12 && (a[tetris->x][tetris->y-1]==0 && a[tetris->x][tetris->y+1]==0 && a[tetris->x-2][tetris->y-1]==0 ) )||(tetris->flag==15 && (a[tetris->x-2][tetris->y]==0 && a[tetris->x-2][tetris->y+1]==0 && a[tetris->x+2][tetris->y]==0 ) )||(tetris->flag==14 && (a[tetris->x][tetris->y-1]==0 && a[tetris->x][tetris->y+1]==0 && a[tetris->x+2][tetris->y+1]==0 ) )||(tetris->flag==13 && (a[tetris->x-2][tetris->y]==0 && a[tetris->x+2][tetris->y-1]==0 && a[tetris->x+2][tetris->y]==0 ) )||(tetris->flag==16 && (a[tetris->x][tetris->y+1]==0 && a[tetris->x][tetris->y-1]==0 && a[tetris->x+2][tetris->y-1]==0 ) )||(tetris->flag==19 && (a[tetris->x-2][tetris->y]==0 && a[tetris->x-2][tetris->y-1]==0 && a[tetris->x+2][tetris->y]==0 ) )||(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 ) )||(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 ) )){return 1;}}return 0;} void CleanTetris(struct Tetris *tetris){for(i=0;i<4;i++) //数组b[4]中有4个元素,循环这4个元素,让每个元素的值都为0{b[i]=0;} MakeTetris(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 Del_Fullline(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; //每删除一行,得100分if( del_rows>0 && ( tetris->score%1000==0 || tetris->score/1000 > tetris->level-1 ) ){tetris->speed-=20;tetris->level++;} } void Flag(struct Tetris *tetris){tetris->number++; //记住产生方块的个数srand(time(NULL));//初始化随机数if(tetris->number==1){tetris->flag = rand()%19+1; //记住第一个方块的序号} tetris->next= rand()%19+1; //记住下一个方块的序号 得到都是右边下一个方块预览界面中显示的方块类型 }void Gameplay(){int n;struct Tetris t,*tetris=&t;//定义结构体指针并指向结构体变量char ch; //定义接收键盘输入的变量tetris->number=0; //初始化俄罗斯方块数为0个tetris->speed=300; // 初始移动速度为300tetris->score=0;tetris->level=1;while(1) //循环产生方块,直至游戏结束 {Flag(tetris); //得到产生俄罗斯方块类型Temp=tetris->flag; tetris->x=frameX+2*frame_width+6;tetris->y=frameY+10;tetris->flag=tetris->next; //获得下一个方块PrintTetris(tetris);tetris->x=frameX+frame_width;tetris->y=frameY-1;tetris->flag=Temp; //按键操作while(1){label:PrintTetris(tetris); //打印俄罗斯方块Sleep(tetris->speed); //延缓时间CleanTetris(tetris); //清除痕迹Temp1=tetris->x; //记住中心块横坐标的值 Temp2=tetris->flag; if(kbhit()) //判断是否有键盘输入,有则用ch接收{ch=getch();if(ch==75 ) //按 ←键则向左移动,中心横坐标减2 {tetris->x-=2;}if(ch==77) //按 →键则1向右移动,中心横坐标加2 {tetris->x+=2;}if(ch==80){if(ifMove(tetris) !=0 ){tetris->y+=2; }if(ifMove(tetris) ==0 ){tetris->y = frameY+frame_height-2;}}if(ch==72) //按 ↑键则1向右移动,中心横坐标加2 {if(tetris->flag>=2 && tetris->flag <=3){tetris->flag++;tetris->flag%=2;tetris->flag+=2; }if(tetris->flag>=4 && tetris->flag <=7){tetris->flag++;tetris->flag%=4;tetris->flag+=4; }if(tetris->flag>=8 && tetris->flag <=11){tetris->flag++;tetris->flag%=4;tetris->flag+=8; }if(tetris->flag>=12 && tetris->flag <=15){tetris->flag++;tetris->flag%=4;tetris->flag+=12; }if(tetris->flag>=16 && tetris->flag <=19){tetris->flag++;tetris->flag%=4;tetris->flag+=16; }}if(ch==32) //按空格键暂停 {PrintTetris(tetris);while(1){if(kbhit()) //再次按空格键,继续游戏 {ch=getch();if(ch==32){goto label;}}}}if(ch==27){system("cls");memset(a,0,6400*sizeof(int));welcome();}if(ifMove(tetris)==0) //如果不可动,则上面操作无效{tetris->x=Temp1;tetris->flag=Temp2;}else //如果可动,则执行操作 {goto label;} }tetris->y++; //如果没有操作指令,则方块向下移动if(ifMove(tetris)==0){tetris->y--;PrintTetris(tetris);Del_Fullline(tetris);break;} }//游戏结束条件:方块触到框顶位置for(i=tetris->y-2;iy+2;i++){if(i==frameY){system("cls");gotoxy(29,7);printf(" n");color(12);printf("ttt■■■■ ■ ■ ■■ n");printf("ttt■ ■■ ■ ■ ■ n");printf("ttt■■■ ■ ■ ■ ■ ■n");printf("ttt■ ■ ■■ ■ ■ n");printf("ttt■■■■ ■ ■ ■■ n");gotoxy(17,18);color(14);printf("我要重新玩一局---------------1");gotoxy(44,18);printf("不玩了,退出吧---------------2");int n;gotoxy(32,20);printf("选择【1/2】");color(11);scanf("%d",&n);switch(n){case 1:system("cls");Replay(tetris);//重新开始游戏break;case 2:exit(0);break;}}}tetris->flag = tetris->next; //清除下一个俄罗斯方块的图形tetris->x=frameX+2*frame_width+6;tetris->y=frameY+10;CleanTetris(tetris); }//while(1) 循环产生方块,直至游戏结束 } void Replay(struct Tetris *tetris){system("cls"); //清屏memset(a,0,6400*sizeof(int)); DrawGameframe(); //制作游戏窗口Gameplay();//开始游戏 }void explation(){int i,j=1;system("cls");color(13);gotoxy(32,3);printf("按键说明");color(2);for(i=6;i<=16;i++) //输出上下边框 {for(j=15;j<=60;j++){gotoxy(j,i);if(i==6||i==16) printf("=");else if(j==15||j==59) printf("||");} }color(3);gotoxy(18,7); printf("tip1:玩家可以通过←→方向键来移动方块");color(10);gotoxy(18,9);printf("tip2:玩家可以通过 ↑使方块旋转");color(14);gotoxy(18,11);printf("tip3:玩家可以通过 ↓加速方块下落");color(11);gotoxy(18,13);printf("tip4:按空格键暂停游戏,再按空格键继续");color(4);gotoxy(18,15);printf("tip5:按ESC键退出游戏");getch(); //按任意键返回主界面 system("cls");main();}void regulation(){int i,j=1;system("cls");color(13);gotoxy(34,3);printf("游戏规则");color(2);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("tip1:不同形状的小方块从屏幕上方落下,玩家通过调整");gotoxy(22,9);printf("方块的位置和方向,使他们在屏幕底部拼出完整的");gotoxy(22,11);printf("一条或几条");color(14);gotoxy(16,13);printf("tip2:每消除一行,积分涨100");color(11);gotoxy(16,15);printf("tip3:每积累1000分,会提升一个等级");color(10);gotoxy(16,17);printf("tip4:提升等级会使方块下落速度加快,游戏难度加大");getch();system("cls");welcome();}void close(){exit(0);}int main(){title(); //欢迎界面上的标题 welcome(); //新添加的语句 return 0; }