天天看點

一個簡單的c++小遊戲——20482048小遊戲

2048小遊戲

代碼

話不多說,代碼如下:

#include<iostream>
#include<vector>
#include<ctime>
#include<cstdlib>
using namespace std;
class Game_2048
{
public:
	Game_2048();
	~Game_2048();
	void introduction();
	bool judgeOver();                            //判斷遊戲是否結束
	void reSize();
	void printBoard();                          //列印函數
	void getRand();                              //随機在棋盤上生成2,4;
	void slide();                                //滑動
private:
	int m=4, n=4;
	char op;                                   //使用者操作
	vector< vector<int> > 	board;								//棋盤
	vector<int>  row;
	bool judgeInsert(int x,int y);
	bool judgeSlide();                               //判斷是否能滑動,(未寫完)
	void copyBoard(vector< vector<int> > &newBoard,vector< vector<int> > &board);
	void inputOp();
	char getOp();							//傳回操作符

	bool judgeLeftSlide(bool mark=true);
	void leftSlide();                            //左滑動

	bool judgeRightSlide(bool mark = true);
	void rightSlide();

	bool judgeUpSlide(bool mark = true);
	void upSlide();

	bool judgeDownSlide(bool mark = true);
	void downSlide();

	void reStart();
	void enlarge();                             //将值擴大二倍
};

int main()
{
	Game_2048 NB;
	NB.introduction();
	NB.getRand();
	NB.printBoard();
	while (!NB.judgeOver())
	{
		NB.slide();
		NB.getRand();
		NB.printBoard();
	} 
	cout << "遊戲結束!!!\n";
	system("pause");
	return 0;

}

void Game_2048::introduction()
{
	cout << "這是一個2048遊戲,規則如下:\n";
	cout << "上劃:W;\n下滑:S;\n左劃:A;\n右劃:D;\n退出:Q;\n重新開始:R;\n請輸入下次操作,\n";
}

void Game_2048::slide()
{
	inputOp();
	switch (getOp())
	{
	case 'a':
	case 'A':
		if (judgeLeftSlide())
			do
				leftSlide();
			while (judgeLeftSlide(false));
		else
		{
			cout << "無法左滑動,請重試!!!\n";
			slide();
		}
		break;
	case 'd':
	case 'D':
		if (judgeRightSlide())
			do
				rightSlide();
		while (judgeRightSlide(false));		
		else
		{
			cout << "無法右滑動,請重試!!!\n";
			slide();
		}
		break;
	case 'w':
	case 'W':
		if(judgeUpSlide())
			do
			upSlide();
		while (judgeUpSlide(false));
		else
		{
			cout << "無法上滑動,請重試!!!\n";
			slide();
		}
		break;
	case 's':
	case 'S':
		if(judgeDownSlide())
			do	
				downSlide();
			while (judgeDownSlide(false));
		else
		{
			cout << "無法下滑動,請重試!!!\n";
			slide();
		}
		break;
	case 'p':
	case 'P':
		enlarge();
		break;
	case 'q':
	case 'Q':
		exit(0);
		break;
	case 'r':
	case 'R':
		reStart();
		break;
	default:
		cout << "輸入錯誤,作為懲罰,随機生成一個數!\n";
		break;
	}
}


void Game_2048::reStart()
{
	for (int i = 0; i < m; i++)
		for (int j = 0; j < n; j++) {
			board[i][j] = 0;
		}
}

void Game_2048::enlarge()
{
	for (int i = 0; i < m; i++)
		for (int j = 0; j < n; j++)
		{
			board[i][j] *= 2;
		}
}


char Game_2048::getOp()
{
	return op;
}

void Game_2048::upSlide()
{
	for (int j = 0; j < n; j++)
		for (int i = m - 1; i > 0; i--) {                              //n-1!!
			if (board[i][j] != 0 && board[i - 1][j] == 0)            //移動
			{
					board[i - 1][j] = board[i][j];
					board[i][j] = 0;
			}
		}
	for (int j = 0; j < n; j++)
		for (int i = m - 1; i > 0; i--) {
			if (board[i][j] != 0 && board[i-1][j] == board[i][j])  //覆寫
			{
				board[i-1][j] += board[i][j];
				board[i][j] = 0;
			}
		}
}

bool Game_2048::judgeUpSlide(bool mark)
{
	if (mark)
	{
		for (int i = 0; i < m; i++)
			for (int j = n - 1; j > 0; j--)
			{
				if (board[i][j] == 0)
				return true;
			}
	}
	for (int j = 0; j < n; j++)
		for (int i = m - 1; i > 0; i--) {                              //n-1!!
			if (board[i][j] != 0 && board[i - 1][j] == 0)            //移動
				return true;
			if (board[i][j] != 0 && board[i - 1][j] == board[i][j])  //覆寫
				return true;
		}
	return false;
}

