#include <bits/stdc++.h>
using namespace std;
//类
class Game{
private:
unsigned long long best;//最高分
unsigned long long score;//当前得分
int map[4][4];//游戏界面
int memory[9][4][4];//游戏记录(0~9步)
int steps;
string w,a,s,d;
public:
//初始化
Game(unsigned long long Best)
{
srand(time(NULL));
best=Best;
score=0;
steps=0;
w="w";
a="a";
s="s";
d="d";
for(int i=0;i<9;i++)
for(int j=0;j<4;j++)
for(int k=0;k<4;k++)
memory[i][j][k]=0;
//生成随机地图
for(int i=0;i<4;i++)
for(int j=0;j<4;j++)
map[i][j]=0;
int x,y;
for(int i=0;i<3;)//在三个不同的随机位置生成2
{
x=rand()%4;
y=rand()%4;
if(map[x][y])
continue;
map[x][y]=2;
i++;
}
if(!(rand()%3))//33%的概率产生一个随机位置的4
map[rand()%4][rand()%4]=4;
}
//求数字位数(0是0位数)
int Get_digit(int x)
{
int digit=0;
while(x)
{
x/=10;
digit++;
}
return digit;
}
//获得最大位数
int Max_digit(int list[][4])
{
int max=list[0][0];//max接收最大数字
for(int i=0;i<4;i++)
for(int j=0;j<4;j++)
if(max<list[i][j])
max=list[i][j];
return Get_digit(max);
}
//打印分割线
void Print_separator(int list[4][4])
{
for(int i=0;i<4;i++)
{
cout<<"+";
for(int j=0;j<Max_digit(list)+2;j++)
cout<<"-";
}
cout<<"+"<<endl;
}
//输出棋盘界面
void Print_map(int list[4][4])
{
Print_separator(list);
for(int i=0;i<4;i++)
{
for(int j=0;j<4;j++)
{
cout<<"| ";
if(list[i][j])
{
cout<<list[i][j];
for(int p=0;p<Max_digit(list)-Get_digit(list[i][j])+1;p++)
cout<<" ";
}
else
{
for(int p=0;p<Max_digit(list)+1;p++)
cout<<" ";
}
}
cout<<"|"<<endl;
Print_separator(list);
}
}
//输出游戏界面
void print()
{
if(best<score)
best=score;
cout<<"\n\n最高分:" <<best<<"\n当前得分:"<<score<<endl;// 输出得分
Print_map(map);
}
//记忆更迭
void Get_memory()
{
if(steps==9)
{
for(int i=0;i<8;i++)
for(int j=0;j<4;j++)
for(int k=0;k<4;k++)
memory[i][j][k]=memory[i+1][j][k];
for(int i=0;i<4;i++)
for(int j=0;j<4;j++)
memory[8][i][j]=map[i][j];
}
else
{
for(int i=0;i<4;i++)
for(int j=0;j<4;j++)
memory[steps][i][j]=map[i][j];
steps++;
}
}
//移动方块w
void Move_w()
{
//更迭记忆
Get_memory();
for(int j=0;j<4;j++)
{
int base=0;
int temp[4]={0,0,0,0};//用于存放移动后的行或列
for(int i=0;i<4;i++)
if(map[i][j])
{
temp[base]=map[i][j];
base++;
}
for(int i=0;i<3;i++)//处理相同方块的合并
{
if(temp[i]==temp[i+1])
{
temp[i]*=2;
score+=temp[i];
for(int p=i+1;p<3;p++)
temp[p]=temp[p+1];
temp[3]=0;
}
}
for(int i=0;i<4;i++)//将移动后的temp整合到list中
map[i][j]=temp[i];
}
//判断不能移动
int check=1;
for(int j=0;j<4;j++)
check*=map[3][j];
if(check)
{
cout<<"\n\n无法移动!\n\n\n";
return;
}
//生成新的方块
srand(time(NULL));
int j;
while(1)
{
j=rand()%4;
if(map[3][j])//当随机生成的位置有数字时,重新生成随机位置
continue;
if(rand()%3)//66%概率生成2
map[3][j]=2;
else//33%概率生成4
map[3][j]=4;
break;
}
}
//移动方块s
void Move_s()
{
//更迭记忆
Get_memory();
for(int j=0;j<4;j++)
{
int base=3;
int temp[4]={0,0,0,0};//用于存放移动后的行或列
for(int i=3;i>=0;i--)
if(map[i][j])
{
temp[base]=map[i][j];
base--;
}
for(int i=3;i>0;i--)//处理相同方块的合并
{
if(temp[i]==temp[i-1])
{
temp[i]*=2;
score+=temp[i];
for(int p=i-1;p>0;p--)
temp[p]=temp[p-1];
temp[0]=0;
}
}
for(int i=3;i>=0;i--)//将移动后的temp整合到list中
map[i][j]=temp[i];
}
//判断不能移动
int check=1;
for(int j=0;j<4;j++)
check*=map[0][j];
if(check)
{
cout<<"\n\n无法移动!\n\n\n";
return;
}
//生成新的方块
srand(time(NULL));
int j;
while(1)
{
j=rand()%4;
if(map[0][j])//当随机生成的位置有数字时,重新生成随机位置
continue;
if(rand()%3)//66%概率生成2
map[0][j]=2;
else//33%概率生成4
map[0][j]=4;
break;
}
}
//移动方块a
void Move_a()
{
//更迭记忆
Get_memory();
for(int i=0;i<4;i++)
{
int base=0;
int temp[4]={0,0,0,0};//用于存放移动后的行或列
for(int j=0;j<4;j++)
if(map[i][j])
{
temp[base]=map[i][j];
base++;
}
for(int j=0;j<3;j++)//处理相同方块的合并
{
if(temp[j]==temp[j+1])
{
temp[j]*=2;
score+=temp[j];
for(int p=j+1;p<3;p++)
temp[p]=temp[p+1];
temp[3]=0;
}
}
for(int j=0;j<4;j++)//将移动后的temp整合到list中
map[i][j]=temp[j];
}
//判断不能移动
int check=1;
for(int i=0;i<4;i++)
check*=map[i][3];
if(check)
{
cout<<"\n\n无法移动!\n\n\n";
return;
}
//生成新的方块
srand(time(NULL));
int j;
while(1)
{
j=rand()%4;
if(map[j][3])//当随机生成的位置有数字时,重新生成随机位置
continue;
if(rand()%3)//66%概率生成2
map[j][3]=2;
else//33%概率生成4
map[j][3]=4;
break;
}
}
//移动方块d
void Move_d()
{
//更迭记忆
Get_memory();
for(int i=0;i<4;i++)
{
int base=3;
int temp[4]={0,0,0,0};//用于存放移动后的行或列
for(int j=3;j>=0;j--)
if(map[i][j])
{
temp[base]=map[i][j];
base--;
}
for(int j=3;j>0;j--)//处理相同方块的合并
{
if(temp[j]==temp[j-1])
{
temp[j]*=2;
score+=temp[j];
for(int p=j-1;p>0;p--)
temp[p]=temp[p-1];
temp[0]=0;
}
}
for(int j=3;j>=0;j--)//将移动后的temp整合到list中
map[i][j]=temp[j];
}
//判断不能移动
int check=1;
for(int i=0;i<4;i++)
check*=map[i][0];
if(check)
{
cout<<"\n\n无法移动!\n\n\n";
return;
}
//生成新的方块
srand(time(NULL));
int j;
while(1)
{
j=rand()%4;
if(map[j][0])//当随机生成的位置有数字时,重新生成随机位置
continue;
if(rand()%3)//66%概率生成2
map[j][0]=2;
else//33%概率生成4
map[j][0]=4;
break;
}
}
//判断游戏是否结束 (结束:false 未结束:true)
bool Check_end()
{
for(int i=0;i<4;i++)
for(int j=0;j<4;j++)
if(map[i][j]==0)
return true;
for(int i=0;i<3;i++)
for(int j=0;j<4;j++)
if(map[i][j]==map[i+1][j])
return true;
for(int i=0;i<4;i++)
for(int j=0;j<3;j++)
if(map[i][j]==map[i][j+1])
return true;
return false;
}
//拓展功能
void Set()
{
cout<<"\n----拓展设置----\n";
cout<<"1:自定义移动操作\n";
cout<<"2:作弊操作-替换方块\n";
cout<<"3:作弊操作-删除方块\n";
cout<<"4:作弊操作-记忆回溯\n";
cout<<"0:返回\n";
string input;
while(1)
{
cin>>input;
if(input=="0" or input=="1" or input=="2" or input=="3" or input=="4")
break;
else
{
cout<<"\n输入信息有误!\n请重新输入!\n\n";
cout<<"1:自定义移动操作\n";
cout<<"2:作弊操作-替换方块\n";
cout<<"3:作弊操作-删除方块\n";
cout<<"4:作弊操作-记忆回溯\n";
cout<<"0:返回\n";
}
}
if(input=="1")
Self_design();
else if(input=="2")
Cheat_replace();
else if(input=="3")
Cheat_delete();
else if(input=="4")
Cheat_memory();
}
//自定义操作
void Self_design()
{
cout<<"\n您已进入自定义操作界面!\n为确保程序运行,请不要将setting作为移动指令!\n";
string input;
//w
cout<<"\n请输入新的上移指令(原"<<w<<"指令)\n";
while(1)
{
cin>>input;
if(input=="setting")
cout<<"\n不可使用setting作为新的移动指令!\n";
else if(input==w or input==a or input==s or input==d)
cout<<"\n输入的新指令与已有的原指令重复!\n请重输!\n\n";
else
break;
cout<<"请输入新的上移指令(原"<<w<<"指令)\n";
}
cout<<"已将上移指令由"<<w<<"更改为"<<input<<endl;
w=input;
//a
cout<<"\n请输入新的左移指令(原"<<a<<"指令)\n";
while(1)
{
cin>>input;
if(input=="setting")
cout<<"\n不可使用setting作为新的移动指令!\n";
else if(input==w or input==a or input==s or input==d)
cout<<"\n输入的新指令与已有的原指令重复!\n请重输!\n\n";
else
break;
cout<<"请输入新的左移指令(原"<<a<<"指令)\n";
}
cout<<"已将左移指令由"<<a<<"更改为"<<input<<endl;
a=input;
//s
cout<<"\n请输入新的下移指令(原"<<s<<"指令)\n";
while(1)
{
cin>>input;
if(input=="setting")
cout<<"\n不可使用setting作为新的移动指令!\n";
else if(input==w or input==a or input==s or input==d)
cout<<"\n输入的新指令与已有的原指令重复!\n请重输!\n\n";
else
break;
cout<<"请输入新的下移指令(原"<<s<<"指令)\n";
}
cout<<"已将下移指令由"<<s<<"更改为"<<input<<endl;
s=input;
//d
cout<<"\n请输入新的右移指令(原"<<d<<"指令)\n";
while(1)
{
cin>>input;
if(input=="setting")
cout<<"\n不可使用setting作为新的移动指令!\n";
else if(input==w or input==a or input==s or input==d)
cout<<"\n输入的新指令与已有的原指令重复!\n请重输!\n\n";
else
break;
cout<<"请输入新的右移指令(原"<<d<<"指令)\n";
}
cout<<"已将右移指令由"<<d<<"更改为"<<input<<endl;
d=input;
}
//替换
void Cheat_replace()
{
cout<<"\n您已进入方块替换操作界面!\n";
string input,num;
while(1)
{
cout<<"请输入替换方块的对应坐标\n输入格式:(行,列)\n行:1~4\t列:1~4\n";
cin>>input;
if(input[0]=='(' and '1'<=input[1] and input[1]<='4' and input[2]==',' and '1'<=input[3] and input[3]<='4' and input[4]==')' and input[5]==0)
break;
cout<<"\n输入有误!\n请重新输入!\n\n" ;
}
while(1)
{
cout<<"\n请输入替换数字\n";
cout<<"输入格式:2^n\nn:1~9\n将"<<input<<"位置上的";
if(map[input[1]-'1'][input[3]-'1']!=0)
cout<<map[input[1]-'1'][input[3]-'1'];
else
cout<<"空方格";
cout<<"替换为:";
cin>>num;
if(num[0]=='2' and num[1]=='^' and '1'<=num[2] and num[2]<='9' and num[3]==0)
break;
cout<<"\n输入有误!\n请重新输入!\n\n" ;
}
int replace=1;
for(int i=0;i<num[2]-'0';i++)
replace*=2;
cout<<"\n已将"<<input<<"位置上的";
if(map[input[1]-'1'][input[3]-'1']!=0)
cout<<map[input[1]-'1'][input[3]-'1'];
else
cout<<"空方格";
cout<<"替换为:"<<replace<<endl;
map[input[1]-'1'][input[3]-'1']=replace;
}
//删除
void Cheat_delete()
{
cout<<"\n您已进入方块删除操作界面!\n";
string input;
while(1)
{
cout<<"请输入删除方块的对应坐标\n输入格式:(行,列)\n行:1~4\t列:1~4\n";
cin>>input;
if(input[0]=='(' and '1'<=input[1] and input[1]<='4' and input[2]==',' and '1'<=input[3] and input[3]<='4' and input[4]==')' and input[5]==0)
break;
cout<<"\n输入有误!\n请重新输入!\n\n" ;
}
cout<<"\n已将"<<input<<"位置上的";
if(map[input[1]-'1'][input[3]-'1']!=0)
cout<<map[input[1]-'1'][input[3]-'1'];
else
cout<<"空方格";
cout<<"删除\n";
map[input[1]-'1'][input[3]-'1']=0;
}
//回溯
void Cheat_memory()
{
cout<<"\n您已进入记忆回溯操作界面!\n";
if(!steps)
{
cout<<"\n目前暂无回溯记录!\n";
return;
}
for(int i=0;i<steps;i++)
{
cout<<"回溯"<<i+1<<":"<<endl;
Print_map(memory[i]);
cout<<"\n\n";
}
string input;
while(1)
{
cout<<"请选择回溯位置:\n";
cout<<"输入格式:n\n";
cout<<"n:1~"<<steps<<endl;
cin>>input;
if('1'<=input[0] and input[0]<=('0'+steps) and input[1]==0)
break;
else
cout<<"\n输入有误!\n请重新输入!\n\n" ;
}
for(int i=0;i<4;i++)
for(int j=0;j<4;j++)
map[i][j]=memory[input[0]-'1'][i][j];
cout<<"\n已经回溯至位置:回溯"<<input[0]<<endl;
steps=input[0]-'1';
}
//游戏程序
unsigned long long Play_game()
{
while(Check_end())
{
if(best<score)
best=score;
print();
string input;
cout<<"请输入操作\n上移:"<<w<<"\n下移:"<<s<<"\n左移:"<<a<<"\n右移:"<<d<<"\n拓展:setting"<<"\n退出:quit\n";
while(1)
{
cin>>input;
if(input==w or input==s or input==a or input==d or input=="setting" or input=="quit")
break;
else
{
cout<<"\n\n输入有误!\n请重新输入!\n";
print();
cout<<"请输入操作\n上移:"<<w<<"\n下移:"<<s<<"\n左移:"<<a<<"\n右移:"<<d<<"\n退出:quit\n";
}
}
if(input==w)
Move_w();
else if(input==s)
Move_s();
else if(input==a)
Move_a();
else if(input==d)
Move_d();
else if(input=="setting")
Set();
else if(input=="quit")
break;
system("cls");
}
cout<<"\n游戏已结束!\n本次得分为:"<<score<<"\n\n否开启新游戏?\n是(yes)\n否(no)\n";
return best;
}
};
int main()
{
unsigned long long best=0;
while(1)
{
Game G_2048(best);
best=G_2048.Play_game();
while(1)
{
string ask;
cin>>ask;
if(ask=="yes")
{
cout<<"\n已为您开启了新的游戏\n";
system("cls");
break;
}
else if(ask=="no")
{
system("cls");
cout<<"\n游戏已退出\n游戏最高分为:"<<best<<endl;
return 0;
}
else
cout<<"\n输入信息有误!\n请重新输入\n\n是否开启新游戏?\n是(yes)\n否(no)\n";
}
}
return 0;
}