⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 els.c

📁 我的俄罗斯方块(有详细注解)
💻 C
📖 第 1 页 / 共 2 页
字号:
/* 2002-11-13 
 *俄罗斯方块
 *Made by GGG
 */
#include <stdio.h>
# include <stdlib.h>
#include <dos.h>
#include <graphics.h>

#define TIMER 0x1c


#define VK_LEFT  0x4b00
#define VK_RIGHT 0x4d00
#define VK_DOWN  0x5000
#define VK_UP    0x4800
#define VK_HOME  0x4700
#define VK_END   0x4f00
#define VK_SPACE 0x3920
#define VK_ESC   0x011b
#define VK_ENTER 0x1c0d

#define MAX_BOX 19			/*总共有19种各形态的方块*/
#define BSIZE 16			/*方块的边长是16个象素*/
#define Sys_x 160			/*显示方块界面的左上角x座标*/
#define Sys_y 25				/*显示方块界面的左上角y座标*/
#define Horizontal_boxs 15		/*水平的方向以方块为单位的长度*/
#define Vertical_boxs 25		/*垂直的方向以方块为单位的长度,也就说长是30个方块*/
#define Begin_boxs_x 15/2		/*产生第一个方块时应该出现的起始位置 这里指定是在第5格出现*/


#define FgColor 2		/*前景颜色,如文字*/
#define BgColor 0		/*背景颜色*/

#define LeftWin_x Sys_x+Horizontal_boxs*BSIZE+50		/*左边状态栏的x座标*/


#define false 0
#define true 1
/*移动的方向*/
#define MoveLeft 1
#define MoveRight 2
#define MoveDown 3
#define MoveRoll 4
/*
 *以后坐标的每个像素点看作是BSIZE*BSIZE正方形的方块
 */
int current_box_numb;		/*保存当前方块编号*/
/*int Table_board[Vertical_boxs][Horizontal_boxs];	/*保存游戏当前状态的数组 */
int Curbox_x=Sys_x+Begin_boxs_x*BSIZE,Curbox_y=Sys_y;/*x,y是保存方块的当前坐标的*/
int flag_newbox=false;	/*是否要产生新方块的标记0*/
int speed=0;			/*下落速度*/
int score=0; 			/*总分*/
int speed_step=15;		/*每等级所需要分数*/
void interrupt (*oldtimer)(void);/* function pointer variable */

struct BOARD			/*游戏底板结构,表示每个点所具有的属性*/
{
	int var;			/*当前状态 只有0和1*/
	int color;				/*颜色*/
}Table_board[Vertical_boxs][Horizontal_boxs];

/*方块结构*/
struct SHAPE
{
	char box[2];			/*一个字节等于8位,每4位来表示一个方块的一行*/
	int color;				/*颜色*/
	int next;				/*下个方块的编号*/
	int prev;				/*上个方块的编号*/
};

/*为游戏底板分配内存*/


/*初始化方块内容*/
struct SHAPE shapes[MAX_BOX]=
{
/*
 *   口     口口口   口口      口
 *   口     口         口  口口口
 *   口口              口        
 */

	{0x88,	0xc0,	CYAN,	1,	3},
	{0xe8,	0x0,	CYAN,	2,	0},
	{0xc4,	0x40,	CYAN,	3,	1},
	{0x2e,	0x0,	CYAN,	0,	2},
/*
 *   口        口口 口口口
 *   口 口     口       口
 * 口口 口口口 口    
 */
	{0x44,	0xc0,	MAGENTA,	5,	7},
	{0x8e,	0x0,	MAGENTA,	6,	4},
	{0xc8,	0x80,	MAGENTA,	7,	5},
	{0xe2,	0x0,	MAGENTA,	4,	6},

/*
 *   口
 *   口口
 *     口
 */
	{0x8c,	0x40,	YELLOW,	9,	9},
	{0x6c,	0x0,	YELLOW,	8,	8},

/*
 *   口
 * 口口
 * 口
 */
	{0x4c,	0x80,	BROWN,	11,	11},
	{0xc6,	0x0,	BROWN,	10,	10},

/*
 *   口
 * 口口口
 */
	{0x4e,	0x0,	WHITE,	13,	15},
	{0x8c,	0x80,	WHITE,	14,	12},
	{0xe4,	0x0,	WHITE,	15,	13},
	{0x4c,	0x40,	WHITE,	12,	14},

/* 口
 * 口
 * 口
 * 口
 */
	{0x88,	0x88,	RED,	17,	17},
	{0xf0,	0x0,	RED,	16,	16},

/*
 * 口口
 * 口口
 */

