2048 Console Version - C++实现

2048 Console Version


用C++实现的控制台版2048小游戏,实现了GitHub上原始版本2048的大部分功能特性,就是界面丑了些。

写之前阅读了Reason的代码,参考了他的思路,并对一些特性与实现方式做了些修改。感谢Reason!

/*
 *	2048 Console Version by ChenKode
 *
 */
#include <iostream>
#include <iomanip>			/* cout << setw() */
#include <ctime>			/* time() */
#include <cstdlib>			/* srand(), rand() */
#include <conio.h>			/* _getch() */

using namespace std;

const int SIZE = 4;			/* Size of each row and column */
/* Goal-Score of the game*/
const int GOAL = (int)pow((double)2, SIZE * (SIZE - 1));

const int UP = 0, DOWN = 1, LEFT = 2, RIGHT = 3;

int pane[SIZE][SIZE];		/* Pane of the game */
int maxNumber;				/* Max number of the pane */
int score;					/* Score of the game */
int bestScore;				/* Best score of the game */
int zeroCnt;				/* Zero number of the pane */

void newGame();				/* Start a new game */
void showPane();			/* Print the pane */
int process();				/* Move, merge and judge */

int main()
{
	system("color f2");

	int gameIsOn = 1;
	while (gameIsOn)
	{
		/* Start a new game */
		newGame();
		
		while (gameIsOn)
		{	/* In game */
			gameIsOn = process();
			showPane();
		}

		if (maxNumber == GOAL)
		{
			cout << setw(43) << "Congratulations! You Win!" << endl;
		}
		else
		{
			cout << setw(43) << "~Game Over~" << endl;
		}
		cout << setw(46) << "Your Final Score is: " << score << endl;
		cout << endl << setw(54) << "Input \"1\" to Retry, \"0\" to Quit." << endl;
		cin >> gameIsOn;
		while (gameIsOn != 1 && gameIsOn != 0)
		{
			cout << setw(43) << "Input Error. Please Input Again.";
			cin >> gameIsOn;
		}
	}

	system("pause");
	return 0;
}

void newGame()
{	/* Start a new game */
	void addNewNumber();

	memset(pane, 0, SIZE * SIZE * sizeof(int));
	maxNumber = 2;
	score = 0;
	zeroCnt = SIZE * SIZE;
	addNewNumber();
	showPane();
}

void showPane()
{	/* Print the pane */
	system("cls");

	cout << endl;
	cout << setw(46) << "2048 by ChenKode" << endl;
	cout << setw(30) << "Score: " << setw(4) << score << "   " << "Best Score: " << setw(4) << bestScore << endl;
	cout << setw(26) << "|";
	for (int k = 0; k < SIZE - 1; k++)
	{
		cout << "------";
	}
	cout << "-----|" << endl;

	for (int i = 0; i < SIZE; i++)	
	{
		cout << setw(24) << "";
		for (int j = 0; j < SIZE; j++)
		{
			if(pane[i][j] == 0)
			{
				cout << setw(2) << "|" << setw(4) << "";
			}
			else
			{
				cout << setw(2) << "|" << setw(4) << pane[i][j];
			}

			if (j == SIZE - 1)
			{
				cout << setw(2) << "|" << endl;
				cout << setw(26) << "|";
				for (int k = 0; k < SIZE - 1; k++)
				{
					cout << "------";
				}
				cout << "-----|" << endl;
			}
		}//for (int j = 0; j < SIZE; j++)
	}//for (int i = 0; i < SIZE; i++)
}

int process()
{	/* Move, merge and judge */
	int getDirection();			/* Get move direction from keyboard */
	void addNewNumber();		/* Add a "2" or "4" to the pane */
	int moveUp();
	int moveLeft();
	int moveRigh();
	int moveDown();
	int canMoveUp();
	int canMoveLeft();
	int canMoveRigh();
	int canMoveDown();

	if (maxNumber == GOAL || !zeroCnt && !canMoveUp() && !canMoveLeft() && !canMoveRigh() && !canMoveDown())
	{	/* Game is finished */
		return 0;
	}

	while (1)
	{
		int dir = getDirection();
		int flag = 0;
		switch(dir)
		{
		case UP:
			flag = moveUp();
			break;

		case LEFT:
			flag = moveLeft();
			break;

		case RIGHT:
			flag = moveRigh();
			break;

		case DOWN:
			flag = moveDown();
			break;

		default:
			break;
		}

		if (flag == 1)
		{	/* Game goes on */
			addNewNumber();
			return 1;
		}
	}//while (1)
}

