#include<bits/stdc++.h>
#include<windows.h>
#include<unistd.h>
#include<conio.h>
#include<time.h>
#define cls system("cls")
#define pause system("pause")
#define two_price 50
#define four_price 99
#define mp_price 599
using namespace std;
int two[20]={0,0,0,0,0,1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192};
bool flag_two,flag_four,flag_mp;
int mp_len=4;
int mp[10][10];
int dx[10]={0,1,-1,0,0};
int dy[10]={0,0,0,1,-1};
bool flag=false;
bool vis[10][10];
bool doing()
{
	for(int i=1;i<=mp_len;i++)
	{
		for(int j=1;j<=mp_len;j++)
		{
			if(mp[i][j]==0)return true;
			for(int k=1;k<=4;k++)
			{
				if(mp[i][j]==mp[i+dx[k]][j+dy[k]])
				return true;
			}
		}
	}
	return false;
 } 
int twice(int a,int b)//先实际,后 标准
{
	if(a<b)return -twice(b,a);
	else if(b==0)return twice(a,1)+1;
	int c=a/b;
	int cnt=0;
	while(c!=1)
	{
		c/=2;
		cnt++;
	}
	return cnt;
}
void gotoxy(int x, int y) {
	COORD pos = {x,y};
	HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);// 获取标准输出设备句柄
	SetConsoleCursorPosition(hOut, pos);//两个参数分别是指定哪个窗体,具体位置
}