	{0xcc,	0x0,	BLUE,	18,	18}

};


unsigned int TimerCounter=0;

void interrupt newtimer(void)
{
	(*oldtimer)();
	TimerCounter++;
}

void SetTimer(void interrupt(*IntProc)(void))
{
	oldtimer=getvect(TIMER);
	disable();
	setvect(TIMER,IntProc);
	enable();
}
void KillTimer()
{
	disable();
	setvect(TIMER,oldtimer);
	enable();
}
/*显示分数*/
void ShowScore(int score)
{
	int x,y;
	char score_str[5];/*保存游戏得分*/
	setfillstyle(SOLID_FILL,BgColor);
	x=LeftWin_x;
	y=100;
	bar(x-BSIZE,y,x+BSIZE*3,y+BSIZE*3);
/*	itoa(score,score_str,10);*/
	sprintf(score_str,"%3d",score);
	outtextxy(x,y,"SCORE");
	outtextxy(x,y+10,score_str);
}

/*显示速度*/
void ShowSpeed(int speed)
{
	int x,y;
	char speed_str[5];/*保存游戏得分*/
	setfillstyle(SOLID_FILL,BgColor);
	x=LeftWin_x;
	y=150;
	bar(x-BSIZE,y,x+BSIZE*3,y+BSIZE*3);
	sprintf(speed_str,"%3d",speed+1);
	outtextxy(x,y,"speed");
	outtextxy(x,y+10,speed_str);
}


/*
 *********初始化界面*******
 *参数说明:
 *		x,y为左上角坐标
 *		m,n对应于Vertical_boxs,Horizontal_boxs
 *		表示横肉纵方向的长度(以方块为单位)
 *BSIZE Sys_x Sys_y
 */   
void initialize(int x,int y,int m,int n)
{

	int i,j,oldx;
	oldx=x;
	for(j=0;j<n;j++)
	{
		for(i=0;i<m;i++)
		{
			/*if(i==0 || i==(m-1) || j==(n-1))	Table_board[j][i]=1;
			else	*/	
			Table_board[j][i].var=0;
			Table_board[j][i].color=BgColor;
			line(x,y,x+BSIZE,y);
			line(x,y,x,y+BSIZE);
			line(x,y+BSIZE,x+BSIZE,y+BSIZE);
			line(x+BSIZE,y,x+BSIZE,y+BSIZE);
			x+=BSIZE;
		}
		y+=BSIZE;
		x=oldx;
	}
	Curbox_x=x;
	Curbox_y=y;/*x,y是保存方块的当前坐标的*/
	flag_newbox=false;	/*是否要产生新方块的标记0*/
	speed=0;			/*下落速度*/
	score=0; 			/*总分*/
	ShowScore(score);
	ShowSpeed(speed);
/*
	for(j=0;j<=n;j++)
	{
		for(i=0;i<=m;i++)
		{
			if(i==0 || i==m || j==n)	Table_board[j][i]=1;			/*最左右边设成1
			else				Table_board[j][i]=0;
		}

	}

Table_board[10][10]=1;
Table_board[5][5]=1;

for(j=0;j<n;j++)
	{
		for(i=0;i<m;i++)
		{
			printf("%d",Table_board[j][i]);
		}
		printf("\n");
	}
*/	
}
/*   删除一行满的情况
 *   这里的y为具体哪一行为满
 */

