cpp
#include <iostream>
#include <windows.h> // 用于颜色和光标
#include <conio.h> // 用于 _kbhit() 和 _getch()
#include <ctime>
#include <cstdlib>
using namespace std;
// ---------- 颜色控制 ----------
enum Color {
BLACK = 0,
DARK_BLUE = 1,
DARK_GREEN = 2,
DARK_CYAN = 3,
DARK_RED = 4,
DARK_MAGENTA = 5,
DARK_YELLOW = 6,
GRAY = 7,
DARK_GRAY = 8,
BLUE = 9,
GREEN = 10,
CYAN = 11,
RED = 12,
MAGENTA = 13,
YELLOW = 14,
WHITE = 15
};
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
void setColor(Color color) {
SetConsoleTextAttribute(hConsole, color);
}
void gotoxy(int x, int y) {
COORD pos = { (short)x, (short)y };
SetConsoleCursorPosition(hConsole, pos);
}
// ---------- 游戏变量 ----------
int board[4][4] = { 0 };
int score = 0;
bool gameOver = false;
bool win = false;
// 随机生成一个方块 (2 或 4)
void addRandomTile() {
int emptyCells[16][2];
int count = 0;
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
if (board[i][j] == 0) {
emptyCells[count][0] = i;
emptyCells[count][1] = j;
count++;
}
}
}
if (count == 0) return;
int idx = rand() % count;
int r = emptyCells[idx][0];
int c = emptyCells[idx][1];
board[r][c] = (rand() % 10 == 0) ? 4 : 2; // 10% 概率生成 4
}
// ---------- 核心移动逻辑 ----------
// 向左滑动一行 (返回是否移动)
bool slideRow(int row[4]) {
bool moved = false;
// 1. 压缩 (去掉空格)
int temp[4] = { 0 };
int idx = 0;
for (int i = 0; i < 4; i++) {
if (row[i] != 0) temp[idx++] = row[i];
}
// 2. 合并
for (int i = 0; i < 3; i++) {
if (temp[i] != 0 && temp[i] == temp[i + 1]) {
temp[i] *= 2;
score += temp[i];
if (temp[i] == 2048) win = true;
temp[i + 1] = 0;
i++; // 跳过已合并的
}
}
// 3. 再次压缩
int result[4] = { 0 };
idx = 0;
for (int i = 0; i < 4; i++) {
if (temp[i] != 0) result[idx++] = temp[i];
}
// 4. 检查是否改变了
for (int i = 0; i < 4; i++) {
if (row[i] != result[i]) moved = true;
row[i] = result[i];
}
return moved;
}
bool moveLeft() {
bool moved = false;
for (int i = 0; i < 4; i++) {
if (slideRow(board[i])) moved = true;
}
return moved;
}
bool moveRight() {
bool moved = false;
for (int i = 0; i < 4; i++) {
int row[4];
for (int j = 0; j < 4; j++) row[j] = board[i][3 - j];
if (slideRow(row)) {
moved = true;
for (int j = 0; j < 4; j++) board[i][3 - j] = row[j];
}
}
return moved;
}
bool moveUp() {
bool moved = false;
for (int j = 0; j < 4; j++) {
int col[4];
for (int i = 0; i < 4; i++) col[i] = board[i][j];
if (slideRow(col)) {
moved = true;
for (int i = 0; i < 4; i++) board[i][j] = col[i];
}
}
return moved;
}
bool moveDown() {
bool moved = false;
for (int j = 0; j < 4; j++) {
int col[4];
for (int i = 0; i < 4; i++) col[i] = board[3 - i][j];
if (slideRow(col)) {
moved = true;
for (int i = 0; i < 4; i++) board[3 - i][j] = col[i];
}
}
return moved;
}
// 检查是否还能继续 (有空位或相邻相等)
bool canContinue() {
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
if (board[i][j] == 0) return true;
if (i < 3 && board[i][j] == board[i + 1][j]) return true;
if (j < 3 && board[i][j] == board[i][j + 1]) return true;
}
}
return false;
}
// ---------- 绘制棋盘 ----------
Color getTileColor(int value) {
switch (value) {
case 2: return DARK_GRAY;
case 4: return DARK_YELLOW;
case 8: return DARK_RED;
case 16: return RED;
case 32: return MAGENTA;
case 64: return DARK_MAGENTA;
case 128: return DARK_BLUE;
case 256: return BLUE;
case 512: return DARK_CYAN;
case 1024: return CYAN;
case 2048: return YELLOW;
default: return WHITE;
}
}
void drawBoard() {
gotoxy(0, 0);
setColor(WHITE);
cout << "╔═══════════════════════════╗" << endl;
for (int i = 0; i < 4; i++) {
cout << "║";
for (int j = 0; j < 4; j++) {
int val = board[i][j];
setColor(WHITE);
cout << " ";
if (val == 0) {
cout << " ";
}
else {
setColor(getTileColor(val));
// 对齐:数字占4格
if (val < 10) cout << " " << val << " ";
else if (val < 100) cout << " " << val << " ";
else if (val < 1000) cout << " " << val;
else cout << val;
}
setColor(WHITE);
cout << " ";
}
cout << "║" << endl;
}
cout << "╚═══════════════════════════╝" << endl;
setColor(WHITE);
cout << "得分: " << score << " ";
if (win) {
setColor(YELLOW);
cout << "你赢了! (按 R 继续挑战)";
setColor(WHITE);
}
else if (gameOver) {
setColor(RED);
cout << "游戏结束! (按 R 重新开始)";
setColor(WHITE);
}
cout << endl;
cout << "操作: WASD 移动 | R 重启 | Q 退出" << endl;
}
// ---------- 游戏控制 ----------
void resetGame() {
for (int i = 0; i < 4; i++)
for (int j = 0; j < 4; j++)
board[i][j] = 0;
score = 0;
gameOver = false;
win = false;
addRandomTile();
addRandomTile();
drawBoard();
}
void processMove(bool moved) {
if (moved) {
addRandomTile();
drawBoard();
if (win) {
// 赢了依然可以继续
}
if (!canContinue()) {
gameOver = true;
drawBoard();
}
}
}
// ---------- 主函数 ----------
int main() {
system("title 2048 游戏");
system("mode con: cols=40 lines=25");
// 隐藏光标
CONSOLE_CURSOR_INFO cursorInfo;
GetConsoleCursorInfo(hConsole, &cursorInfo);
cursorInfo.bVisible = false;
SetConsoleCursorInfo(hConsole, &cursorInfo);
srand((unsigned)time(nullptr));
resetGame();
while (true) {
if (_kbhit()) {
int key = _getch();
bool moved = false;
if (key == 224) { // 方向键
key = _getch();
switch (key) {
case 75: moved = moveLeft(); break; // 左
case 77: moved = moveRight(); break; // 右
case 72: moved = moveUp(); break; // 上
case 80: moved = moveDown(); break; // 下
}
if (moved) processMove(moved);
}
else {
switch (tolower(key)) {
case 'a': moved = moveLeft(); break;
case 'd': moved = moveRight(); break;
case 'w': moved = moveUp(); break;
case 's': moved = moveDown(); break;
case 'r': resetGame(); break;
case 'q': return 0;
}
if (moved) processMove(moved);
}
drawBoard(); // 刷新显示
}
Sleep(50);
}
return 0;
}
这个放在vs2022上就可以直接运行,不同的数字为了区分用了不同的颜色
WASD 或 方向键(↑↓←→) 移动方块
R:重新开始
Q:退出游戏
游戏规则
每次移动,所有方块会滑向对应方向,相同数字的方块相遇时会合并(数值相加),并增加分数。
每移动一次,棋盘空位会随机生成一个新方块(2 或 4)。
当棋盘被填满且无法再进行任何合并时,游戏结束。
拼出 2048 方块即为胜利(但仍可继续挑战更高分数)