//----------隐藏光标----------
void HideTheCursor() {
	CONSOLE_CURSOR_INFO cciCursor;
	HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);

	if(GetConsoleCursorInfo(hStdOut, &cciCursor)) {
		cciCursor.bVisible = FALSE;
		SetConsoleCursorInfo(hStdOut, &cciCursor);
	}
}
int jifen=100,max_mp,aim,sum;
void shu()
{
	cls;
	cout<<"最高分值为:"<<max_mp;
	cout<<"\n总和为:"<<sum<<"\n";
	cout<<"\n目标分值为:"<<aim<<'\n';
	if(max_mp>=aim)
	{
		cout<<"你达到了目标分数\n";
		cout<<"积分+"<<twice(max_mp,aim)+aim+sum;
		jifen+=twice(max_mp,aim)+aim+sum;
	}
	else
	{
		cout<<"你没有达到目标分数\n";
		if(twice(max_mp,aim)+max_mp-aim+sum<0)
		{
			cout<<"积分"<<twice(max_mp,aim)+max_mp-aim+sum;
		}
		
		else
		{
			cout<<"鉴于你表现优异,积分+"<<twice(max_mp,aim)+max_mp-aim+sum;
		}
		jifen+=twice(max_mp,aim)+max_mp-aim+sum;
	}			
	Sleep(5000);
	cout<<"\n按任意键重开。\n";
	getch();
}
bool is_two(int a)
{
	for(int i=1;i<=15;i++)
	{
		if(a==pow(2,i))
		{
			return true;
		}
	}
	return false;
}
void mu()
{
	cls;
	cout<<"请输入目标分值(大于等于32且小于等于1024的2的幂次,如果输错,则默认为128)\n";
	cin>>aim;
	if(is_two(aim)&&aim>=32&&aim<=1024);
	else aim=128;
	cout<<"你的目标分数为:" <<aim<<"\n";
	pause;
	cls;
}
int two_cnt,four_cnt,mp_cnt;
void shangchen()
{
	cls;
	while(1)
	{
		gotoxy(0,0);
		cout<<"欢迎来到积分商城";
		cout<<"\n积分数:"<<jifen;
		cout<<"\n双倍卡:"<<two_cnt<<"个";
		cout<<"\n四倍卡:"<<four_cnt<<"个";
		cout<<"\n扩大地图:"<<mp_cnt<<"个";
		cout<<"\n[1]双倍卡:一局内所有数字乘2(50积分)";//two_cnt,two_price
		cout<<"\n[2]四倍卡:一局内所有数字乘4(99积分)";//four_cnt,four_price
		cout<<"\n[3]扩大地图:一局内地图长、宽各扩大至2倍(599积分)";// mp_cnt,mp_price
		cout<<"\n[Esc]退出\n";
		char v=getch();
		int x;
		if(v!=(char)27)
		{
			cout<<"请输入购买数量:";
			cin>>x;
		 } 
		if(x<0)
		{
			cout<<"错误";
			continue;
		}
		if(v=='1')
		{
			
			if(jifen>=x*two_price)
			{
				two_cnt+=x;
				jifen-=two_cnt*two_price;
				cout<<"\n剩余积分:"<<jifen<<"\n\n"; 
			}
			else cout<<"\n积分不足\n";
		} 
		else if(v=='2')
		{
			
			if(jifen>=x*four_price)
			{
				four_cnt+=x;
				jifen-=four_cnt*four_price;
				cout<<"\n剩余积分:"<<jifen; 
			}
			else cout<<"\n积分不足\n";
		} 
		else if(v=='3')
		{
			
			if(jifen>=x*mp_price)
			{
				mp_cnt+=x;
				jifen-=mp_cnt*mp_price;
				cout<<"\n剩余积分:"<<jifen; 
			}
			else cout<<"\n积分不足\n";
		} 
		else if(v==(char)27)
		{
			break;
		}
		pause;
	}

}
void zhuang_bei()
{
	cls;
	while(1)
	{
		cls;
		if(two_cnt==0&&four_cnt==0&&mp_cnt==0) 
		{
			cout<<"没有装备\n";
			pause;
			break;
		}
		if(two_cnt>0||four_cnt>0||mp_cnt>0)
		{
			cout<<"是否使用装备?\n[Y]是\n[N]否";
			char f=getch();
			if(f=='y'||f=='Y')
			{
				cout<<"\n\n请选择:\n[1]双倍卡\n[2]四倍卡\n[3]扩大地图\n[Esc]退出\n";
				char z=getch();
				if(z=='1')
				{
					if(two_cnt<=0)
					{
						cout<<"没有此项装备\n";
						pause;
					}
					else
					{
						two_cnt--;
						cout<<"已使用\n双倍卡:"<<two_cnt<<"个\n";
						pause; 
						flag_two=true;
					}
				}
				else if(z=='2')
				{
					if(four_cnt<=0)
					{
						cout<<"没有此项装备\n";
						pause;
					}
					else
					{
						four_cnt--;
						cout<<"已使用\n四倍卡:"<<four_cnt<<"个\n";
						pause; 
						flag_four=true;
					}
				}
				else if(z=='3')
				{
					if(mp_cnt<=0)
					{
						cout<<"没有此项装备\n";
						pause;
					}
					else
					{
						mp_cnt--;
						cout<<"已使用\n扩大地图:"<<mp_cnt<<"个\n";
						pause; 
						flag_mp=true;
					}
				}
				else if(z==(char)27)
				{
					break;
				}
			 } 
			else if(f=='n'||f=='N')
			{
				break;
			}
		}		
	}

}
void start_2048()
{
	HideTheCursor();
	cls;
	while(1)
	{
		gotoxy(0,0);
		if(flag_mp)mp_len=8;
		cout<<"地图大小:"<<mp_len<<"×"<<mp_len;	
		int flag=rand()%4+1;
		cout<<"小贴士:按Esc退出(不保留记录)\n小贴士:按Tab退出(保留记录)\n小贴士:按q更改目标分数\n小贴士:按p进入积分商城\n小贴士:按r换装备\n";
		for(int i=1;i<=mp_len;i++)
		{
			for(int j=1;j<=mp_len;j++)
			{
				if(mp[i][j]==0&&flag)
				{
					flag--;
					mp[i][j]=two[rand()%8];
					if(flag_two)
					{
						mp[i][j]*=2;
					}
					else if(flag_four)
					{
						mp[i][j]*=4;
					}
				}
				cout<<mp[i][j];
				if(mp[i][j]>=0&&mp[i][j]<10)
				{
					cout<<"    ";//五个 
				}
				else if(mp[i][j]>=10&&mp[i][j]<=100)
				{
					cout<<"   ";//四个 
				}
				else if(mp[i][j]>100&&mp[i][j]<=1000)
				{
					cout<<"  ";//三个 
				}
				else if(mp[i][j]>=1000&&mp[i][j]<10000)
				{
					cout<<" ";//两个 
				}
				max_mp=max(max_mp,mp[i][j]);
				sum+=mp[i][j];
			}
			cout<<"\n\n";
			
		 } 
		cout<<"\n最高值为"<<max_mp<<"\n";
		cout<<"\n总和为"<<sum<<"\n";
		cout<<"\n目标分值为:"<<aim<<"\n";
		char c=getch();
		if(c==(char)9)
		{
			shu();
			flag_two=false;
			flag_four=false;
			flag_mp=false;
			break;
		}
		else if(c==(char)27)
		{
			break;
		}
		else if(c=='q')
		{
			mu();
		 } 
		else if(c=='p')
		{
			shangchen();
		}
		if(c=='w')
		{
			for(int i=2;i<=mp_len;i++)
			{
				for(int j=1;j<=mp_len;j++)
				{
					if(mp[i-1][j]==mp[i][j])
					{
						mp[i-1][j]*=2;
						mp[i][j]=0;
					}
					else if(mp[i-1][j]==0)
					{
						mp[i-1][j]=mp[i][j];
						mp[i][j]=0;
					}
				}
			}
		}
		if(c=='s')
		{
			for(int i=1;i<=mp_len-1;i++)
			{
				for(int j=1;j<=mp_len;j++)
				{
					if(mp[i+1][j]==mp[i][j])
					{
						mp[i+1][j]*=2;
						mp[i][j]=0;
					}
					else if(mp[i+1][j]==0)
					{
						mp[i+1][j]=mp[i][j];
						mp[i][j]=0;
					}					
				}
			}
		}
		if(c=='a')
		{
			for(int i=1;i<=mp_len;i++)
			{
				for(int j=2;j<=mp_len;j++)
				{
					if(mp[i][j-1]==mp[i][j])
					{
						mp[i][j-1]*=2;
						mp[i][j]=0;
					}
					else if(mp[i][j-1]==0)
					{
						mp[i][j-1]=mp[i][j];
						mp[i][j]=0;
					}					
				}
			}
		}
		if(c=='d')
		{
			for(int i=1;i<=mp_len;i++)
			{
				for(int j=1;j<=mp_len-1;j++)
				{
					if(mp[i][j+1]==mp[i][j])
					{
						mp[i][j+1]*=2;
						mp[i][j]=0;
					}
					else if(mp[i][j+1]==0)
					{
						mp[i][j+1]=mp[i][j];
						mp[i][j]=0;
					}					
				}
			}
		}
		else if(c=='r')
		{
			cls;
			zhuang_bei();
		}
		
		if(!doing())
		{
			cout<<"你输了\n";
			flag_two=false;
			flag_four=false;
			flag_mp=false;
			shu();
			break;
		}
		sum=0;
		
	}
	sum=0;
 } 

int main()
{
	aim=128;
	while(1)
	{
		
		max_mp=-1;
		for(int i=1;i<=mp_len;i++)
		{
			for(int j=1;j<=mp_len;j++)
			{
				mp[i][j]=0;
			}
		}
		system("title 2048");
		srand(time(0));
		if(flag_mp)
		{
			mp_len=8;
			cout<<"已使用双倍地图\n\n";
		}
		cout<<"地图大小"<<mp_len<<"×"<<mp_len<<"\n\n"; 
		cls;
		cout<<"2048游戏欢迎您\n积分:"<<jifen<<"\n";
		cout<<"[1]开始\n[2]设置目标分数\n[3]积分商城\n[4]使用装备\n";
		char x=getch();
		if(x=='1')
		{
			start_2048();			
		}
		else if(x=='2')
		{
			mu();
		}
		else if(x=='3')
		{
			shangchen();
		}
		else if(x=='4')
		{
			zhuang_bei();
		}
	}
	return 0;
}