//-std=c++11
#include <iostream>
#include <vector>
#include <fstream>
#include <conio.h>
#include <windows.h>
#include <cstdlib>
#include <ctime>
#include <iomanip>
#include <cstring>
#include <algorithm>

using namespace std;

enum Color {
    BLACK = 0, BLUE = 1, GREEN = 2, CYAN = 3, RED = 4,
    MAGENTA = 5, BROWN = 6, LGRAY = 7, GRAY = 8, LBLUE = 9,
    LGREEN = 10, LCYAN = 11, LRED = 12, LMAGENTA = 13, YELLOW = 14, WHITE = 15
};

void setColor(int c) {
    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), c);
}

void clear() { system("cls"); }

void waitKey() {
    setColor(WHITE);
    cout << "\n按任意键返回...";
    _getch();
}

int getHighScore(const string& name) {
    ifstream fin("score.dat");
    string n; int s;
    while (fin >> n >> s) if (n == name) return s;
    return 0;
}

void saveHighScore(const string& name, int score) {
    vector<pair<string, int>> vec;
    ifstream fin("score.dat"); string n; int s;
    bool found = false;
    while (fin >> n >> s) {
        if (n == name) {
            vec.emplace_back(n, max(score, s));
            found = true;
        } else vec.emplace_back(n, s);
    }
    if (!found) vec.emplace_back(name, score);
    ofstream fout("score.dat");
    for (auto& p : vec) fout << p.first << " " << p.second << endl;
}

int chooseDifficulty() {
    clear();
    setColor(LBLUE);
    cout << "============ 难度选择 ============\n\n";
    setColor(WHITE);
    cout << "1 - 简单\n2 - 普通\n3 - 困难\n\n";
    cout << "选择: ";
    int c = _getch() - '0';
    return (c < 1 || c > 3) ? 2 : c;
}

int speedByDifficulty(int d) {
    if (d == 1) return 180;
    if (d == 2) return 120;
    return 70;
}

void showHelp() {
    clear();
    setColor(LCYAN);
    cout << "==================== 操作说明 ====================\n\n";
    setColor(WHITE);
    cout << "X      退出/返回\n";
    cout << "WASD   移动\n";
    cout << "空格   跳跃(小恐龙)\n";
    cout << "===================================================\n";
    waitKey();
}

void showTutorial() {
    clear();
    setColor(YELLOW);
    cout << "==================== 游戏教程 ====================\n\n";
    setColor(WHITE);
    cout << "【贪吃蛇】多食物同时存在,吃F得分\n";
    cout << "【2048】相同数字合并,目标2048\n";
    cout << "【打砖块】接住小球,不让它掉落\n";
    cout << "【猜数字】猜1-100数字,提示大小\n";
    cout << "【小恐龙】空格跳跃躲避仙人掌,越跑越快\n";
    cout << "===================================================\n";
    waitKey();
}

