c++版的

需要Easy x库

#include <graphics.h>
#include <conio.h>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <algorithm>
#include <random>
#include <ctime>

using namespace std;

// ==================== 颜色定义 ====================
#define COLOR_BG       0x221C0A
#define COLOR_PANEL    0x2D2B1A
#define COLOR_BTN      0x4A5D3E
#define COLOR_BTN_HOVER 0x6B8C5A
#define COLOR_TEXT     0xEFE8C9
#define COLOR_HP       0xFF6B6B
#define COLOR_ENERGY   0xFFD93B
#define COLOR_CRYSTAL  0x6BCBFF
#define COLOR_BATTLE   0xFF8C42
#define COLOR_SKILL1   0x8B5A2B
#define COLOR_SKILL2   0x2B6B8B
#define COLOR_SKILL3   0x2B8B5A
#define COLOR_SKILL_ULT 0x8B2B6B

// ==================== 游戏数据 ====================
struct GameData {
    string currentLocation = "回廊大厅";
    int lampEnergy = 12;
    int maxLamp = 12;
    int hp = 36;
    int maxHp = 36;
    set<string> crystals;
    vector<string> inventory;
    bool inBattle = false;
    int bossHp = 56;
    int bossMaxHp = 56;
    bool gameOver = false;
    bool escaped = false;
    bool ironShield = false;
    
    vector<tuple<string, string, bool>> items = {
        {"赤炎灵晶", "演武厅", false}, {"霜月灵晶", "书阁", false},
        {"苍翠灵晶", "幽暗牢房", false}, {"紫霄灵晶", "星语祭坛", false},
        {"曜金灵晶", "灵晶矿脉", false}, {"断刃匕首", "回廊大厅", false},
        {"流光磨刀石", "演武厅", false}, {"灵灯余烬", "书阁", false},
        {"残破卷轴", "星语祭坛", false}, {"魂晶碎块", "菌菇洞穴", false}
    };
    
    vector<string> locations = {"回廊大厅", "演武厅", "书阁", "幽暗牢房", 
                                 "星语祭坛", "菌菇洞穴", "灵晶矿脉", "玄光出口"};
    map<string, vector<string>> exits = {
        {"回廊大厅", {"演武厅", "书阁", "幽暗牢房"}},
        {"演武厅", {"回廊大厅", "星语祭坛"}},
        {"书阁", {"回廊大厅", "菌菇洞穴"}},
        {"幽暗牢房", {"回廊大厅", "灵晶矿脉"}},
        {"星语祭坛", {"演武厅"}},
        {"菌菇洞穴", {"书阁", "玄光出口"}},
        {"灵晶矿脉", {"幽暗牢房"}},
        {"玄光出口", {"菌菇洞穴"}}
    };
    
    map<string, vector<string>> npcs = {
        {"菌菇洞穴", {"黄炎硕"}}, {"星语祭坛", {"坤哥"}}, {"灵晶矿脉", {"章鱼"}}
    };
    
    map<string, vector<string>> npcDialogs = {
        {"黄炎硕", {"白切鸡背叛了五灵!", "用魂晶碎块换情报。"}},
        {"坤哥", {"集齐五晶才能对抗白切鸡。", "卷轴记载了五灵归一斩。"}},
        {"章鱼", {"小黄,白切鸡就在出口等你。", "战斗时用大招可以重创他。"}}
    };
    
    map<string, string> npcSpecial = {
        {"黄炎硕", "魂晶碎块"}, {"坤哥", "残破卷轴"}
    };
};

GameData game;
mt19937 rng(time(0));

// 按钮结构
struct Button {
    int x, y, w, h;
    string text;
    int color;
    int hoverColor;
    bool enabled;
    function<void()> onClick;
    
    void draw() {
        if (!enabled) {
            setfillcolor(0x333333);
        } else {
            int mx = getmousex(), my = getmousey();
            if (mx >= x && mx <= x + w && my >= y && my <= y + h) {
                setfillcolor(hoverColor);
            } else {
                setfillcolor(color);
            }
        }
        solidroundrect(x, y, x + w, y + h, 10, 10);
        setcolor(COLOR_TEXT);
        setbkmode(TRANSPARENT);
        settextstyle(18, 0, _T("微软雅黑"));
        int tw = textwidth(text.c_str());
        outtextxy(x + (w - tw) / 2, y + (h - 20) / 2, text.c_str());
    }
    
    bool isHover() {
        int mx = getmousex(), my = getmousey();
        return enabled && mx >= x && mx <= x + w && my >= y && my <= y + h;
    }
};

