c++实现2048[牛客网、控制台]

1.前言

刚学完c++基础,找个项目练练手,于是上牛客网找了个2048练练手,文章最后给出源码

2.简介

  1. 一次只能合并相邻的两个数字,例如 [2 2 2 2] ,向右合并以后是 [空 空 4 4] ,不是 [空 空 空 8]
  2. 每次合并的时候,合并方向优先级高,例如 [空 2 2 2],向右合并以后是 [空 空 2 4],不是 [空 空 4 2]
  3. 判断游戏结束
  4. 每次合并以后随机新出4的概率10%

3.项目思路

  1. 用一个4*4的int数组来储存数据,初始化为0
  2. 用户上下左右移的操作可整体简化为3个步骤
  • 1)将非0元素紧凑
  • 2)合并同类项
  • 3)再将非0元素紧凑

4.示例

2 0 0 0
0 0 0 0
2 0 0 0
8 0 0 0

此时执行上移操作,步骤如下

                                1)紧凑

2 0 0 0
2 0 0 0
8 0 0 0
0 0 0

0

                               2)上移合并同类项

4 0 0 0
0 0 0 0
8 0 0 0
0 0 0 0

                               3)紧凑

4 0 0 0
8 0 0 0
0 0 0 0
0 0 0 0

5.bug

因为楼主在随机位置生成随机数的代码如下

//生成随机数
int randomNum(){
	int num=rand()%10;
	return num>8?4:2;
}
//para num->用户想生成[0,num]间随机数
inline void random(int num){
	srand((unsigned int)(time(NULL)));
	a=rand()%num;
	Sleep(100);
	b=rand()%num;
}

//生成1个随机位置并赋值
void randomAddress(){
	//随着4*4数组中非0个数增加  可能出现卡顿  带优化
	while(map[a][b]!=0){
		
		random(3);
	}
	int num=randomNum();
	map[a][b]=num;
	cout<<"row:"<<a<<" column"<<b<<" "<<map[a][b]<<endl;
}

当数组中非0元素个数增多时,在随机位置生成随机数所耗费的时间也不断增加

6.源码

#include <iostream>
#include <ctime>
#include<windows.h>
using namespace std;

void print();//打印当前状态

int randomNum();//生成2个随机数(其中一个必为2,另一个 2:4出现的比例=4:1) 

void randomAddress();//生成2个随机位置  

inline void random(int);//生成随机数[0,num),以便上述2个函数使用

void up();

void down();

void left();

void right();

bool isEnd();//判断游戏是否结束

int map[4][4]={0,};

int a=0,b=0;//两个用来储存随机数的值

void print(){

	cout << "************************************************" << endl;
	cout << "*     " << map[0][0] << "       	 " << map[0][1] << "           " << map[0][2] << "      	  " << map[0][3] << "    *" << endl;
	cout << "************************************************" << endl;
	cout << "*     " << map[1][0] << "       	 " << map[1][1] << "           " << map[1][2] << "      	  " << map[1][3] << "    *" << endl;
	cout << "************************************************" << endl;
	cout << "*     " << map[2][0] << "       	 " << map[2][1] << "           " << map[2][2] << "      	  " << map[2][3] << "    *" << endl;
	cout << "************************************************" << endl;
	cout << "*     " << map[3][0] << "       	 " << map[3][1] << "           " << map[3][2] << "      	  " << map[3][3] << "    *" << endl;
	cout << "************************************************" << endl;
	cout << "操作详情:(输入后,按回车键结束)" << endl;
	cout << "w :	向上移动		s :		向下移动" << endl;
	cout << "a :	向左移动		r :		向右移动" << endl;
	cout << "q :	退出" << endl;


}

//para num->用户想生成[0,num]间随机数
inline void random(int num){
	srand((unsigned int)(time(NULL)));
	a=rand()%num;
	Sleep(100);
	b=rand()%num;
}

//生成随机数
int randomNum(){
	int num=rand()%10;
	return num>8?4:2;
}

//判断游戏是否结束 结束条件:1.4x4数组中非0元素已满  2.出现2048
bool isEnd(){
	for(int a=0;a<4;a++){
		for(int b=0;b<4;b++){
			if(map[a][b]==2048)return true;
			if(map[a][b]==0)return false;
		}
	}
	return true;
}

//生成1个随机位置并赋值
void randomAddress(){
	//随着4*4数组中非0个数增加  可能出现卡顿  带优化
	while(map[a][b]!=0){
		
		random(3);
	}
	int num=randomNum();
	map[a][b]=num;
	cout<<"row:"<<a<<" column"<<b<<" "<<map[a][b]<<endl;
}