// ==================== 贪吃蛇 · 多食物版 ====================
void gameSnake() {
    int diff = chooseDifficulty();
    int spd = speedByDifficulty(diff);
    enum class Dir { STOP, LEFT, RIGHT, UP, DOWN };
    struct Point { int x, y; };

    bool over = false;
    const int w = 20, h = 20;
    const int FOOD_COUNT = 5;
    vector<Point> foods;
    int score = 0;
    Dir dir = Dir::STOP;
    vector<Point> snake;
    snake.push_back({w/2, h/2});
    int high = getHighScore("snake");

    auto addFood = [&]() {
        bool ok;
        Point p;
        do {
            ok = true;
            p.x = rand() % w;
            p.y = rand() % h;
            for (auto& s : snake) if (s.x == p.x && s.y == p.y) ok = false;
            for (auto& f : foods) if (f.x == p.x && f.y == p.y) ok = false;
        } while (!ok);
        foods.push_back(p);
    };

    for (int i = 0; i < FOOD_COUNT; i++) addFood();

    while (!over) {
        clear();
        setColor(LGREEN);
        for (int i = 0; i < w+2; i++) cout << "#"; cout << endl;

        for (int i = 0; i < h; i++) {
            setColor(LGREEN); cout << "#";
            for (int j = 0; j < w; j++) {
                bool isBody = false;
                bool isFood = false;
                for (auto& s : snake) if (s.x == j && s.y == i) { isBody = true; break; }
                for (auto& f : foods) if (f.x == j && f.y == i) { isFood = true; break; }

                if (i == snake[0].y && j == snake[0].x) { setColor(WHITE); cout << "O"; }
                else if (isFood) { setColor(LRED); cout << "F"; }
                else if (isBody) { setColor(LGREEN); cout << "o"; }
                else cout << " ";
            }
            setColor(LGREEN); cout << "#\n";
        }
        for (int i = 0; i < w+2; i++) cout << "#";
        setColor(WHITE);
        cout << "\n分数: " << score << "   最高分: " << high << "   按X退出\n";

        if (_kbhit()) {
            char ch = _getch();
            if (ch == 'x' || ch == 'X') break;
            switch (ch) {
                case 'a': if (dir != Dir::RIGHT) dir = Dir::LEFT; break;
                case 'd': if (dir != Dir::LEFT) dir = Dir::RIGHT; break;
                case 'w': if (dir != Dir::DOWN) dir = Dir::UP; break;
                case 's': if (dir != Dir::UP) dir = Dir::DOWN; break;
            }
        }

        Point head = snake[0];
        switch (dir) {
            case Dir::LEFT: head.x--; break;
            case Dir::RIGHT: head.x++; break;
            case Dir::UP: head.y--; break;
            case Dir::DOWN: head.y++; break;
            default: break;
        }
        snake.insert(snake.begin(), head);

        bool ate = false;
        for (auto it = foods.begin(); it != foods.end(); ++it) {
            if (head.x == it->x && head.y == it->y) {
                foods.erase(it);
                score += 10;
                ate = true;
                break;
            }
        }

        if (ate) addFood();
        else snake.pop_back();

        if (head.x < 0 || head.x >= w || head.y < 0 || head.y >= h) over = true;
        for (size_t i = 1; i < snake.size(); i++)
            if (snake[i].x == head.x && snake[i].y == head.y) over = true;

        Sleep(spd);
    }

    setColor(LRED);
    cout << "\n===== GAME OVER =====\n";
    if (score > high) {
        setColor(YELLOW);
        cout << "?? 新纪录!\n";
        saveHighScore("snake", score);
    }
    waitKey();
}