vector<Button> mapButtons;
vector<Button> skillButtons;
Button takeBtn, combineBtn, resetBtn, talkBtn;

// 日志系统
vector<pair<string, int>> logs;

void addLog(const string& msg, int color = COLOR_TEXT) {
    logs.insert(logs.begin(), {msg, color});
    if (logs.size() > 20) logs.pop_back();
}

// ==================== 游戏逻辑 ====================
void refreshUI() {
    // 重新创建地图按钮
    mapButtons.clear();
    int bx = 30, by = 200;
    for (int i = 0; i < game.locations.size(); i++) {
        string loc = game.locations[i];
        bool canGo = false;
        for (const auto& e : game.exits[game.currentLocation]) {
            if (e == loc) canGo = true;
        }
        Button btn;
        btn.x = bx + (i % 4) * 110;
        btn.y = by + (i / 4) * 55;
        btn.w = 100;
        btn.h = 45;
        btn.text = (loc == game.currentLocation) ? loc + " ?" : loc;
        btn.color = (loc == game.currentLocation) ? COLOR_SKILL_ULT : COLOR_BTN;
        btn.hoverColor = COLOR_BTN_HOVER;
        btn.enabled = canGo && !game.inBattle && !game.gameOver;
        btn.onClick = [loc]() {
            if (game.lampEnergy <= 0) {
                addLog("灵灯能量耗尽!", COLOR_BATTLE);
                return;
            }
            game.lampEnergy--;
            game.currentLocation = loc;
            addLog("?? 来到 " + loc);
            
            // 自动拾取灵晶(简化)
            for (auto& item : game.items) {
                if (get<1>(item) == loc && !get<2>(item) && get<0>(item).find("灵晶") != string::npos) {
                    get<2>(item) = true;
                    game.inventory.push_back(get<0>(item));
                    game.crystals.insert(get<0>(item));
                    addLog("?? 获得 " + get<0>(item) + "! (" + to_string(game.crystals.size()) + "/5)", COLOR_CRYSTAL);
                }
            }
            
            if (loc == "玄光出口" && game.crystals.size() >= 5 && !game.inBattle) {
                game.inBattle = true;
                game.bossHp = game.bossMaxHp;
                addLog("?? 白切鸡挡住了去路!战斗开始!", COLOR_BATTLE);
            }
            refreshUI();
        };
        mapButtons.push_back(btn);
    }
    
    // 技能按钮
    skillButtons.clear();
    const char* skillNames[] = {"?? 崩拳", "?? 疾风连打", "??? 铁壁", "?? 五灵归一斩"};
    int skillColors[] = {COLOR_SKILL1, COLOR_SKILL2, COLOR_SKILL3, COLOR_SKILL_ULT};
    for (int i = 0; i < 4; i++) {
        Button btn;
        btn.x = 30 + i * 110;
        btn.y = 520;
        btn.w = 100;
        btn.h = 45;
        btn.text = skillNames[i];
        btn.color = skillColors[i];
        btn.hoverColor = COLOR_BTN_HOVER;
        btn.enabled = game.inBattle && !game.gameOver;
        btn.onClick = [i]() {
            if (!game.inBattle) return;
            int cost = (i == 3) ? 2 : 1;
            if (game.lampEnergy < cost) {
                addLog("灵灯不足!", COLOR_BATTLE);
                return;
            }
            game.lampEnergy -= cost;
            
            if (i == 2) { // 铁壁
                int heal = 12;
                game.hp = min(game.maxHp, game.hp + heal);
                game.ironShield = true;
                addLog("??? 铁壁恢复 " + to_string(heal) + " 生命!");
            } else {
                uniform_int_distribution<int> dmgDist((i == 0) ? 12 : (i == 1) ? 18 : 30, 
                                                       (i == 0) ? 18 : (i == 1) ? 28 : 48);
                int damage = dmgDist(rng);
                uniform_int_distribution<int> critDist(1, 100);
                if (critDist(rng) <= 20) {
                    damage = damage * 1.5;
                    addLog("? 暴击!");
                }
                if (i == 1 && critDist(rng) <= 25) {
                    damage += damage * 0.5;
                    addLog("?? 连击触发!");
                }
                game.bossHp -= damage;
                addLog("? 使用" + string((i == 0) ? "崩拳" : (i == 1) ? "疾风连打" : "五灵归一斩") + 
                       " 造成 " + to_string(damage) + " 伤害!");
            }
            
            if (game.bossHp <= 0) {
                addLog("?? 击败白切鸡!逃离深渊!", COLOR_CRYSTAL);
                game.inBattle = false;
                game.escaped = true;
                game.gameOver = true;
                refreshUI();
                return;
            }
            
            // 敌人反击
            uniform_int_distribution<int> bossDist(7, 15);
            int bossDmg = bossDist(rng);
            if (i == 3) bossDmg = max(4, bossDmg - 5);
            if (game.ironShield) {
                bossDmg /= 2;
                addLog("??? 铁壁减伤!");
                game.ironShield = false;
            }
            game.hp -= bossDmg;
            addLog("?? 白切鸡反击造成 " + to_string(bossDmg) + " 伤害!", COLOR_BATTLE);
            
            if (game.hp <= 0) {
                addLog("?? 小黄被击败了...", COLOR_BATTLE);
                game.gameOver = true;
            }
            refreshUI();
        };
        skillButtons.push_back(btn);
    }
    
    // 操作按钮
    takeBtn = {30, 580, 110, 40, "?? 拾取", COLOR_BTN, COLOR_BTN_HOVER, 
               !game.inBattle && !game.gameOver, []() {
        for (auto& item : game.items) {
            if (get<1>(item) == game.currentLocation && !get<2>(item)) {
                get<2>(item) = true;
                game.inventory.push_back(get<0>(item));
                if (get<0>(item).find("灵晶") != string::npos) {
                    game.crystals.insert(get<0>(item));
                    addLog("?? 获得 " + get<0>(item) + "! (" + to_string(game.crystals.size()) + "/5)", COLOR_CRYSTAL);
                } else {
                    addLog("? 获得 " + get<0>(item));
                }
                refreshUI();
                return;
            }
        }
        addLog("这里没有可拾取的物品");
    }};
    
    combineBtn = {150, 580, 110, 40, "?? 合成", COLOR_BTN, COLOR_BTN_HOVER,
                  !game.inBattle && !game.gameOver, []() {
        auto hasDagger = find(game.inventory.begin(), game.inventory.end(), "断刃匕首") != game.inventory.end();
        auto hasStone = find(game.inventory.begin(), game.inventory.end(), "流光磨刀石") != game.inventory.end();
        if (hasDagger && hasStone) {
            game.inventory.erase(find(game.inventory.begin(), game.inventory.end(), "断刃匕首"));
            game.inventory.erase(find(game.inventory.begin(), game.inventory.end(), "流光磨刀石"));
            game.inventory.push_back("破晓短刃");
            addLog("?? 合成成功!获得破晓短刃!");
        } else {
            addLog("需要断刃匕首和流光磨刀石");
        }
        refreshUI();
    }};
    
    resetBtn = {270, 580, 110, 40, "?? 重置", COLOR_BTN, COLOR_BTN_HOVER, true, []() {
        game = GameData();
        addLog("?? 游戏已重置!");
        refreshUI();
    }};
    
    talkBtn = {390, 580, 110, 40, "?? 对话", COLOR_BTN, COLOR_BTN_HOVER,
               !game.inBattle && !game.gameOver, []() {
        if (game.npcs.count(game.currentLocation)) {
            string npc = game.npcs[game.currentLocation][0];
            // 检查特殊物品
            if (game.npcSpecial.count(npc)) {
                auto it = find(game.inventory.begin(), game.inventory.end(), game.npcSpecial[npc]);
                if (it != game.inventory.end()) {
                    game.inventory.erase(it);
                    addLog("?? " + npc + ": \"获得战斗增益!\"");
                    refreshUI();
                    return;
                }
            }
            vector<string> dialogs = game.npcDialogs[npc];
            addLog("?? " + npc + ": \"" + dialogs[rand() % dialogs.size()] + "\"");
        } else {
            addLog("这里没有人可以对话");
        }
    }};
}