//用户点击上移操作
void up(){
	int row,column;
	//1.将非0元素上移
	for(row=0;row<4;row++){
		for(column=0;column<4;column++){
			
			while(row!=0&&map[row][column]!=0&&map[row-1][column]==0){
				map[row-1][column]=map[row][column];
				map[row][column]=0;
				row--;
			}
		}
	}
	
	//2.相同元素合并  循环遍历每一个元素
	for(row=1;row<4;row++){
		for(column=0;column<4;column++){
			if(map[row][column]==0)continue;
			else if(map[row][column]!=map[row-1][column]){
				continue;
			}else{
				map[row-1][column]*=2;
				map[row][column]=0;
				}	
		}
	}

	//3.将合并后非0元素上移
	for(row=0;row<4;row++){
		for(column=0;column<4;column++){
			
			while(row!=0&&map[row][column]!=0&&map[row-1][column]==0){
				map[row-1][column]=map[row][column];
				map[row][column]=0;
				row--;
			}
		}
	}
	randomAddress();
}

//用户点击下移操作
void down(){
	int row,column;
	//1.将非0元素下移
	for(row=3;row>=0;row--){
		for(column=0;column<4;column++){
			while(row!=3&&map[row][column]!=0&&map[row+1][column]==0){
				map[row+1][column]=map[row][column];
				map[row][column]=0;
				row++;
			}
		}
	}
	//2.合并同类项
	for(row=2;row>=0;row--){
		for(column=0;column<4;column++){
			if(map[row][column]==0)continue;
			else if(map[row][column]!=map[row+1][column]){
				continue;
			}else{
				map[row+1][column]*=2;
				map[row][column]=0;
			}
			
		}

		
	}

	//3.合并后非0
	for(row=3;row>=0;row--){
	for(column=0;column<4;column++){
		while(row!=3&&map[row][column]!=0&&map[row+1][column]==0){
			map[row+1][column]=map[row][column];
			map[row][column]=0;
			row++;
		}
	}
}
	randomAddress();
}

//用户点击左移操作
void left(){
	int row,column;
	//1.将非0元素左移
	for(row=0;row<4;row++){
		for(column=0;column<4;column++){
			while(column!=0&&map[row][column]!=0&&map[row][column-1]==0){
				map[row][column-1]=map[row][column];
				map[row][column]=0;
				column--;
			}
		}
	}

	//2.合并元素
	for(row=0;row<4;row++){
		for(column=1;column<4;column++){
			if(map[row][column]==0)continue;
			else if(map[row][column]!=map[row][column-1])continue;
			
			map[row][column]=0;
			map[row][column-1]*=2;
				
			
		}
	}
	//3.
	for(row=0;row<4;row++){
		for(column=0;column<4;column++){
			while(column!=0&&map[row][column]!=0&&map[row][column-1]==0){
				map[row][column-1]=map[row][column];
				map[row][column]=0;
				column--;
			}
		}
	}
	randomAddress();
}

void right(){
	int row,column;

	//1.
	for(row=0;row<4;row++){
		for(column=3;column>=0;column--){
			while(column!=3&&map[row][column]!=0&&map[row][column+1]==0){
				map[row][column+1]=map[row][column];
				map[row][column]=0;
				column++;
			}
		}
	}

	//2.右移合并同类项
	for(row=0;row<4;row++){
		for(column=2;column>=0;column--){
			if(map[row][column]==0||map[row][column]!=map[row][column+1])continue;
			else{
				map[row][column+1]*=2;
				map[row][column]=0;
			}
		}
	}
	//3.
	for(row=0;row<4;row++){
		for(column=3;column>=0;column--){
			while(column!=3&&map[row][column]!=0&&map[row][column+1]==0){
				map[row][column+1]=map[row][column];
				map[row][column]=0;
				column++;
			}
		}
	}
	randomAddress();
}

int main(){
	char control;
	//数据初始化
	randomAddress();
	randomAddress();
	print();
	while(cin>>control){
		switch(control){
				case 'w':up();break;
				case 's':down();break;
				case 'a':left();break;
				case 'd':right();break;
				case 'q':return 0;
			}
		print();//将移动后元素打印
		if(isEnd()){
			cout<<"游戏已结束"<<endl;
			return 0;
		}
	}
	
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41437917/article/details/85246010