之前在面试过程中被问到了2048怎么写,当时思路阻塞,写不出来。面试结束回来仔细想了想,觉得也不是很难,可以实现。于是乎有了下面的代码。
说下思路:
2048主要可以分为1、随机生成新数2或者4,;2、上下左右移动;3、判断死亡及胜利。
上下左右移动都可以归结到对一行或一列的四个数进行操作,然后进行四次。
filename: my2048.h
void Adjust(int *num);
void Add(int* num);
void Movedown();
void Moveup();
void Moveleft();
void Moveright();
bool dead();
bool win(int MAX);
double random(double start, double end);
void generate();
void display (int mark);
filename: my2048.cpp
#include <iostream>
#include <ctime>
#include "my2048.h"
using namespace std;
int MAP[4][4];
int mark;
//将所有非零元素都移动到左侧
void Adjust(int *num)
{
int i,j;
for(i=0;i<3;i++)
{
if(num[i]==0)
{
for(j=i+1;j<4;j++)
{
if(num[j]!=0)
{
num[i]=num[j];
num[j]=0;
break;
}
}
}
}
}
void Add(int* num)
{
int i;
//先将所有非零元素都移动到左侧
Adjust(num);
//然后再考虑相同元素合并问题
for(i=0;i<3;i++)
{
if(num[i]==num[i+1])
{
num[i]=2*num[i];
num[i+1]=0;
mark += num[i];
}
}
//因为合并过程中可能会出现0元素,故需要重新将非零元素左移
Adjust(num);
}
void Movedown()
{
int j;
int num[4]={0};
for(j=0;j<4;j++)
{
num[0]=MAP[3][j];
num[1]=MAP[2][j];
num[2]=MAP[1][j];
num[3]=MAP[0][j];
Add(num);
MAP[3][j]=num[0];
MAP[2][j]=num[1];
MAP[1][j]=num[2];
MAP[0][j]=num[3];
}
}
void Moveup()
{
int j;
int num[4]={0};
for(j=0;j<4;j++)
{
num[0]=MAP[0][j];
num[1]=MAP[1][j];
num[2]=MAP[2][j];
num[3]=MAP[3][j];
Add(num);
MAP[0][j]=num[0];
MAP[1][j]=num[1];
MAP[2][j]=num[2];
MAP[3][j]=num[3];
}
}
void Moveleft()
{
int i;
int num[4]={0};
for(i=0;i<4;i++)
{
num[0]=MAP[i][0];
num[1]=MAP[i][1];
num[2]=MAP[i][2];
num[3]=MAP[i][3];
Add(num);
MAP[i][0]=num[0];
MAP[i][1]=num[1];
MAP[i][2]=num[2];
MAP[i][3]=num[3];
}
}
void Moveright()
{
int i;
int num[4]={0};
for(i=0;i<4;i++)
{
num[0]=MAP[i][3];
num[1]=MAP[i][2];
num[2]=MAP[i][1];
num[3]=MAP[i][0];
Add(num);
MAP[i][3]=num[0];
MAP[i][2]=num[1];
MAP[i][1]=num[2];
MAP[i][0]=num[3];
}
}
//检测是否已经死亡,主要是检查元素是否跟自己右侧和下侧元素是否相同,相同表明还没死
bool dead()
{
int i,j;
for(i=0;i<4;i++)
for(j=0;j<4;j++)
if(MAP[i][j]==0)
return false;
for(i=0;i<3;i++)
{
for(j=0;j<3;j++)
{
if(MAP[i][j]==MAP[i][j+1] || MAP[i][j]==MAP[i+1][j])
return false;
}
}
return true;
}
bool win(int MAX)
{
int i,j;
int temp = 0;
for(i=0;i<4;i++)
{
for(j=0;j<4;j++)
{
if(MAP[i][j]>temp)
temp=MAP[i][j];
}
}
if(temp==MAX)
return true;
else
return false;
}
double random(double start, double end)
{
return start+(end-start)*rand()/(RAND_MAX+ 1.0); //最后范围处于[start,end-1]
}
//随机生成数字2或者4
void generate()
{
int i,j;
int zero_num = 0;
//先统计0的个数
for(i=0;i<4;i++)
for(j=0;j<4;j++)
if(MAP[i][j]==0)
zero_num++;
//生成两个随机数:第一个数是位置,第二个是新生成的数(2或者4)
int random_num = static_cast<int>(random(0,zero_num)+1.0);
//int new_num = static_cast<int>((random(0,2)+1.0)) * 2; //2、4完全随机
int new_num = 0;
int new_num_temp = static_cast<int>(random(0,4)+1.0);
if(new_num_temp<4)
new_num = 2;
else
new_num = 4;
int zero_temp=0;
for(i=0;i<4;i++)
for(j=0;j<4;j++)
if(MAP[i][j]==0)
{
zero_temp ++;
if(zero_temp == random_num)
MAP[i][j] = new_num;
}
}
void display (int mark)
{
printf ("得分:%d\n",mark);
printf ("┏━━┳━━┳━━┳━━┓\n");
printf ("┃%4d┃%4d┃%4d┃%4d┃\n",MAP[0][0],MAP[0][1],MAP[0][2],MAP[0][3]);
printf ("┣━━╋━━╋━━╋━━┫\n");
printf ("┃%4d┃%4d┃%4d┃%4d┃\n",MAP[1][0],MAP[1][1],MAP[1][2],MAP[1][3]);
printf ("┣━━╋━━╋━━╋━━┫\n");
printf ("┃%4d┃%4d┃%4d┃%4d┃\n",MAP[2][0],MAP[2][1],MAP[2][2],MAP[2][3]);
printf ("┣━━╋━━╋━━╋━━┫\n");
printf ("┃%4d┃%4d┃%4d┃%4d┃\n",MAP[3][0],MAP[3][1],MAP[3][2],MAP[3][3]);
printf ("┗━━┻━━┻━━┻━━┛\n");
}
int main()
{
printf("HOW TO PLAY: \n");
printf("Use a(left),s(down),d(right),w(up) to move the tiles.\n");
printf("When two tiles with the same number touch, they merge into one!\n");
printf("When you merge the number 2048, you win!\n");
//printf("Please input the maxnum you want to achieve!\n");
int MAX=16;
//cin>>MAX;
srand(static_cast<unsigned>(time(0)));
int i,j;
char direction;
mark = 0;
for(i=0;i<3;i++)
for(j=0;j<3;j++)
MAP[i][j]=0;
generate();
display(mark);
while(cin>>direction)
{
switch(direction)
{
case 'a': Moveleft();break;
case 's': Movedown();break;
case 'd': Moveright();break;
case 'w': Moveup();break;
//default :cout<<"direction input wrong!"<<endl;break;
}
generate();
display(mark);
if(dead())
{
cout<<"You lose!"<<endl;
break;
}
if(win(MAX))
{
cout<<"You win!"<<endl;
break;
}
}
return 0;
}