2048 C++源代码 By CR

一直想写2048这个游戏,前几天看到了这篇博文,给了我很大的启示,也学习到了很多。

1、使用conio.h里的_getch()来读取方向键;

2、system()这个函数的妙用,以前一直看到别人用system("pause")来暂停程序,从来没有深究过,原来system这个函数就是可以向CMD里发送指令啊;

3、srand()的使用,大家可以百度一下srand和rand()的区别。

不过他的游戏规则是偏Threes!的,和我一开始玩的2048有很大不同,主要区别在于2048每次移动都是一次到底,而Threes!是每次只移动一格。

于是我就试着在他的基础上自己写了一个,现在分享给大家。

主要修改了移动的函数,和增加随机数的函数。


4.11日更新了字体颜色,现在每种数字可以显示不同的颜色了

/*By Cr*/
#include<iostream>
#include<iomanip>
#include<stdlib.h>
#include<time.h>
#include<conio.h> //为了读取方向键
#include<windows.h>
#include<vector>
#define BACKGROUND_WHITE BACKGROUND_RED|BACKGROUND_BLUE|BACKGROUND_GREEN|BACKGROUND_INTENSITY
using namespace std;

class Point{
private:
	int x;
	int y;
public:
	Point(int x1,int y1)
	{
		x = x1;
		y = y1;
	}
	int getx(){
		return x;
	}
	int gety(){
		return y;
	}
};

int pane[4][4]; //棋盘
int N=1; //2的n次方

void addrandomnumber()
{
	vector <Point*> *emptyPoint = new vector<Point*>();
	/*
	先把所有为零的位置存起来
	*/
	for(int x = 0;x<4;x++)
		for(int y = 0; y<4;y++)
			if(pane[x][y]<=0) emptyPoint->push_back(new Point(x,y));
	/*
	再随机取出一个位置,并将2或者4随机存入其中,
	*/
	if(emptyPoint->size()>0)
	{
		srand((unsigned)time( NULL ));
		Point *p = *(emptyPoint->begin()+rand()%emptyPoint->size());
		pane[p->getx()][p->gety()] = rand()/(double)(RAND_MAX)>0.1?2:4;
		//cout<<emptyPoint->size()<<endl;
	}
	delete emptyPoint;
}
void SetColor(int a)
{
	HANDLE outPutHandle = GetStdHandle(STD_OUTPUT_HANDLE);
	switch(a)
	{
	case 2:
		SetConsoleTextAttribute(outPutHandle,FOREGROUND_BLUE|BACKGROUND_WHITE);
		break;
	case 4:
		SetConsoleTextAttribute(outPutHandle,FOREGROUND_BLUE|BACKGROUND_WHITE);
		break;
	case 8:
		SetConsoleTextAttribute(outPutHandle,FOREGROUND_BLUE|FOREGROUND_INTENSITY|BACKGROUND_WHITE);
		break;
	case 16:
		SetConsoleTextAttribute(outPutHandle,FOREGROUND_BLUE|FOREGROUND_INTENSITY|BACKGROUND_WHITE);
		break;
	case 32:
		SetConsoleTextAttribute(outPutHandle,FOREGROUND_GREEN|BACKGROUND_WHITE);
		break;
	case 64:
		SetConsoleTextAttribute(outPutHandle,FOREGROUND_GREEN|BACKGROUND_WHITE);
		break;
	case 128:
		SetConsoleTextAttribute(outPutHandle,FOREGROUND_GREEN|FOREGROUND_INTENSITY|BACKGROUND_WHITE);
		break;
	case 256:
		SetConsoleTextAttribute(outPutHandle,FOREGROUND_GREEN|FOREGROUND_INTENSITY|BACKGROUND_WHITE);
		break;
	case 512:
		SetConsoleTextAttribute(outPutHandle,FOREGROUND_RED|BACKGROUND_WHITE);
		break;
	case 1024:
		SetConsoleTextAttribute(outPutHandle,FOREGROUND_RED|BACKGROUND_WHITE);
		break;
	case 2048:
		SetConsoleTextAttribute(outPutHandle,FOREGROUND_RED|FOREGROUND_INTENSITY|BACKGROUND_WHITE);
		break;
	default:
		SetConsoleTextAttribute(outPutHandle,FOREGROUND_BLUE|BACKGROUND_WHITE);
		break;
	}
	cout<<setw(4)<<a;
}
void showpane() //显示棋盘
{
	cout<<setw(46)<<"X2048 by CR"<<endl;
	cout<<setw(50)<<" |-----------------------|"<<endl;
	for(int i=0;i<=3;i++) 
	{
		cout<<setw(24)<<"";
		for(int j=0;j<=3;j++)
		{
			//SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_RED); 
			cout<<setw(2)<<"|";
			SetColor(pane[i][j]);
			if(j==3)
			{
				cout<<setw(2)<<"|"<<endl;
				cout<<setw(50)<<" |-----------------------|"<<endl;
			}
		}
	}
}
void newgame() //开始游戏
{
	N=1;
	for(int i=0;i<=3;i++) //初始化棋盘
		for(int j=0;j<=3;j++)
			pane[i][j]=0;
	addrandomnumber();
	addrandomnumber();
	showpane();
}

