您的位置:首页 > 其它

俄罗斯方块机器人版

2010-11-21 09:43 183 查看
没事写的,自动摆放算法比较简单,大约为新手水平,以后会继续改进。。。



自动摆放算法:尽量消行,尽量往低了放,尽量不留空。。



#include<iostream>
#include<conio.h>
#include<windows.h>
#include <time.h>
#pragma comment(lib, "winmm.lib") 
using namespace std;
#define MAPSIZEH 20
#define MAPSIZEL 15

char GRA[24][4][4]=
{
	{0,0,0,0,0,1,1,0,0,1,1,0,0,0,0,0},	/*小田字格*/
	{0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0},	/*横*/
	{0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0},	/*竖*/
	{0,0,0,0,0,1,0,0,1,1,1,0,0,0,0,0},	/*上土*/
	{0,0,0,0,0,1,0,0,0,1,1,0,0,1,0,0},	/*右土*/
	{0,0,0,0,0,0,0,0,1,1,1,0,0,1,0,0},	/*下土*/
	{0,0,0,0,0,1,0,0,1,1,0,0,0,1,0,0},	/*左土*/
	{0,0,0,0,0,1,0,0,0,1,1,0,0,0,1,0},	/*Z*/
	{0,0,0,0,0,1,1,0,1,1,0,0,0,0,0,0},	/*Z*/
	{0,0,0,0,0,0,1,0,0,1,1,0,0,1,0,0},	/*Z*/
	{0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,0},	/*Z*/
	{0,0,0,0,0,1,1,0,0,0,1,0,0,0,1,0},	/*-|*/	
	{0,0,0,0,0,0,1,0,1,1,1,0,0,0,0,0},	/*__|*/
	{0,1,0,0,0,1,0,0,0,1,1,0,0,0,0,0},	/*||_*/
	{0,0,0,0,0,1,1,1,0,1,0,0,0,0,0,0},	/*|--*/
	{0,0,0,0,0,1,1,0,0,1,0,0,0,1,0,0},	/*||-*/
	{0,0,0,0,1,1,1,0,0,0,1,0,0,0,0,0},	/*--|*/
	{0,0,1,0,0,0,1,0,0,1,1,0,0,0,0,0},	/*_||*/
	{0,0,0,0,0,1,0,0,0,1,1,1,0,0,0,0},	/*|__*/
	{0,0,0,0,0,1,1,1,0,1,1,1,0,1,1,1},	/*超级大田*/
	{0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0},	/*大竖*/
	{0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0},	/*大横*/
	{0,0,0,0,0,1,0,0,1,1,1,0,0,1,0,0},	/*十*/
	{0,0,0,0,0,1,1,1,0,1,0,1,0,1,1,1},	/*空心大田*/
};
char MAP[MAPSIZEH][MAPSIZEL];		int STARTX,STARTY/*起始XY坐标*/,TYPE/*当前图形类型*/,NEXTTYPE/*下一个图形*/,SOCER/*当前分数*/,TURN[24]={0,2,1,4,5,6,3,8,7,10,9,12,13,14,11,16,17,18,15,19,21,20,22,23};	/*旋转状态跳转*/

struct move
{
	int x,y;
}move[4]={0,-1,0,1,1,0,0,0};	/*左右下和不动,不动的用于判定方块是否能旋转*/

bool decidemove(int type,int dis)			/*判断方块是否能够移动或旋转*/
{
	int i,j;
	for(i=0;i<4;i++)
		for(j=0;j<4;j++)
			if(GRA[type][i][j])
			{
				if(STARTX+i+move[dis].x<0||STARTX+i+move[dis].x>=MAPSIZEH||STARTY+j+move[dis].y<0||STARTY+j+move[dis].y>=MAPSIZEL||MAP[STARTX+i+move[dis].x][STARTY+j+move[dis].y]==1)
					return false;
			}
	return true;
}

