#include<stdio.h>
#include<stdlib.h>
#include <conio.h>
#include<assert.h>
#define N 4
void Print(int (*arr)[N],int n)//输出
{
system("cls");
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
printf("%5d",arr[i][j]);
}
printf("\n\n");
}
printf("\n\n\n\n");
}
bool IsContinue(int (*arr)[N],int n) //游戏是否可以继续
{
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
if(arr[i][j]==0)
{
return true;
}
if(i>0&&arr[i][j]==arr[i-1][j])
{
return true;
}
if(i<n-1&&arr[i][j]==arr[i+1][j])
{
return true;
}
if(j>0&&arr[i][j]==arr[i][j-1])
{
return true;
}
if(j<n-1&&arr[i][j]==arr[i][j+1])
{
return true;
}
}
}
return false;
}
int GetDirectionkey()//获取方向键
{
int ch1=0;
int ch2=0;
if(ch1=getch())
{
ch2=getch();
}
return ch2;
}
bool IsAddress(int (*arr)[N],int n)
{
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
if(arr[i][j]==0)
{
return true;
}
}
}
return false;
}
void Address(int (*arr)[N],int n)//产生一个随机值(随机位置)
{
int tmp=rand()%5;//随机值
int row=rand()%n;//随机位置
int col=rand()%n;
int count=0;
if(tmp!=4)
{
tmp=2;
}
if(arr[row][col]==0)
{
arr[row][col]=tmp;
}
else
{
count=row*n+col;
while(arr[row][col]!=0)
{
count=(count+1)%(n*n);
row=count/n;
col=count%n;
}
arr[row][col]=tmp;
}
}
bool IsMoveUp(int (*arr)[N],int n)//是否可以上移
{
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
if(arr[i][j]!=0)
{
if(i>0&&arr[i][j]==arr[i-1][j])
{
return true;
}
for(int k=i-1;k>=0;k--)
{
if(arr[k][j]==0)
{
return true;
}
}
}
}
}
return false;
}
bool IsMoveDown(int (*arr)[N],int n)//是否可以下移
{
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
if(arr[i][j]!=0)
{
if(i<n-1&&arr[i][j]==arr[i+1][j])
{
return true;
}
for(int k=i;k<n;k++)
{
if(arr[k][j]==0)
{
return true;
}
}
}
}
}
return false;
}
bool IsMoveLeft(int (*arr)[N],int n)//是否可以左移
{
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
if(arr[i][j]!=0)
{
if(j>0&&arr[i][j]==arr[i][j-1])
{
return true;
}
for(int k=j-1;k>=0;k--)
{
if(arr[i][k]==0)
{
return true;
}
}
}
}
}
return false;
}
bool IsMoveRight(int (*arr)[N],int n)//是否可以右移
{
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
if(arr[i][j]!=0)
{
if(j<n-1&&arr[i][j]==arr[i][j+1])
{
return true;
}
for(int k=j;k<n;k++)
{
if(arr[i][k]==0)
{
return true;
}
}
}
}
}
return false;
}
void Move(int *arr,int n) //将一维数组元元素移动在一起
{
for(int i=0;i<n;i++)
{
if(arr[i]==0)
{
for(int j=i+1;j<n;j++)
{
if(arr[j]!=0)
{
arr[i]=arr[j];
arr[j]=0;
break;
}
}
}
}
}
void Sum(int *arr,int n)//将一维数组相邻两个相同的数加起来赋给前者,后者置0
{
for(int i=0;i+1<n;i++)
{
if(arr[i]!=0&&arr[i]==arr[i+1])
{
arr[i]+=arr[i];
arr[i+1]=0;
}
}
}
void MoveUp(int (*arr)[N],int n)//向上移更新数据
{
int i;
int j;
int *brr=(int *)calloc(n,sizeof(int));
assert(brr!=NULL);
for(j=0;j<n;j++)
{
for(i=0;i<n;i++)
{
brr[i]=arr[i][j];
arr[i][j]=0;
}
Move(brr,n);
Sum(brr,n);
Move(brr,n);
for(i=0;i<n;i++)
{
arr[i][j]=brr[i];
brr[i]=0;
}
}
free(brr);
}
void MoveDown(int (*arr)[N],int n) //向下移更新数据
{
int i;
int j;
int *brr=(int *)calloc(n,sizeof(int));
assert(brr!=NULL);
for(j=0;j<n;j++)
{
for(i=n-1;i>=0;i--)
{
brr[n-1-i]=arr[i][j];
arr[i][j]=0;
}
Move(brr,n);
Sum(brr,n);
Move(brr,n);
for(i=0;i<n;i++)
{
arr[n-1-i][j]=brr[i];
brr[i]=0;
}
}
free(brr);
}
void MoveLeft(int (*arr)[N],int n) //向左移更新数据
{
int i;
for(i=0;i<n;i++)
{
Move(arr[i],n);
Sum(arr[i],n);
Move(arr[i],n);
}
}
void MoveRight(int (*arr)[N],int n) //向右移更改数据
{
int i;
int j;
int *brr=(int *)calloc(n,sizeof(int));
assert(brr!=NULL);
for(i=n-1;i>=0;i--)
{
for(j=0;j<n;j++)
{
brr[n-1-j]=arr[i][j];
arr[i][j]=0;
}
Move(brr,n);
Sum(brr,n);
Move(brr,n);
for(j=0;j<n;j++)
{
arr[i][n-1-j]=brr[j];
brr[j]=0;
}
}
free(brr);
}
void Merge(int (*arr)[N],int n)//更改数据
{
int tmp=GetDirectionkey();//获取方向键
int flag=0;
if(tmp==72&&IsMoveUp(arr,n)) //上
{
MoveUp(arr,n);
flag=1;
}
else if(tmp==80&&IsMoveDown(arr,n))//下
{
MoveDown(arr,n);
flag=1;
}
else if(tmp==75&&IsMoveLeft(arr,n))//左
{
MoveLeft(arr,n);
flag=1;
}
else if(tmp==77&&IsMoveRight(arr,n)) //右
{
MoveRight(arr,n);
flag=1;
}
if(flag==1&&IsAddress(arr,n))
{
Address(arr,n);
}
}
void Game(int (*arr)[N],int n)
{
Address(arr,n);
Address(arr,n);
Print(arr,n);
while(IsContinue(arr,n))
{
Merge(arr,n);
Print(arr,n);
}
system("cls");
printf("Game Over!\n");
}
int main()
{
int arr[N][N]={0};
Game(arr,N);
return 0;
}