俄罗斯方块源码

这是博主大一时做的一个小游戏,当时是纯兴趣使然。做成之后兴奋地手舞足蹈,玩的不亦乐乎。现在想来,喜悦不是来自游戏本身,而是自己独立完成的快感和编码的趣味。

现在把代码公布出来,一是备存,二是希望聪慧的你,能一眼看出其中的 bug,并告知我。同是天涯程序员,相助何须曾相识,对吧?

当时毕竟资历浅显,代码中如有看起来特别幼稚的地方,还请诸君万勿见笑!

#include <stdio.h>
#include <conio.h>
#include <time.h>
#include <windows.h>
#include <vld.h>

#define MAXWIDTH 24
#define MAXHEIGHT 24
#define BOXNUMBER 4
const int rx=MAXWIDTH+5,ry=MAXHEIGHT/3;
#define FIRSTSPEED 500

typedef enum num
{
	/*
	 *	one		I
	 *	two		O
	 *	three	        L
	 *	four	        J
	 *	five	        T
	 *	six		Z
	 *	seven	        S
	 */
	one,two,three,four,five,six,seven
}en;

typedef struct pos
{
	int x,y;
}position;

typedef struct point
{
	bool have;
	int color;
}point;

typedef struct box
{
	en style;
	position pos[BOXNUMBER];

}box;

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

void color(int a)//颜色函数
{
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),a);
}

void Interface(point arr[][MAXWIDTH])
{
	int i,j;
	for(i=0;i<MAXHEIGHT;i++)
	{
		for(j=0;j<MAXWIDTH;j++)
		{
			if(i==MAXHEIGHT-1||j==MAXWIDTH-1||j==0)
			{
				arr[i][j].have=1;
			}
		}
	}
	for(i=0;i<MAXHEIGHT;i++)
	{
		for(j=0;j<MAXWIDTH;j++)
		{
			if(1==arr[i][j].have)
				printf("■");

			else

				printf("  ");
		}

		printf("\n");
	}

	for (i=rx;i<rx+8;i++)
	{
		for (j=ry;j<ry+7;j++)
		{
			if (i==rx||i==rx+7||j==ry+7-1)
			{
				gotoxy(i,j);
				printf("■");
			}
			else
			{
				gotoxy(i,j);
				printf("  ");
			}
		}
	}

}

void cleanbox(box *b)
{
	int k;
	for (k=0;k<4;k++)
	{
		gotoxy(b->pos[k].x,b->pos[k].y);
		printf("  ");
	}
}

void CreateReady(box * ready)
{
	int ran,k;
	ran=rand()%7+1;
	/*
	 *	one		I
	 *	two		O
	 *	three	    L
	 *	four	    J
	 *	five	    T
	 *	six		Z
	 *	seven	    S
	 */
	cleanbox(ready);
	switch(ran)
	{
	case 1:
		ready->style=one;
		ready->pos[0].x=rx+2;
		ready->pos[0].y=ry+1;
		ready->pos[1].x=rx+2;
		ready->pos[1].y=ry+2;
		ready->pos[2].x=rx+2;
		ready->pos[2].y=ry+3;
		ready->pos[3].x=rx+2;
		ready->pos[3].y=ry+4;
		break;
	case 2:
		ready->style=two;
		ready->pos[0].x=rx+3;
		ready->pos[0].y=ry+2;
		ready->pos[1].x=rx+4;
		ready->pos[1].y=ry+2;
		ready->pos[2].x=rx+3;
		ready->pos[2].y=ry+3;
		ready->pos[3].x=rx+4;
		ready->pos[3].y=ry+3;
		break;
	case 3:
		ready->style=three;
		ready->pos[0].x=rx+3;
		ready->pos[0].y=ry+1;
		ready->pos[1].x=rx+3;
		ready->pos[1].y=ry+2;
		ready->pos[2].x=rx+3;
		ready->pos[2].y=ry+3;
		ready->pos[3].x=rx+4;
		ready->pos[3].y=ry+3;
		break;
	case 4:
		ready->style=four;
		ready->pos[0].x=rx+4;
		ready->pos[0].y=ry+1;
		ready->pos[1].x=rx+4;
		ready->pos[1].y=ry+2;
		ready->pos[2].x=rx+4;
		ready->pos[2].y=ry+3;
		ready->pos[3].x=rx+3;
		ready->pos[3].y=ry+3;
		break;
	case 5:
		ready->style=five;
		ready->pos[0].x=rx+2;
		ready->pos[0].y=ry+2;
		ready->pos[1].x=rx+3;
		ready->pos[1].y=ry+2;
		ready->pos[2].x=rx+4;
		ready->pos[2].y=ry+2;
		ready->pos[3].x=rx+3;
		ready->pos[3].y=ry+3;
		break;
	case 6:
		ready->style=six;
		ready->pos[0].x=rx+2;
		ready->pos[0].y=ry+2;
		ready->pos[1].x=rx+3;
		ready->pos[1].y=ry+2;
		ready->pos[2].x=rx+3;
		ready->pos[2].y=ry+3;
		ready->pos[3].x=rx+4;
		ready->pos[3].y=ry+3;
		break;
	case 7:
		ready->style=seven;
		ready->pos[1].x=rx+3;
		ready->pos[1].y=ry+2;
		ready->pos[0].x=rx+4;
		ready->pos[0].y=ry+2;
		ready->pos[2].x=rx+2;
		ready->pos[2].y=ry+3;
		ready->pos[3].x=rx+3;
		ready->pos[3].y=ry+3;
		break;
	}

	for(k=0;k<4;k++)
	{
		color(ready->style+8);
		gotoxy(ready->pos[k].x,ready->pos[k].y);
		printf("■");
	}
	color(0x07);
	gotoxy(MAXWIDTH,MAXHEIGHT);
}