void lockinmap(int s)				/*将方块固定在地图上*/
{
	int i,j;
	for(i=0;i<4;i++)					
		for(j=0;j<4;j++)
			if(GRA[TYPE][i][j])
				MAP[STARTX+i][STARTY+j]=s;
}

void moving(int type,int dis)	/*将方块在屏幕上移动*/
{
	lockinmap(0);					/*将MAP中的'2'置为0*/
						
	STARTX+=move[dis].x;	STARTY+=move[dis].y;		/*移动方块*/
	lockinmap(2);

}

void gotoxy(int x,int y)			/*移动光标*/
{
	COORD C;
	C.X = x;
	C.Y = y;
	SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),C);
}

void show()				/*显示屏*/
{
	gotoxy(0,0);
	int i,j;
	for(i=0;i<MAPSIZEH;i++,cout<<endl)
		for(j=0;j<MAPSIZEL;j++)
			if(MAP[i][j])
				cout<<"■";
			else
				cout<<"  ";
	gotoxy(MAPSIZEL*2+4,2);
	for(i=0;i<4;i++,gotoxy(MAPSIZEL*2+4,2+i))
		for(j=0;j<4;j++)
			if(GRA[NEXTTYPE][i][j])
				cout<<"■";
			else
				cout<<"  ";

	gotoxy(MAPSIZEL*2+4,2+10);
	cout<<" SCORE ";
	gotoxy(MAPSIZEL*2+4,2+12);
	cout<<"   "<<SOCER;
	gotoxy(MAPSIZEL*3+1,MAPSIZEH);
}

void creat()		/*生成随机方块*/
{
	STARTX=0;	STARTY=MAPSIZEL/2-1;
	TYPE=NEXTTYPE;
	srand((unsigned)time(NULL)+TYPE); 
	NEXTTYPE=rand()%19;			/*生成随机数*/
	if(decidemove(TYPE,3)==false)
	{
		system("cls");
		cout<<"   GAME  END"<<endl<<"YOUR SOCER IS ";
		PlaySound("end.wav",NULL,SND_ALIAS|SND_ASYNC); 
		Sleep(2000);
		cout<<SOCER<<endl;
		system("pause");
		exit(0);
	}
	moving(TYPE,3);
}

void check()		/*判定消行和记分函数*/
{
	int i,j,res=0,sum;
	for(i=MAPSIZEH-1;i>-1;i--)
	{
		for(j=MAPSIZEL-1,sum=0;j>-1;j--)
			sum+=MAP[i][j];
		if(sum==MAPSIZEL)					/*如果发现满行则消行*/
		{
			res++;
			int k=i,s;
			for(;k>0;k--)
				for(s=0;s<MAPSIZEL;s++)
					MAP[k][s]=MAP[k-1][s];
			memset(MAP,0,sizeof(char)*MAPSIZEL);
			i++;
		}
	}
	if(res)
		PlaySound("AK47A.wav",NULL,SND_ALIAS|SND_ASYNC); 
	else
		PlaySound("oned.wav",NULL,SND_ALIAS|SND_ASYNC);
	SOCER+=100*res*res;					/*消行分数计算*/
}

void  OnTime() 				/*回调函数*/
{
	
	if(true==decidemove(TYPE,2))
	{	moving(TYPE,2);	}
	else
	{
		lockinmap(1);
		check();
		creat();
	}
	show();
}

void operate(char op)	/*控制方块移动函数*/
{
	
	if(op=='a'||op=='A')
	{
		if(true==decidemove(TYPE,0))
		{	moving(TYPE,0);		show();}
		
	}
	else	if(op=='d'||op=='D')
	{
		if(true==decidemove(TYPE,1))
		{	moving(TYPE,1);	show();		}
	}
	else if(op=='w'||op=='W')
	{
		if(decidemove(TURN[TYPE],3)==true)
		{
			lockinmap(0);
			TYPE=TURN[TYPE];
			moving(TYPE,3);
			show();
			PlaySound("sound1.wav",NULL,SND_ALIAS|SND_ASYNC); 
		}
	}
	else	if(op=='s'||op=='S')
	{
		if(true==decidemove(TYPE,2))
			moving(TYPE,2);
		else
		{
			lockinmap(1);
			check();
			creat();
		}
		show();
	}
	else if(op==0x20)
	{
		while(true==decidemove(TYPE,2))
			moving(TYPE,2);
		lockinmap(1);
		check();
		creat();
		show();
	}
}

