一个简单的2048小游戏

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 方块即为胜利(但仍可继续挑战更高分数)

相关推荐
甲维斯18 小时前
我用AI做了一款「三国吃鸡」,开局孔明灯,落地青龙刀 !
人工智能·游戏·游戏开发
书生执笔画浮沉1 天前
分享一个开源小工具CAdapt
linux·c·gnu·glibc·kernel·升级·灵感
myshare20221 天前
Dungeon Saga 常用词中英文对照表(阵营 / 品质 / 部位 / 套装 / 属性 / 套装效果)
游戏·dungeon saga·链游攻略
薛定谔的猫-菜鸟程序员1 天前
上传试卷、打Boss,玩游戏:我用 TextIn xParse 做了一套“会解析试卷的刷题游戏“
人工智能·游戏·大模型·textin·ai数据层基础设施
lkjaslkdj1 天前
游戏指套戴在食指上,为什么套口下缘先被汗浸出一圈深色硬边、像被盐水泡过发脆,而中指戴同款只留下浅色汗印?
游戏
释厄6231 天前
认知盲区与游戏即创造世界——悖论发生在认知之外不突破无法发现
游戏
Sylvia-girl1 天前
堆排序算法
算法·排序算法·c
梦想平凡2 天前
棋牌游戏技术实战(五):从对局事件重新执行规则,核对棋盘和最终状态
数据库·游戏·oracle
liulilittle2 天前
Linux 下 select 测试函数
linux·服务器·网络·数据库·c++·select·c
Martina_03212 天前
AI生成3D模型导入后只剩一个大网格?用6步完成微缩场景拆分与优化
人工智能·游戏·数学建模·3d·ai·自然语言处理·aigc