如何制作俄罗斯方块(作业第一部分)

这是用链表结构制作俄罗斯方块的作业。这种结构并不是最适合来做这个游戏的,但是用链表来做,可以提高对链表的理解和对链表的运用能力,自己做的还是比较粗糙,希望大家来学习交流指出意见和建议,一共有三个部分。

第二部分 https://blog.csdn.net/qq_29989211/article/details/104580386
第三部分 https://blog.csdn.net/qq_29989211/article/details/104581507
在这里插入图片描述
这是进入游戏的欢迎界面,下方可以看到选择1,2,3,4个数字,来进入不同的界面,这些界面都是需要制作的。

1.头文件和需要用的全局变量

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
#include <conio.h>
#include <time.h>

前三个头文件大家都很熟悉了, windows.h 文件是用来控制DOS界面,获取控制台上坐标位置,设置字体颜色需要用到的,稍后会详细给出代码来说明如何用到;conio.h
是用来接受键盘输入的,只要用在kbhit()和getch()函数上;time.h具体用来获取随机数,后面也会介绍。

#define FrameX 13//游戏窗口左上角的X坐标
#define FrameY 3//游戏窗口左上角的y坐标
#define Frame_height 20//游戏窗口的高度
#define Frame_width 18//游戏窗口的宽度

全局宏定义这几个常量,后面都要用到,需要记一下,游戏窗口实际如下图:在这里插入图片描述
左上角坐标实际如下图:在这里插入图片描述

 int i,j,Temp1,Temp2;//几个需要用的int变量 
int a[80][80]={0};//用来表示游戏界面的画或者不画情况的正方数组,都是0或1 

int b[4];//一个俄罗斯方块4个块 
int speed;//游戏速度 
int number;//方块数量 
int score;//分数 
int level;//等级 
typedef struct Tetris
{
	int x;
	int y;
	int flag;
	struct Tetris *pnext;
}asd;//用来做链表 

struct Tetris *pa_tetris;//制作链表的工具指针 
struct Tetris *pz_tetris;//尾指针 
struct Tetris *pHead_tetris;//头指针 
struct Tetris *pTemp_tetris;//这个指针如何用稍后会有代码 
int contact;//0或1的变量有用 

HANDLE hOut;//控制台句柄 

需要说的是 HANDLE hOut ,这个句柄需要在此声明一下,之后的gotoxy函数必须在这个句柄说明之后,才能正常编译。

以下是整个游戏定义出要用的函数

void gotoxy(int x,int y);//移动光标
void DrawGameframe();//打印游戏方框
void CreateFlag();//稍后细说
void MakeTetris(struct Tetris*);//制作方块
void PrintTetris(struct Tetris*);//打印方块
void CleanTetris(struct Tetris*);//清楚上一时间方块痕迹
int ifMove(struct Tetris*);//判断是否可以移动

void Del_Fullline(struct Tetris*);//判断是否满行
void Gameplay();//稍后细说
void Regulation();//游戏规则
void explantion();//游戏解释
void Replay();//重玩
void welcome();//欢迎界面
void title();//标题
void flower();//一朵小花
void closer();//关闭游戏
int  color();//颜色函数
int main();//主函数

2.函数解释

下面就按照上面给出的函数顺序,一个一个介绍函数(CreateFlag和Gameplay放在最后):

void gotoxy(int x,int y);
void gotoxy(int x,int y)
{
	COORD pos;
	pos.X=x;
	pos.Y=y;
	SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),pos);
}

SetConsoleCursorPosition是API中定位光标位置的函数。
如果用户定义了 COORD pos,那么pos其实是一个结构体变量,其中X和Y是它的成员,之后每当调用gotoxy函数的时候,括号里面的 x和y就是你需要让光标跑到那个位置的坐标,很好用。

void DrawGameframe();
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("╚");
	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<Frame_height;i++)
	{
		gotoxy(FrameX,FrameY+i);
		printf("|");
		a[FrameX][FrameY+i]=2;
	}
	
	for(i=1;i<Frame_height;i++)
	{
		gotoxy(FrameX+2*Frame_width-2,FrameY+i);
		printf("|");
		a[FrameX+2*Frame_width-2][FrameY+i]=2;
	}

} 

这是打印游戏方框的函数,如图在这里插入图片描述
其中也可以看出为什么要定义以下几个变量了,如果不定义,那就会全是单纯的数字,看上去很乱

#define FrameX 13
#define FrameY 3
#define Frame_height 20
#define Frame_width 18

需要将光标移动到指定位置之前,需要先调用gotoxy函数,gotoxy(x,y),这样你下面要用的printf就会在指定位置进行打印了。
还看到有个color函数,color(数字)这个是之后会说的颜色函数,和gotoxy类似,每次你要将打印出的东西变个颜色的时候,也是提前调用color函数。

void PrintTetris(struct Tetris*tetris);
void PrintTetris(struct Tetris *tetris)
{

	
	for(i=0;i<4;i++)
	{
		b[i]=1;//用循环将方块数组全部赋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)//FrameY就是最顶段的Y坐标,超过这个坐标就打印不了
			{
				gotoxy(i,j);//定位
				printf("▇");//打印
			}
		}
	}
	
		
	gotoxy(FrameX+2*Frame_width+3,FrameY+1);//以下都是打印游戏界面右边的信息,每打印一个方块,信息都会更新或者不更新,所以每次都要运行一遍
	color(4);
	printf("level : ");
	color(12);
	printf("%d",level);
	gotoxy(FrameX+2*Frame_width+3,FrameY+3);
	color(4);
	printf("score :");
	color(12);
	printf("%d",score);
    gotoxy(FrameX+2*Frame_width+3,FrameY+5);
	color(4);
	printf("speed :");
	color(12);
	printf("%dms",speed);	
	
}

解释一下这段代码

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)//FrameY就是最顶段的Y坐标,超过这个坐标就打印不了
			{
				gotoxy(i,j);//定位
				printf("▇");//打印
			}
		}
	}

在这里插入图片描述
在这里插入图片描述
游戏所用的方块横向站2个单位,竖直占1个单位,而且俄罗斯方块所有的一共19种方块形态,无论怎么转换,都是在这个4X4的大方形里面变换的,所以双重循环把16个格子都读了一遍,那些需要打印,哪些不需要打印,都有1和0定义过,所以上面的代码将留很好理解了。

void MakeTetris(struct Tetris*tetris)void MakeTetris(struct Tetris*tetris)
{
		a[tetris->x][tetris->y]=b[0];//中心方块即上面4X4
	switch(tetris->flag)
	{
		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:
			{
				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:
			{
				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:
			{
				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:
			{
				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:
			{
				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:
			{
				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:
			{
				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:
			{
				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:
			{
				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:
			{
				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:
			{
				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:
			{
				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
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值