void addNewNumber()
{	/* Add a "2" or "4" to the pane */
	srand((unsigned)time(NULL));			/* Get seed */
	int position = rand() % zeroCnt;
	int newNumber = (rand() % 2 + 1) * 2;

	for (int row = 0; row < SIZE; row++)
	{
		for (int column = 0; column < SIZE; column++)
		{
			if (pane[row][column] == 0)
			{
				if (position == 0)
				{
					pane[row][column] = newNumber;
					zeroCnt--;
					return;
				}
				position--;
			}
		}//for (int column = 0; column < SIZE; column++)
	}//for (int row = 0; row < SIZE; row++)
}

int getDirection()
{	/* Get direction from keyboard */
	while (1)
	{
		int key = _getch();
		switch (key)
		{
		case 72:
			return UP;
			break;
		case 75:
			return LEFT;
			break;
		case 77:
			return RIGHT;
			break;
		case 80:
			return DOWN;
			break;
		default:
			break;
		}
	}
}

int moveUp()
{
	int isMoved = 0;
	for (int column = 0; column < SIZE; column++)
	{
		int mergeFlag = 0;
		for (int row = 1; row < SIZE; row++)
		{	/* Begin at row = 1 */
			if (pane[row][column] != 0)
			{
				int tmp = row - 1;
				while (tmp >= 0 && pane[tmp][column] == 0)
				{	/* Find last non-zero number */
					tmp--;
				}
				if (tmp == -1)
				{	/* pane[row][column] is the first non-zero number */
					pane[0][column] = pane[row][column];
					pane[row][column] = 0;
					isMoved = 1;
				}
				else
				{	/* pane[row][column] is not the first non-zero number */
					if (pane[row][column] == pane[tmp][column] && mergeFlag == 0)
					{	/* Need to merge */
						pane[tmp][column] *= 2;
						pane[row][column] = 0;

						mergeFlag = 1;
						isMoved = 1;

						score += pane[tmp][column];
						if (score > bestScore)
						{
							bestScore = score;
						}
						if (pane[tmp][column] > maxNumber)
						{
							maxNumber = pane[tmp][column];
						}

						zeroCnt++;
					}
					else
					{	/* Just move*/
						if (tmp == row - 1)
						{	/* pane[row][column] is adjacent to pane[tmp][column] */
							continue;
						}
						pane[tmp + 1][column] = pane[row][column];
						pane[row][column] = 0;
						isMoved = 1;
					}
				}
			}//if (pane[row][column] != 0)
		}//for (int row = 1; row < SIZE; row++)
	}//for (int column = 0; column < SIZE; column++)

	return isMoved;
}

int moveLeft()
{
	int isMoved = 0;
	for (int row = 0; row < SIZE; row++)
	{
		int mergeFlag = 0;
		for (int column = 1; column < SIZE; column++)
		{	/* Begin at column = 1 */
			if (pane[row][column] != 0)
			{
				int tmp = column - 1;
				while (tmp >= 0 && pane[row][tmp] == 0)
				{	/* Find last non-zero number */
					tmp--;
				}
				if (tmp == -1)
				{	/* pane[row][column] is the first non-zero number */
					pane[row][0] = pane[row][column];
					pane[row][column] = 0;
					isMoved = 1;
				}
				else
				{	/* pane[row][column] is not the first non-zero number */
					if (pane[row][column] == pane[row][tmp] && mergeFlag == 0)
					{	/* Need to merge */
						pane[row][tmp] *= 2;
						pane[row][column] = 0;

						mergeFlag = 1;
						isMoved = 1;

						score += pane[row][tmp];
						if (score > bestScore)
						{
							bestScore = score;
						}
						if (pane[row][tmp] > maxNumber)
						{
							maxNumber = pane[row][tmp];
						}

						zeroCnt++;
					}
					else
					{	/* Just move*/
						if (tmp == column - 1)
						{	/* pane[row][column] is adjacent to pane[row][tmp] */
							continue;
						}
						pane[row][tmp + 1] = pane[row][column];
						pane[row][column] = 0;
						isMoved = 1;
					}
				}
			}//if (panepane[row][column] != 0)
		}//for (int column = 1; column < SIZE; j++)
	}//for (int row = 0; row < SIZE; i++)

	return isMoved;
}

int moveRigh()
{
	int isMoved = 0;
	for (int row = 0; row < SIZE; row++)
	{
		int mergeFlag = 0;
		for (int column = SIZE - 1 - 1; column >= 0; column--)
		{	/* Begin at column = SIZE - 1 - 1 */
			if (pane[row][column] != 0)
			{
				int tmp = column + 1;
				while (tmp < SIZE && pane[row][tmp] == 0)
				{	/* Find last non-zero number */
					tmp++;
				}
				if (tmp == SIZE)
				{	/* pane[row][column] is the first non-zero number */
					pane[row][SIZE - 1] = pane[row][column];
					pane[row][column] = 0;
					isMoved = 1;
				}
				else
				{	/* pane[row][column] is not the first non-zero number */
					if (pane[row][column] == pane[row][tmp] && mergeFlag == 0)
					{	/* Need to merge */
						pane[row][tmp] *= 2;
						pane[row][column] = 0;

						mergeFlag = 1;
						isMoved = 1;

						score += pane[row][tmp];
						if (score > bestScore)
						{
							bestScore = score;
						}
						if (pane[row][tmp] > maxNumber)
						{
							maxNumber = pane[row][tmp];
						}

						zeroCnt++;
					}
					else
					{	/* Just move*/
						if (tmp == column + 1)
						{	/* pane[row][column] is adjacent to pane[row][tmp] */
							continue;
						}
						pane[row][tmp - 1] = pane[row][column];
						pane[row][column] = 0;
						isMoved = 1;
					}
				}
			}//if (panepane[row][column] != 0)
		}//for (int column = SIZE - 1 - 1; column >= 0; column--)
	}//for (int row = 0; row < SIZE; row++)

	return isMoved;
}

int moveDown()
{
	int isMoved = 0;
	for (int column = 0; column < SIZE; column++)
	{
		int mergeFlag = 0;
		for (int row = SIZE - 1 - 1; row >= 0; row--)
		{	/* Begin at row = SIZE - 1 - 1 */
			if (pane[row][column] != 0)
			{
				int tmp = row + 1;
				while (tmp < SIZE && pane[tmp][column] == 0)
				{	/* Find last non-zero number */
					tmp++;
				}
				if (tmp == SIZE)
				{	/* pane[row][column] is the first non-zero number */
					pane[SIZE - 1][column] = pane[row][column];
					pane[row][column] = 0;
					isMoved = 1;
				}
				else
				{	/* pane[row][column] is not the first non-zero number */
					if (pane[row][column] == pane[tmp][column] && mergeFlag == 0)
					{	/* Need to merge */
						pane[tmp][column] *= 2;
						pane[row][column] = 0;

						mergeFlag = 1;
						isMoved = 1;

						score += pane[tmp][column];
						if (score > bestScore)
						{
							bestScore = score;
						}
						if (pane[tmp][column] > maxNumber)
						{
							maxNumber = pane[tmp][column];
						}

						zeroCnt++;
					}
					else
					{	/* Just move*/
						if (tmp == row + 1)
						{	/* pane[row][column] is adjacent to pane[tmp][column] */
							continue;
						}
						pane[tmp - 1][column] = pane[row][column];
						pane[row][column] = 0;
						isMoved = 1;
					}
				}
			}//if (pane[row][column] != 0)
		}//for (int row = SIZE - 1 - 1; row >= 0; row--)
	}//for (int column = 0; column < SIZE; column++)

	return isMoved;
}