bool Game_2048::judgeDownSlide(bool mark)
{
	if (mark) {
		for (int i = 0; i < m; i++)
			for (int j = n - 1; j > 0; j--)
				{
					if (board[i][j] == 0)
						return true;
				}
		
	}
	for (int j = 0; j < n; j++)
				for (int i = 0; i < m - 1; i++) {                              //n-1!!
					if (board[i][j] != 0 && board[i + 1][j] == 0)            //移動
						return true;
					if (board[i][j] != 0 && board[i + 1][j] == board[i][j])  //覆寫
						return true;

				}
	return false;
}

void Game_2048::downSlide()
{
	for (int j = 0; j < n; j++)
		for (int i = 0; i < m - 1; i++) {                         
			if (board[i][j] != 0 && board[i + 1][j] == 0)            //移動
			{
					board[i + 1][j] = board[i][j];
					board[i][j] = 0;
			}
		}
	for (int j = 0; j < n; j++)
		for (int i = 0; i < m - 1; i++) {
			if (board[i][j] != 0 && board[i + 1][j] == board[i][j])  //覆寫
			{
				board[i + 1][j] += board[i][j];
				board[i][j] = 0;
			}
		}
}


void Game_2048::rightSlide()
{
	for (int i = 0; i < m; i++)
		for (int j = 0; j < n - 1; j++) {                              //n-1!!
			if (board[i][j] != 0 && board[i][j + 1] == 0)            //移動
			{
					board[i][j + 1] = board[i][j];
					board[i][j] = 0;
			}
		}
	for (int i = 0; i < m; i++)
		for (int j = 0; j < n - 1; j++) {
			if (board[i][j] != 0 && board[i][j + 1] == board[i][j])  //覆寫
			{
				board[i][j + 1] += board[i][j];
				board[i][j] = 0;
			}
		}
}

bool Game_2048::judgeRightSlide(bool mark )
{
	if (mark) {
		for (int i = 0; i < m; i++)
			for (int j = n - 1; j > 0; j--)
			{
				if (board[i][j] == 0)
					return true;
			}
	}
	for (int i = 0; i < m; i++)
		for (int j = 0; j < n - 1; j++) {                              //n-1!!
			if (board[i][j] != 0 && board[i][j + 1] == board[i][j])  //覆寫
				return true;
			if (board[i][j] != 0 && board[i][j + 1] == 0)
				return true;
		}
	return false;
}

void Game_2048::leftSlide()
{
	for (int i = 0; i < m; i++)
		for (int j = 1; j < n; j++) {                              //n-1!!
			if (board[i][j] != 0 && board[i][j - 1] == 0)            //移動
			{
					board[i][j - 1] = board[i][j];
					board[i][j] = 0;
			}
		}
	for (int i = 0; i < m; i++)
		for (int j = 1; j < n; j++) {
			if (board[i][j] != 0 && board[i][j - 1] == board[i][j])  //覆寫
			{
				board[i][j - 1] += board[i][j];
				board[i][j] = 0;
			}
		}
}

bool Game_2048::judgeLeftSlide(bool mark)
{
	if (mark) {
		for (int i = 0; i < m; i++)
				for (int j = n - 1; j > 0; j--)
				{
					if (board[i][j] == 0)
						return true;
				}
	}
	for (int i = 0; i < m; i++)
		for (int j = n - 1; j > 0; j--) {                              //n-1!!
			if (board[i][j] != 0 && board[i][j - 1] == 0)            //移動
				return true;
			if (board[i][j] != 0 && board[i][j - 1] == board[i][j])  //覆寫
				return true;
		}
	return false;
}

bool Game_2048::judgeOver()
{
	if (op == 'q' || op == 'Q')
		return true;
	for (int i = 0; i < m; i++)
		for (int j = 0; j < n; j++) {
			if (board[i][j] == 2048)
			{
				printBoard();
				cout << "有數字達到了2048,恭喜!!!\n";
				return true;
			}	
		}

	for (int i = 0; i < m; i++)
		for (int j = 0; j < n; j++) {
			 if (board[i][j] == 0)
				return false;
		}
	if (judgeSlide())
		return false;
	else
	{
		cout << "無法再滑動\n";
		return true;
	}
		
}

bool Game_2048::judgeSlide()
{
	vector< vector<int> > 	copyBoard;								//棋盤
	vector<int>  copyRow;
	for (int i = 0; i < n; i++) {
		copyRow.push_back(0);
	}
	for (int i = 0; i < m; i++) {
		copyBoard.push_back(copyRow);
	}
	copyBoard = board;
	upSlide();
	downSlide();
	leftSlide();
	rightSlide();
	for (int i = 0; i < m; i++)
		for (int j = 0; j < n; j++)
		{
			if (board[i][j] == 0) {
				board = copyBoard;
				return true;
			}	
		}
	return false;
}