void ConverttoNow(box * ready,box *now)
{
	int k;
	now->style=ready->style;
	for (k=0;k<4;k++)
	{
		now->pos[k].x=ready->pos[k].x-21;
		now->pos[k].y=ready->pos[k].y-(ry+2);
	}
	color(ready->style+8);
	for(k=0;k<4;k++)
	{
		gotoxy(now->pos[k].x,now->pos[k].y);
		printf("■");
	}
	color(0x07);
}

void change(box * now)
{
	int tmpx,tmpy;
	if (now->style==two)
	{
		return;
	}
	int k;
	for(k=0;k<4;k++)
	{
		gotoxy(now->pos[k].x,now->pos[k].y);
		printf("  ");
	}
	color(now->style+8);
	for (k=0;k<4;k++)
	{
		tmpx=now->pos[k].x;
		tmpy=now->pos[k].y;
		now->pos[k].x=-(tmpy-now->pos[1].y)+now->pos[1].x;
		now->pos[k].y=(tmpx-now->pos[1].x)+now->pos[1].y;
		gotoxy(now->pos[k].x,now->pos[k].y);
		printf("■");
	}
	color(0x07);
	gotoxy(MAXWIDTH,MAXHEIGHT);
}

void accelerate(int & speed)
{
	speed*=0.3;
}

void down(box * now)
{
	int k;
	for (k=0;k<4;k++)
	{
		gotoxy(now->pos[k].x,now->pos[k].y);
		printf("  ");
		now->pos[k].y++;
	}
	color(now->style+8);
	for(k=0;k<4;k++)
	{
		gotoxy(now->pos[k].x,now->pos[k].y);
		printf("■");
	}
	color(0x07);
	gotoxy(MAXWIDTH,MAXHEIGHT);
}

int left(box * now,point arr[][MAXWIDTH])
{
	int i,j,k;
	for (k=0;k<4;k++)
	{
		for (i=MAXHEIGHT;i>0;i--)
		{
			for (j=MAXWIDTH;j>0;j--)
			{
				if (arr[i][j-1].have==1&&now->pos[k].x==j&&now->pos[k].y==i)
				{
					return 0;
				}
			}
		}
	}
	for (k=0;k<4;k++)
	{
		gotoxy(now->pos[k].x,now->pos[k].y);
		printf("  ");
		now->pos[k].x--;
	}
	color(now->style+8);
	for(k=0;k<4;k++)
	{
		gotoxy(now->pos[k].x,now->pos[k].y);
		printf("■");
	}
	color(0x07);
	gotoxy(MAXWIDTH,MAXHEIGHT);
	return 1;
}