void first()				/*初始化界面*/
{
	memset(MAP,0,sizeof(MAP));
	SOCER=0;
	srand((unsigned)time(NULL));
	NEXTTYPE=rand()%20;
	creat();
	int i;
	show();
	for(i=0;i<MAPSIZEH;i++)
	{	gotoxy(MAPSIZEL*2,i);	cout<<"┃";			gotoxy(MAPSIZEL*3,i);	cout<<"┃";	}
	gotoxy(0,MAPSIZEH);
	for(i=0;i<MAPSIZEL*1.5;i++)
			cout<<"━";	
	
}

void BOT()
{
	int x,y,savetype,temp,max,maxl,maxtype,i,j,k,mapnum[4],l;
	while(1)				/*开始自动下方块*/
	{
		max=0;	savetype=TYPE;	x=STARTX;	y=STARTY;	maxl=STARTY;	maxtype=TYPE;
		
		for(;;)				/*遍历当前图形的几种旋转图形*/
		{

			while(decidemove(TYPE,0)==true)
				STARTY--;

			for(;;STARTX=x,STARTY++)					/*往右移动的所有情况*/
			{

				while(decidemove(TYPE,2)==true)			/*将图形下到底*/
					STARTX++;

				memset(mapnum,0,sizeof(mapnum));

				for(i=0;i<4&&STARTX+i<MAPSIZEH;i++)		/*统计STARTX开始的那四行原来有的方块数*/
					for(j=0;j<MAPSIZEL;j++)
						if(MAP[STARTX+i][j]==1)
							mapnum[i]++;

				for(i=0;i<4&&STARTX+i<MAPSIZEH;i++)		/*如果将当前图形插入后每行几个块*/
					for(j=0;j<4;j++)
						if(GRA[TYPE][i][j])
							mapnum[i]++;

				for(i=0,l=0,temp=0;i<4;i++)										/*开始记分*/
					for(j=0;j<4;j++)
						if(GRA[TYPE][i][j])
						{
							
							for(k=1;STARTX+i+k<MAPSIZEH;k++)
								if(MAP[STARTX+i+k][STARTY+j]==0&&(i+k>3||(i+k<4&&GRA[TYPE][i+k][j]==0)))
									l++;
								else
								{	temp+=1;	break;	}
								k=i;
						}
				if(l<8)
					temp-=l*10;
					
				temp+=(k+STARTX)*10;
				for(i=0,k=0;i<4;i++)							/*能消一行就加1000分*/
					if(mapnum[i]==MAPSIZEL)
						k++;		
				temp+=1000*k;
				if(temp>max)
				{
					maxl=STARTY;
					maxtype=TYPE;
					max=temp;
				}
				STARTX=x;
				if(decidemove(TYPE,1)==false)
					break;
			}
			STARTX=x;	STARTY=y;
			if(decidemove(TURN[TYPE],3)==true)				/*如果图形不能旋转就停止,旋转回原图形也停止*/
				TYPE=TURN[TYPE];
			else
				break;
			if(savetype==TYPE)
				break;

		}
		/*找到位置后开始控制*/

		TYPE=savetype;	STARTX=x;	STARTY=y;

		while(TYPE!=maxtype)			/*旋转到目标图形*/
		{
			operate('w');
//			Sleep(100);
		}

		char o='a';

		if(maxl>STARTY)
			o='d';
		
		while(STARTY!=maxl)				/*移动到目标列*/
		{
			operate(o);
//			Sleep(100);
		}
		
		operate(0x20);
//		Sleep(100);
	}

}

int main()
{
	first();			/*初始化界面*/
	while(1)			/*进入游戏*/
		BOT();

	return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: