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

相关推荐
JQweryuiop21 小时前
中小型游戏陪练工作室数字化管理实践:基于七彩屋电竞护航小程序订单、履约与绩效系统的落地复盘
大数据·游戏·小程序·架构
乌萨达2 天前
低配电脑玩手游怎么设置?4GB、8GB内存与模拟器选择指南
游戏·电脑·安卓模拟器·雷电模拟器
西西弗Sisyphus3 天前
Qt 实现一个 水波进度球
c++·qt·c
林川~013 天前
Unity 万能物理检测工具:射线检测 / 范围检测 / 层级过滤 / 编辑器可视化(可直接拿去用)
游戏·unity·c#·射线检测·通用工具
C++ 老炮儿的技术栈4 天前
我们在设计tcp协议时,要传一个字符串过去,报文:头十长度十内容,是否要把‘\0‘也填入,长度是否包含‘\0‘
开发语言·数据结构·c++·mfc·c
一孤程4 天前
游戏测试专题第七篇:游戏自动化测试实战
游戏·测试
一孤程5 天前
游戏测试专题第八篇:游戏安全测试与反外挂
游戏·测试
anew___5 天前
舵机——让 Arduino 动起来
c++·stm32·单片机·嵌入式硬件·c
河南花仙子科技6 天前
小游戏社交裂变功能的高阶设计思路
大数据·科技·游戏
一孤程6 天前
游戏测试专题第五篇:游戏兼容性测试与多端适配
游戏·测试