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