// ==================== 绘图函数 ====================
void draw() {
    cleardevice();
    
    // 背景
    setfillcolor(COLOR_BG);
    solidrectangle(0, 0, 800, 700);
    
    // 标题
    setcolor(COLOR_CRYSTAL);
    settextstyle(28, 0, _T("微软雅黑"));
    outtextxy(200, 15, _T("?? 遗忘深渊 · 小黄 VS 白切鸡 ??"));
    
    // 状态栏
    setfillcolor(COLOR_PANEL);
    solidroundrect(20, 60, 780, 120, 15, 15);
    
    char status[256];
    sprintf(status, "?? 小黄 %d/%d      ?? 灵灯 %d/%d      ?? 灵晶 %d/5      ?? %s",
            game.hp, game.maxHp, game.lampEnergy, game.maxLamp, 
            (int)game.crystals.size(), game.currentLocation.c_str());
    setcolor(COLOR_TEXT);
    settextstyle(20, 0, _T("微软雅黑"));
    outtextxy(40, 85, status);
    
    // 血量条
    setfillcolor(0x442222);
    solidrectangle(40, 115, 40 + 200, 130);
    setfillcolor(COLOR_HP);
    solidrectangle(40, 115, 40 + 200 * game.hp / game.maxHp, 130);
    
    // 灵灯条
    setfillcolor(0x443300);
    solidrectangle(260, 115, 260 + 150, 130);
    setfillcolor(COLOR_ENERGY);
    solidrectangle(260, 115, 260 + 150 * game.lampEnergy / game.maxLamp, 130);
    
    // 地图区域标题
    setcolor(COLOR_TEXT);
    settextstyle(16, 0, _T("微软雅黑"));
    outtextxy(30, 165, _T("??? 深渊地图 (点击移动)"));
    
    // 绘制地图按钮
    for (auto& btn : mapButtons) btn.draw();
    
    // 背包区域
    setfillcolor(COLOR_PANEL);
    solidroundrect(30, 430, 400, 510, 10, 10);
    outtextxy(35, 440, _T("?? 背包"));
    int iy = 465;
    for (const auto& item : game.inventory) {
        setcolor(COLOR_CRYSTAL);
        outtextxy(40, iy, item.c_str());
        iy += 22;
    }
    
    // NPC区域
    solidroundrect(410, 430, 780, 510, 10, 10);
    outtextxy(415, 440, _T("?? 角色"));
    iy = 465;
    if (game.npcs.count(game.currentLocation)) {
        for (const auto& npc : game.npcs[game.currentLocation]) {
            setcolor(COLOR_SKILL2);
            outtextxy(420, iy, npc.c_str());
            iy += 22;
        }
    } else {
        setcolor(0x888888);
        outtextxy(420, 465, _T("无人在此"));
    }
    
    // 技能区域
    if (game.inBattle) {
        setfillcolor(COLOR_BATTLE);
        solidroundrect(20, 510, 780, 560, 10, 10);
        setcolor(COLOR_TEXT);
        char bossHpStr[100];
        sprintf(bossHpStr, "?? 白切鸡 HP: %d/%d", game.bossHp, game.bossMaxHp);
        outtextxy(30, 522, bossHpStr);
    }
    
    for (auto& btn : skillButtons) btn.draw();
    takeBtn.draw();
    combineBtn.draw();
    resetBtn.draw();
    talkBtn.draw();
    
    // 日志区域
    solidroundrect(20, 635, 780, 690, 10, 10);
    int ly = 645;
    for (int i = 0; i < min((int)logs.size(), 6); i++) {
        setcolor(logs[i].second);
        outtextxy(30, ly, logs[i].first.c_str());
        ly += 22;
    }
    
    // 胜利/失败提示
    if (game.gameOver) {
        if (game.escaped) {
            setcolor(COLOR_CRYSTAL);
            settextstyle(36, 0, _T("微软雅黑"));
            outtextxy(250, 300, _T("?? 胜利!逃离深渊! ??"));
        } else if (game.hp <= 0) {
            setcolor(COLOR_BATTLE);
            settextstyle(36, 0, _T("微软雅黑"));
            outtextxy(250, 300, _T("?? 游戏结束 ??"));
        }
    }
}

