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; // 初始移动速度为300
tetris->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;
}



