首页 > 代码库 > 2048 源代码

2048 源代码

之前在面试过程中被问到了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;
}