int canMoveUp()
{
	for (int column = 0; column < SIZE; column++)
	{
		for (int row = 1; row < SIZE; row++)
		{	/* Begin at row = 1 */
			if (pane[row][column] != 0)
			{
				int tmp = row - 1;
				while (tmp >= 0 && pane[tmp][column] == 0)
				{	/* Find last non-zero number */
					tmp--;
				}
				if (tmp == -1)
				{	/* pane[row][column] is the first non-zero number */
					return 1;
				}
				else
				{	/* pane[row][column] is not the first non-zero number */
					if (pane[row][column] != pane[tmp][column] && tmp == row - 1)
					{	/* Cannot merge */
						/* And pane[row][column] is adjacent to pane[tmp][column] */
						continue;
					}
					else
					{	/* Just move*/
						return 1;
					}
				}
			}//if (pane[row][column] != 0)
		}//for (int row = 1; row < SIZE; row++)
	}//for (int column = 0; column < SIZE; column++)

	return 0;
}

int canMoveLeft()
{
	for (int row = 0; row < SIZE; row++)
	{
		for (int column = 1; column < SIZE; column++)
		{	/* Begin at column = 1 */
			if (pane[row][column] != 0)
			{
				int tmp = column - 1;
				while (tmp >= 0 && pane[row][tmp] == 0)
				{	/* Find last non-zero number */
					tmp--;
				}
				if (tmp == -1)
				{	/* pane[row][column] is the first non-zero number */
					return 1;
				}
				else
				{	/* pane[row][column] is not the first non-zero number */
					if (pane[row][column] != pane[row][tmp] && tmp == column - 1)
					{	/* Cannot merge */
						/* And pane[row][column] is adjacent to pane[row][tmp] */
						continue;
					}
					else
					{	/* Just move*/
						return 1;
					}
				}
			}//if (panepane[row][column] != 0)
		}//for (int column = 1; column < SIZE; j++)
	}//for (int row = 0; row < SIZE; i++)

	return 0;
}

int canMoveRigh()
{
	for (int row = 0; row < SIZE; row++)
	{
		for (int column = SIZE - 1 - 1; column >= 0; column--)
		{	/* Begin at column = SIZE - 1 - 1 */
			if (pane[row][column] != 0)
			{
				int tmp = column + 1;
				while (tmp < SIZE && pane[row][tmp] == 0)
				{	/* Find last non-zero number */
					tmp++;
				}
				if (tmp == SIZE)
				{	/* pane[row][column] is the first non-zero number */
					return 1;
				}
				else
				{	/* pane[row][column] is not the first non-zero number */
					if (pane[row][column] != pane[row][tmp] && tmp == column + 1)
					{	/* Cannot merge */
						/* And pane[row][column] is adjacent to pane[row][tmp] */
						continue;
					}
					else
					{
						return 1;
					}
				}
			}//if (panepane[row][column] != 0)
		}//for (int column = SIZE - 1 - 1; column >= 0; column--)
	}//for (int row = 0; row < SIZE; row++)

	return 0;
}

int canMoveDown()
{
	for (int column = 0; column < SIZE; column++)
	{
		for (int row = SIZE - 1 - 1; row >= 0; row--)
		{	/* Begin at row = SIZE - 1 - 1 */
			if (pane[row][column] != 0)
			{
				int tmp = row + 1;
				while (tmp < SIZE && pane[tmp][column] == 0)
				{	/* Find last non-zero number */
					tmp++;
				}
				if (tmp == SIZE)
				{	/* pane[row][column] is the first non-zero number */
					return 1;
				}
				else
				{	/* pane[row][column] is not the first non-zero number */
					if (pane[row][column] != pane[tmp][column] && tmp == row + 1)
					{	/* Cannot merge */
						/* And pane[row][column] is adjacent to pane[tmp][column] */
						continue;
					}
					else
					{
						return 1;
					}
				}
			}//if (pane[row][column] != 0)
		}//for (int row = SIZE - 1 - 1; row >= 0; row--)
	}//for (int column = 0; column < SIZE; column++)

	return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值