// ==================== 2048 完整修复版 ====================
void game2048() {
    const int SZ = 4;
    int grid[SZ][SZ] = {0};
    int score = 0;
    int high = getHighScore("2048");

    auto hasEmpty = [&]() {
        for (int i = 0; i < SZ; ++i)
            for (int j = 0; j < SZ; ++j)
                if (grid[i][j] == 0) return true;
        return false;
    };

    auto canMove = [&]() {
        for (int i = 0; i < SZ; ++i)
            for (int j = 0; j < SZ; ++j) {
                int v = grid[i][j];
                if (j < SZ-1 && grid[i][j+1] == v) return true;
                if (i < SZ-1 && grid[i+1][j] == v) return true;
            }
        return false;
    };

    auto addRandom = [&]() {
        if (!hasEmpty()) return;
        vector<pair<int, int>> pos;
        for (int i = 0; i < SZ; ++i)
            for (int j = 0; j < SZ; ++j)
                if (grid[i][j] == 0) pos.emplace_back(i, j);
        int r = rand() % pos.size();
        grid[pos[r].first][pos[r].second] = (rand() % 10 < 9) ? 2 : 4;
    };

    auto draw = [&]() {
        clear();
        setColor(LBLUE);
        cout << "============== 2048 ==============\n\n";
        setColor(WHITE);
        cout << "分数: " << score << "    最高分: " << high << "\n\n";
        for (int i = 0; i < SZ; ++i) {
            for (int j = 0; j < SZ; ++j) {
                int v = grid[i][j];
                if (v == 0)      { setColor(GRAY);    cout << setw(6) << "."; }
                else if (v == 2) { setColor(WHITE);   cout << setw(6) << v; }
                else if (v == 4) { setColor(LGREEN);  cout << setw(6) << v; }
                else if (v == 8) { setColor(CYAN);    cout << setw(6) << v; }
                else if (v == 16){ setColor(YELLOW);  cout << setw(6) << v; }
                else if (v == 32){ setColor(LRED);    cout << setw(6) << v; }
                else if (v == 64){ setColor(MAGENTA); cout << setw(6) << v; }
                else             { setColor(RED);     cout << setw(6) << v; }
            }
            cout << "\n\n";
        }
        setColor(WHITE);
        cout << "WASD移动  X退出\n";
    };

    auto slideLine = [&](int line[]) {
        int tmp[SZ] = {0}, idx = 0;
        for (int i = 0; i < SZ; ++i) if (line[i]) tmp[idx++] = line[i];
        for (int i = 0; i < SZ-1; ++i) {
            if (tmp[i] && tmp[i] == tmp[i+1]) {
                tmp[i] *= 2; score += tmp[i]; tmp[i+1] = 0;
            }
        }
        int res[SZ] = {0}; idx = 0;
        for (int i = 0; i < SZ; ++i) if (tmp[i]) res[idx++] = tmp[i];
        memcpy(line, res, sizeof(res));
    };

    auto left = [&]() {
        int old[SZ][SZ]; memcpy(old, grid, sizeof(grid));
        for (int i = 0; i < SZ; ++i) slideLine(grid[i]);
        return memcmp(old, grid, sizeof(grid)) != 0;
    };

    auto right = [&]() {
        int old[SZ][SZ]; memcpy(old, grid, sizeof(grid));
        for (int i = 0; i < SZ; ++i) {
            int line[SZ];
            for (int j = 0; j < SZ; ++j) line[j] = grid[i][SZ-1-j];
            slideLine(line);
            for (int j = 0; j < SZ; ++j) grid[i][SZ-1-j] = line[j];
        }
        return memcmp(old, grid, sizeof(grid)) != 0;
    };

    auto up = [&]() {
        int old[SZ][SZ]; memcpy(old, grid, sizeof(grid));
        for (int j = 0; j < SZ; ++j) {
            int line[SZ];
            for (int i = 0; i < SZ; ++i) line[i] = grid[i][j];
            slideLine(line);
            for (int i = 0; i < SZ; ++i) grid[i][j] = line[i];
        }
        return memcmp(old, grid, sizeof(grid)) != 0;
    };

    auto down = [&]() {
        int old[SZ][SZ]; memcpy(old, grid, sizeof(grid));
        for (int j = 0; j < SZ; ++j) {
            int line[SZ];
            for (int i = 0; i < SZ; ++i) line[i] = grid[SZ-1-i][j];
            slideLine(line);
            for (int i = 0; i < SZ; ++i) grid[SZ-1-i][j] = line[i];
        }
        return memcmp(old, grid, sizeof(grid)) != 0;
    };

    addRandom(); addRandom();
    draw();

    while (true) {
        if (!_kbhit()) continue;
        char c = _getch();
        if (c == 'x' || c == 'X') break;
        bool moved = false;
        switch (c) {
            case 'a': moved = left(); break;
            case 'd': moved = right(); break;
            case 'w': moved = up(); break;
            case 's': moved = down(); break;
        }
        if (moved) { addRandom(); draw(); }
        if (!hasEmpty() && !canMove()) {
            setColor(LRED);
            cout << "\n===== GAME OVER =====\n";
            break;
        }
    }

    if (score > high) saveHighScore("2048", score);
    waitKey();
}

// ==================== 打砖块 ====================
void gameBrick() {
    int diff = chooseDifficulty();
    int spd = speedByDifficulty(diff);
    const int w = 24, h = 12;
    int bx = w/2, by = h/2;
    int dx = 1, dy = -1;
    int pad = w/2 - 2;
    const int padW = 5;
    int score = 0;
    int high = getHighScore("brick");

    while (true) {
        clear();
        setColor(LGREEN);
        for (int i = 0; i < w+2; i++) cout << "#"; cout << endl;

        for (int i = 0; i < h; i++) {
            setColor(LGREEN); cout << "#";
            for (int j = 0; j < w; j++) {
                if (i == by && j == bx) { setColor(WHITE); cout << "O"; }
                else cout << " ";
            }
            setColor(LGREEN); cout << "#\n";
        }

        cout << "#";
        for (int j = 0; j < w; j++) {
            if (j >= pad && j < pad+padW) cout << "=";
            else cout << " ";
        }
        cout << "#\n";
        for (int i = 0; i < w+2; i++) cout << "#";

        setColor(WHITE);
        cout << "\n分数: " << score << "   最高分: " << high << "   A/D移动 X退出\n";

        if (_kbhit()) {
            char c = _getch();
            if (c == 'a' && pad > 0) pad--;
            if (c == 'd' && pad+padW < w) pad++;
            if (c == 'x' || c == 'X') break;
        }

        bx += dx; by += dy;

        if (bx <= 0 || bx >= w-1) { dx *= -1; }
        if (by <= 0) { dy *= -1; }

        if (by == h-1 && bx >= pad && bx < pad+padW) { dy *= -1; score += 5; }
        if (by >= h) {
            setColor(LRED);
            cout << "\n===== GAME OVER =====\n";
            break;
        }