void Game_2048::copyBoard(vector< vector<int> >& newBoard, vector< vector<int> >& 	board)
{
	for (int i = 0; i < m; i++)
		for (int j = 0; j < n; j++)
			newBoard[i][j] = board[i][j];
}

bool Game_2048::judgeInsert(int x,int y)
{
	if (board[x][y] == 0)
		return true;
	else
		return false;
}
void Game_2048::getRand()
{
	srand(time(0));
	int x, y,val;
	do
	{
		x = rand() % m;
		y = rand() % n;
	} while (!judgeInsert(x,y));
	val = (rand() % 2 + 1)*2;
	board[x][y] = val;

}

void Game_2048::inputOp()
{
	cin >> op;
}
void Game_2048::reSize()
{
	cout << "請輸入棋盤大小m*n\n";
	cin >> m >> n;
	Game_2048();
}

Game_2048::~Game_2048()
{
}

Game_2048::Game_2048()
{
	for (int i = 0; i < n; i++){
		row.push_back(0);
	}
	for (int i = 0; i < m; i++){
		board.push_back(row);
	}
}
void Game_2048::printBoard()
{
	cout << "\n--------------\n";
	for (int i = 0; i < m; i++) {
		for (int j = 0; j < n; j++) {
			cout << board[i][j];
			if (j < n-1)
			{
				cout << "—";
			}
			if (j == n-1 && i < m-1)
			{
				cout << endl;
				int count = 0;
				while (count++ < n-1)
				{
					cout << "|  ";
				}
				cout << "|" << endl;
			}
		}
	}

	cout << "\n--------------\n" ;
}
           

ps:樓主現在還是個C++小白,這個小遊戲寫了差不多有450行,感覺有點多,後續會嘗試删減一點。

設計思路

編譯器

目前部落客隻會c++的控制台程式,編譯器是vs2019;

2048類的聲明

遊戲很簡單,主要操作隻有上下左右滑動,數字也僅是儲存在一個4 × 4的一個二維向量中。遊戲類中公共部分主要有滑動,列印,判斷遊戲是否運作結束,擷取操作符的函數,而私有部分主要是上下左右的滑動函數以及判斷函數,另外聲明了一個預設4 × 4的向量(可以通過resize函數修改)。

列印函數的實作

void Game_2048::printBoard()
{
	cout << "\n--------------\n";
	for (int i = 0; i < m; i++) {
		for (int j = 0; j < n; j++) {
			cout << board[i][j];
			if (j < n-1)
			{
				cout << "—";
			}
			if (j == n-1 && i < m-1)
			{
				cout << endl;
				int count = 0;
				while (count++ < n-1)
				{
					cout << "|  ";
				}
				cout << "|" << endl;
			}
		}
	}

	cout << "\n--------------\n" ;
}
           

這部分挺簡單,實際上就是對一個二位向量的一個周遊(兩個for循環),稍微有點複雜的部分是“|”“-”的輸出,多想想就歐克了。

公共部分滑動函數slide的實作

代碼就不粘了,其實就是一個簡單的switch結構,根據使用者的輸入調用不同的函數。滑動case 有個do while結構,原因是私有部分的四 個滑動函數對棋盤上的數隻能滑 動一下(局限性),例如4-0-0-0,向右 滑動隻能滑成0-4-0-0,故使用do-while多次調用右劃函數。

judgeOver函數的實作

思路就是簡單的周遊,出現了2048,遊戲結束,還有0,遊戲未結束。但還有一種情況就是棋盤滿了,但是還能夠進行滑動,這種情況下就建立一個copy的棋盤(ps:當然不能在原棋盤上嘗試滑動),對這個copy的棋盤進行上下左右的滑動,如果出現了空位,則遊戲未結束。

私有滑動函數的實作

void Game_2048::rightSlide()
{
	for (int i = 0; i < m; i++)
		for (int j = 0; j < n - 1; j++) {                              //n-1!!
			if (board[i][j] != 0 && board[i][j + 1] == 0)            //移動
			{
					board[i][j + 1] = board[i][j];
					board[i][j] = 0;
			}
		}
	for (int i = 0; i < m; i++)
		for (int j = 0; j < n - 1; j++) {
			if (board[i][j] != 0 && board[i][j + 1] == board[i][j])  //覆寫
			{
				board[i][j + 1] += board[i][j];
				board[i][j] = 0;
			}
		}
}
           

還是很簡單,就是兩個周遊,一個移動,一個合并。

總結

部落客是一個程式設計小白,這個2048遊戲是部落客某一天晚上突發奇想,想編一個小遊戲,來試試自己的能力。設計思路一個晚上(ps:失眠的晚上)已經想的差不多了,第二天一早的三節課已經初步編編出來了,改bug差不都一個晚上(主要是那個do-while循環)。畢竟小白,效率很低。450行的代碼沒什麼亮點,也沒有算法。

但學習是一個漸進的過程,與諸君共勉!!!