// ==================== 主函数 ====================
int main() {
    initgraph(800, 700);
    setbkcolor(COLOR_BG);
    srand(time(0));
    
    addLog("?? 小黄 VS 白切鸡 - 点击式游戏");
    addLog("?? 目标:集齐5枚灵晶,前往玄光出口决战!");
    addLog("?? 点击地图移动,点击技能战斗");
    
    refreshUI();
    
    ExMessage msg;
    while (true) {
        draw();
        
        if (peekmessage(&msg, EM_MOUSE)) {
            if (msg.message == WM_LBUTTONDOWN) {
                // 检查所有按钮
                for (auto& btn : mapButtons) {
                    if (btn.isHover() && btn.enabled) btn.onClick();
                }
                for (auto& btn : skillButtons) {
                    if (btn.isHover() && btn.enabled) btn.onClick();
                }
                if (takeBtn.isHover() && takeBtn.enabled) takeBtn.onClick();
                if (combineBtn.isHover() && combineBtn.enabled) combineBtn.onClick();
                if (resetBtn.isHover() && resetBtn.enabled) resetBtn.onClick();
                if (talkBtn.isHover() && talkBtn.enabled) talkBtn.onClick();
            }
        }
        
        Sleep(16);
    }
    
    closegraph();
    return 0;
}