int right(box * now,point arr[][MAXWIDTH])
{
	int i,j,k;
	for (k=0;k<4;k++)
	{
		for (i=MAXHEIGHT;i>0;i--)
		{
			for (j=MAXWIDTH;j>0;j--)
			{
				if (arr[i][j+1].have==1&&now->pos[k].x==j&&now->pos[k].y==i)
				{
					return 0;
				}
			}
		}
	}
	for (k=0;k<4;k++)
	{
		gotoxy(now->pos[k].x,now->pos[k].y);
		printf("  ");
		now->pos[k].x++;
	}
	color(now->style+8);
	for(k=0;k<4;k++)
	{
		gotoxy(now->pos[k].x,now->pos[k].y);
		printf("■");
	}
	color(0x07);
	gotoxy(MAXWIDTH,MAXHEIGHT);
	return 1;
}

int IsBottom(const box *now,const point arr[][MAXWIDTH])
{
	int i,j,k;
	for (k=0;k<4;k++)
	{
		for (i=MAXHEIGHT;i>0;i--)
		{
			for (j=MAXWIDTH;j>0;j--)
			{
				if (arr[i][j].have==1&&now->pos[k].x==j&&now->pos[k].y+1==i)
				{
					return 1;
				}
			}
		}
	}
	return 0;
}

void ConverttoArr(box *now,point arr[][MAXWIDTH])
{
	int k;
	for (k=0;k<4;k++)
	{
		arr[now->pos[k].y][now->pos[k].x].have=1;
		arr[now->pos[k].y][now->pos[k].x].color=now->style;
	}
}

void CleanLine(point arr[][MAXWIDTH],int n)	//清除一行时设置颜色
{
	int i,j;
	for (j=1;j<MAXWIDTH-1;j++)
	{
		gotoxy(j,n);
		printf("  ");
	}
	for (i=n;i>=0;i--)
	{
		for (j=1;j<MAXWIDTH-1;j++)
		{
			arr[i][j].have=arr[i-1][j].have;
			if (arr[i][j].have==1)
			{
				gotoxy(j,i-1);
				printf("  ");
				gotoxy(j,i);
				color(arr[i][j].color+8);
				printf("■");
				color(0x07);
			}
		}
	}
}

int IsLine(point arr[][MAXWIDTH],int *score)
{
	int i,j;
	for (i=MAXHEIGHT-1-1;i>=0;i--)
	{
		for (j=1;j<MAXWIDTH-1;j++)
		{
			if (arr[i][j].have==0)
			{
				break;
			}
		}
		if (j==MAXWIDTH-1)
		{
			*score+=5;
			CleanLine(arr,i);
		}
	}
	return 1;
}

void showscore(const int const * score)
{
	gotoxy(rx,ry-5);
	printf("您的战绩:%d",*score);
	gotoxy(rx,ry-4);
	printf("按p暂停!");
	gotoxy(MAXWIDTH,MAXHEIGHT);
}

int main()
{
	//system("mode con cols=250 lines=250");
	box now,ready;
	int score=0;
	int speed=FIRSTSPEED;
	int ch=0;
	static point arr[MAXHEIGHT][MAXWIDTH];	//auto set 0
	Interface(arr);
	srand(time(NULL));
	CreateReady(&ready);
	ConverttoNow(&ready,&now);
	CreateReady(&ready);
	while(true)
	{
		if(kbhit())
		{
			ch=getch();			//key value is double bytes,so get twice
			if(ch==224)
			{
				ch=getch();
			}
		}
		if (IsBottom(&now,arr))
		{
			ConverttoArr(&now,arr);
			ConverttoNow(&ready,&now);
			CreateReady(&ready);
			speed=FIRSTSPEED;
		}
		IsLine(arr,&score);
		showscore(&score);
		switch (ch)
		{
		case 'p':
			;
			break;
		case 0:
label:
			down(&now);
			break;
		case 72:
			change(&now);
			ch=0;
			goto label;
			break;
		case 80:
			accelerate(speed);
			ch=0;
			break;
		case 75:
			if(left(&now,arr)==0)
			{
				goto label;
			}
			ch=0;
			break;
		case 77:
			if(right(&now,arr)==0)
			{
				goto label;
			}
			ch=0;
			break;
		default:
			break;
		}
		Sleep(speed);
	}
	return 0;
}