栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

俄罗斯方块游戏系统-c语言版

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

俄罗斯方块游戏系统-c语言版

 

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;
 } 


转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/737933.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号