void upmove() //上移
{
	bool merge = false;
	for(int y=0;y<4;y++)
	{
		for(int x=0;x<4;x++)
		{
			for(int x1=x+1;x1<4;x1++)
			{
				if(pane[x1][y]>0)
				{
					if(pane[x][y]<=0){
						pane[x][y] = pane[x1][y];
						pane[x1][y] = 0;
						x--;
						merge = true;
					}
					else if(pane[x][y]==pane[x1][y])
					{
						pane[x][y] = pane[x][y]*2;
						pane[x1][y] = 0;
						merge = true;
					}
					break;
				}
			}
		}
	}
	if(merge == true)
	{
		addrandomnumber();
	}
}
void downmove() //下移
{
	bool merge = false;
	for(int y=0;y<4;y++)
	{
		for(int x=3;x>=0;x--)
		{
			for(int x1=x-1;x1>=0;x1--)
			{
				if(pane[x1][y]>0)
				{
					if(pane[x][y]<=0){
						pane[x][y] = pane[x1][y];
						pane[x1][y] = 0;
						x++;
						merge = true;
					}
					else if(pane[x][y]==pane[x1][y])
					{
						pane[x][y] = pane[x][y]*2;
						pane[x1][y] = 0;
						merge = true;
					}
					break;
				}
			}
		}
	}
	if(merge == true)
	{
		addrandomnumber();
	}
}
void leftmove() //左移
{
	bool merge = false;
	for(int x=0;x<4;x++)
	{
		for(int y=0;y<4;y++)
		{
			for(int y1=y+1;y1<4;y1++)
			{
				if(pane[x][y1]>0)
				{
					if(pane[x][y]<=0){
						pane[x][y] = pane[x][y1];
						pane[x][y1] = 0;
						y--;
						merge = true;
					}
					else if(pane[x][y]==pane[x][y1])
					{
						pane[x][y] = pane[x][y]*2;
						pane[x][y1] = 0;
						merge = true;
					}
					break;
				}
			}
		}
	}
	if(merge == true)
	{
		addrandomnumber();
	}
}
void rightmove() //右移
{
	bool merge = false;
	for(int x=0;x<4;x++)
	{
		for(int y=3;y>=0;y--)
		{
			for(int y1=y-1;y1>=0;y1--)
			{
				if(pane[x][y1]>0)
				{
					if(pane[x][y]<=0){
						pane[x][y] = pane[x][y1];
						pane[x][y1] = 0;
						y++;
						merge = true;
					}
					else if(pane[x][y]==pane[x][y1])
					{
						pane[x][y] = pane[x][y]*2;
						pane[x][y1] = 0;
						merge = true;
					}
					break;
				}
			}
		}
	}
	if(merge == true)
	{
		addrandomnumber();
	}
}

int panemax() //棋盘最大数
{
	int max=pane[0][0];
	for(int i=0;i<=3;i++)
		for(int j=0;j<=3;j++)
			if(pane[i][j]>max)
				max=pane[i][j];
	return max;
}
int ifwin() //判断是否胜利
{
	int flag=0;
	if(panemax()==2048)
	{
		cout<<setw(45)<<"You Win!"<<endl;
		flag=1;
	}
	return flag;
}
int ifGameOver() //判断是否游戏结束
{
	int flag=1;
	for (int y = 0; y < 4; y++) {
		for (int x = 0; x < 4; x++) {
			if (pane[x][y]==0||
				(x>0&&pane[x][y]==pane[x-1][y])||
				(x<4-1&&pane[x][y]==pane[x+1][y])||
				(y>0&&pane[x][y]==pane[x][y-1])||
				(y<4-1&&pane[x][y]==pane[x][y+1])) {
					flag = 0;
					return flag;
				}
			}
		}
	return flag;
}

int GetDirection() //读取方向
{
	int ret = 0;

	do 
	{
		int ch = _getch();
		if(isascii(ch))
			continue;

		ch = _getch();
		switch(ch)
		{
		case 72:   
			ret = 2; // top
			break;
		case 75:   
			ret = 1; // left 
			break;
		case 77:   
			ret = 3; // right
			break;
		case 80:   
			ret = 4; // down
			break;
		default:   
			break;
		}
	} while (ret == 0);

	return ret;
}

int main() //主函数
{
	system("color f9");
	int makesure=1;
	while(makesure)
	{ 
		system("cls");
		newgame();
		//showpane();
		while(ifwin()+ifGameOver()==0)
		{
			int c=GetDirection();
			switch(c)
			{
			case 2:
				upmove();
				//addrandomnumber();
				system("cls");
				showpane();
				break;
			case 4:
				downmove();
				//addrandomnumber();
				system("cls");
				showpane();
				break;
			case 1:
				leftmove();
				//addrandomnumber();
				system("cls");
				showpane();
				break;
			case 3:
				rightmove();
				//addrandomnumber();
				system("cls");
				showpane();
				break;
			default:   
				break;
			}
		}
		cout<<setw(43)<<"你的最后成绩为:"<<panemax()<<endl;
		cout<<setw(60)<<"若要重新开始游戏请输入1,若要结束请输入0。"<<endl;
		cin>>makesure;
		while(makesure!=1&&makesure!=0)
		{
			cout<<"输入不正确,请重新输入!"<<endl;
			cin>>makesure;
		}
	}
	cout<<"再见!"<<endl;
	return 0;
}


转载于:https://my.oschina.net/chasec/blog/220355

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值