#include <cstdio>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <vector>
#include <conio.h>
#include <windows.h>
#include<iostream>
using namespace std;
int table[16]={0},Score=0,Max_number=0;
bool allprint=true;
int&at(int* pn,int x,int y=-1,bool rev=false){
return rev?(~y?pn[x*4+y]:pn[x]):(~y?pn[y*4+x]:pn[x]);
}
bool canMove(int* pn,int direction){
for(int i=0,sum=0;i<4;i++){
for(int j=0;j<4;j++){
if(!at(pn,i,j,direction==0))return true;
if(j&&at(pn,i,j,direction==0)==at(pn,i,j-1,direction==0))return true;
}
}
return false;
}
void gotoxy(int x,int y){
COORD c; c.X=x;c.Y=y;
SetConsoleCursorPosition (GetStdHandle(STD_OUTPUT_HANDLE),c);
}
void random_insert(int* pn){
int dataCount=0;
for(int i=0;i<16;i++)
if(pn[i])
dataCount++;
if(dataCount==16)
return;
int index=rand()%(16-dataCount);
int iScan=0;
while(pn[iScan]||index--)iScan++;
pn[iScan]=(rand()%10)?2:4;
}
int cur_direction(int* pn,int direct,bool visual=false,int* callcount=NULL,int* squareCount=NULL,bool noinsert=false){
int _score=0,sum=0,square=0,flag=1;
bool isReverse=direct%2==0;
for(int iLine=0;iLine<4;iLine++){
vector<int> line;
for(int i=(isReverse?0:3);i!=(isReverse?4:-1);i+=(isReverse?1:-1)){
if(at(pn,iLine,i,direct>1))line.push_back(at(pn,iLine,i,direct>1));
flag=1;
while(flag){
flag=0;
for(int k=1;k<line.size();k++)
if(line[k-1]==line[k]){
line[--k]*=2;
_score+=line[k];
if(Max_number<line[k])Max_number=line[k];
line.erase(line.begin()+k+1);
flag++;
}
sum+=flag;
}
}
if(!visual)
for(int i=(isReverse?0:3);i!=(isReverse?4:-1);i+=(isReverse?1:-1)){
if(line.empty())at(pn,iLine,i,direct>1)=0;
else{
at(pn,iLine,i,direct>1)=line[0];
line.erase(line.begin());
}
}
for(int i=1;i<line.size();i++)
if(line[i-1]*2==line[i]||line[i-1]==2*line[i])
square+=line[i]-line[i-1];
}
if(callcount)(*callcount)=sum;
if(squareCount)(*squareCount)=abs(square);
if((!visual)&&(!noinsert))random_insert(pn);
return _score;
}
bool isConinue(int *pn=table){
int dataCount=0;
for(int i=0;i<16;i++)if(at(pn,i,-1,false))dataCount++;
return dataCount<16||cur_direction(table,0,true)||cur_direction(table,2,true);
}
void print(){
if(!allprint)return;
gotoxy(0,0);
printf("2048-GameTable designed by X.P.Y\nScore:%d \n\n\n",Score); //x=1
for(int i=0;i<16;i++){
gotoxy((i%4+1)*5+1,(i/4+1)*2+1);
printf("%d ",table[i]);
}
gotoxy(0,11);
}
int ai_calculate(){
bool canv=canMove(table,0),canh=canMove(table,1);
if(!(canv&&canh))return canv?2:0;
int sum[4]={0},score[4]={0},square[4]={0},ai_table[16][16];
int tmp_sum,tmp_square,index=0,maxScore=-1,curScore=0;
for(int i=0;i<4;i++){
for(int k=0;k<4;k++){
memcpy(ai_table[i*k],table,sizeof(int)*16);
score[i]=cur_direction(ai_table[i*k],i,false,sum+i,square+i);
score[i]+=0.8*cur_direction(ai_table[i*k],k,false,&tmp_sum,&tmp_square,true);
sum[i]+=0.8*tmp_sum;
square[i]+=0.8*tmp_square;
for(int j=0;j<4;j++){
score[i]+=0.4*cur_direction(ai_table[i*k],j,true,&tmp_sum,&tmp_square,true);
sum[i]+=0.4*tmp_sum;
square[i]+=0.4*tmp_square;
}
curScore=2*score[i]+sum[i];
if(maxScore<curScore){maxScore=curScore;index=i;}
}
}
return index;
}
void initialize(int n=3){
memset(table,0,16*sizeof(int));
Score=Max_number=0;
while(n--)random_insert(table);
}
void gameJudge(){
initialize();
while(isConinue()){
print();
switch(getch()){
case 87:case 119:case 72:Score+=cur_direction(table,0);break;
case 83:case 115:case 80:Score+=cur_direction(table,1);break;
case 65:case 97 :case 75:Score+=cur_direction(table,2);break;
case 68:case 100:case 77:Score+=cur_direction(table,3);break;
}
}
}
void ai_judge(int nloop=1){
while(nloop--){
initialize();
while(isConinue()){
Score+=cur_direction(table,ai_calculate());
print();
}
if(allprint)printf("Max Number:%d\n",Max_number);
}
}
int main(){
srand(time(0));
gameJudge();
return 0;
}