int DelFullRow(int y)
{
	/*该行游戏板往下移一行*/
	int n,top=0;				/*top保存的是当前最高点,出现一行全空就表示为最点了,移动是到最高点结束*/
	register m,totoal;
	for(n=y;n>=0;n--)/*从当前行往上看*/
	{
		totoal=0;
		for(m=0;m<Horizontal_boxs;m++)
		{
			if(!Table_board[n][m].var)totoal++;				/*没占有方格+1*/
			if(Table_board[n][m].var!=Table_board[n-1][m].var)	/*上行不等于下行就把上行传给下行 xor关系*/
			{
				Table_board[n][m].var=Table_board[n-1][m].var;
				Table_board[n][m].color=Table_board[n-1][m].color;
			}
		}
		if(totoal==Horizontal_boxs)						/*发现上面有连续的空行提前结束*/
		{
			top=n;
			break;
		}
	}
	return(top);				/*返回最高点*/
}
/*找到一行满的情况*/
void setFullRow(int t_boardy)
{
	int n,full_numb=0,top=0;			/*top保存的是当前方块的最高点*/
	register m;
/*
t_boardy 口       5
         口       6
   口口口口口口   7
n  口口口口口口   8
 */
	for(n=t_boardy+3;n>=t_boardy;n--)
	{
		if(n<0 || n>=Vertical_boxs ){continue;}	/*超过低线了*/
		for(m=0;m<Horizontal_boxs;m++)			/*水平的方向*/
		{
			if(!Table_board[n+full_numb][m].var)break;		/*发现有一个是空就跳过该行*/
		}
		if(m==Horizontal_boxs)					/*找到满行了*/
		{
			if(n==t_boardy+3)					/*第一次献给了n,最高的*/
				top=DelFullRow(n+full_numb);		/*清除游戏板里的该行,并下移数据*/
			else
				DelFullRow(n+full_numb);
			full_numb++;						/*统计找到的行数*/
/*			printf(" %d ",m);*/
		}
	}
	if(full_numb)
	{
		int oldx,x=Sys_x,y=BSIZE*top+Sys_y;
		oldx=x;
		score=score+full_numb*2-1;				/*加分数*/
		/*这里相当于重显调色板*/
		for(n=top;n<t_boardy+4;n++)
		{
			if(n>=Vertical_boxs)continue;	/*超过低线了*/
			for(m=0;m<Horizontal_boxs;m++)	/*水平的方向*/
			{
				if(Table_board[n][m].var)
					setfillstyle(SOLID_FILL,Table_board[n][m].color);/*Table_board[n][m].color*/
				else
					setfillstyle(SOLID_FILL,BgColor);

				bar(x,y,x+BSIZE,y+BSIZE);
				line(x,y,x+BSIZE,y);
				line(x,y,x,y+BSIZE);
				line(x,y+BSIZE,x+BSIZE,y+BSIZE);
				line(x+BSIZE,y,x+BSIZE,y+BSIZE);
				x+=BSIZE;
			}
			y+=BSIZE;
			x=oldx;
		}
		ShowScore(score);
		if(speed!=score/speed_step)
		{
			speed=score/speed_step;
			ShowSpeed(speed);
		}

	}
}


/* 返回下个方块号
 * 
 */
int MkNextBox(int box_numb)
{

	int mask=128,t_boardx,t_boardy,n,m;
	t_boardx=(Curbox_x-Sys_x)/BSIZE;
	t_boardy=(Curbox_y-Sys_y)/BSIZE;
	for(n=0;n<4;n++)
	{
		for(m=0;m<4;m++)
		{
			if( ((shapes[current_box_numb].box[n/2]) & mask) )/*设置游戏板*/
			{
/*				bar(Curbox_x+m*BSIZE,y+n*BSIZE,Curbox_x+m*BSIZE+BSIZE,y+n*BSIZE+BSIZE);*/
				Table_board[t_boardy+n][t_boardx+m].var=1;/*这里设制游戏板*/
				Table_board[t_boardy+n][t_boardx+m].color=shapes[current_box_numb].color;/*这里设制游戏板*/
			}
			mask=mask/(2);
			if(mask==0)mask=128;
		}
	}
	setFullRow(t_boardy);
	Curbox_x=Sys_x+Begin_boxs_x*BSIZE,Curbox_y=Sys_y;/*再次初始化座标*/
	if(box_numb==-1)box_numb=rand()%MAX_BOX;
	current_box_numb=box_numb;
	flag_newbox=false;
	return(rand()%MAX_BOX);
}

/* 检查游戏板里和当前方块是否重叠

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -