1. 程式人生 > >c++實現2048[牛客網、控制檯]

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;
}