• 个人简介

    #include <iostream #include <vector #include <string #include <sstream #include <cstdlib #include <ctime #include <conio.h> #include <windows.h> using namespace std;

    // 垃圾类型枚举 enum GarbageType { RECYCLABLE, // 可回收垃圾 HAZARDOUS, // 有害垃圾 KITCHEN_WASTE, // 厨余垃圾 OTHER_WASTE // 其他垃圾 };

    // 垃圾结构体 struct Garbage { int x, y; // 位置 GarbageType type; // 垃圾类型 string name; // 垃圾名称 string icon; // 垃圾图标(字符表示) string description; // 垃圾描述 };

    // 垃圾车(蛇)结构体 struct GarbageTruck { vector<pair<int, int>> body; // 车身各部分位置 int direction; // 移动方向:0-上,1-右,2-下,3-左 int length; // 车身长度 };

    // 游戏类 class GarbageSnakeGame { private: const int WIDTH = 35; // 游戏区域宽度 const int HEIGHT = 18; // 游戏区域高度 GarbageTruck truck; // 垃圾车 Garbage currentGarbage; // 当前垃圾 int score; // 得分 bool gameOver; // 游戏结束标志 bool garbageMissed; // 垃圾未吃到标志

    // 垃圾类型数据
    vector<Garbage> garbageTemplates;
    
    // 控制台句柄
    HANDLE hConsole;
    
    // 隐藏光标
    void hideCursor() {
        CONSOLE_CURSOR_INFO cursorInfo;
        GetConsoleCursorInfo(hConsole, &cursorInfo);
        cursorInfo.bVisible = FALSE;
        SetConsoleCursorInfo(hConsole, &cursorInfo);
    }
    
    // 设置光标位置
    void setCursorPosition(int x, int y) {
        COORD pos = {(SHORT)x, (SHORT)y};
        SetConsoleCursorPosition(hConsole, pos);
    }
    
    // 填充字符串到固定宽度(考虑中文字符宽度)
    string padLine(const string& text, int targetWidth) {
        int displayWidth = 0;
        // 计算显示宽度(中文字符算2个宽度)
        for (size_t i = 0; i < text.length(); i++) {
            if ((unsigned char)text[i] > 127) {
                displayWidth += 2;
                if (i + 1 < text.length() && (unsigned char)text[i + 1] > 127) {
                    i++; // 跳过中文字符的第二个字节
                }
            } else {
                displayWidth += 1;
            }
        }
        
        // 添加空格填充到目标宽度
        int spacesNeeded = targetWidth - displayWidth;
        if (spacesNeeded > 0) {
            return text + string(spacesNeeded, ' ');
        }
        return text;
    }
    
    // 将长文本分行显示
    vector<string> wrapText(const string& text, int maxWidth) {
        vector<string> lines;
        string currentLine = " ";  // 添加前导空格
        int currentWidth = 1;
        
        for (size_t i = 0; i < text.length(); ) {
            int charWidth = 1;
            size_t charLen = 1;
            
            // 判断是否为中文字符
            if ((unsigned char)text[i] > 127 && i + 1 < text.length()) {
                charWidth = 2;
                charLen = 2;
            }
            
            // 如果当前行加上新字符会超宽,就换行
            if (currentWidth + charWidth > maxWidth - 1) {
                lines.push_back(currentLine);
                currentLine = " ";  // 新行添加前导空格
                currentWidth = 1;
            }
            
            // 添加字符到当前行
            currentLine += text.substr(i, charLen);
            currentWidth += charWidth;
            i += charLen;
        }
        
        if (!currentLine.empty() && currentLine != " ") {
            lines.push_back(currentLine);
        }
        
        return lines;
    }
    
    // 初始化垃圾类型数据
    void initGarbageTemplates() {
        // 可回收垃圾
        garbageTemplates.push_back({0, 0, RECYCLABLE, "废纸", "[纸]", "可回收垃圾:废纸、纸板等,可以回收再利用"});
        garbageTemplates.push_back({0, 0, RECYCLABLE, "易拉罐", "[罐]", "可回收垃圾:铝制易拉罐,回收后可制成新铝制品"});
        garbageTemplates.push_back({0, 0, RECYCLABLE, "塑料瓶", "[瓶]", "可回收垃圾:PET塑料瓶,回收后可制成纤维等"});
        garbageTemplates.push_back({0, 0, RECYCLABLE, "玻璃瓶", "[玻]", "可回收垃圾:玻璃瓶,回收后可熔制新玻璃"});
    
        // 有害垃圾
        garbageTemplates.push_back({0, 0, HAZARDOUS, "废电池", "[电]", "有害垃圾:含有重金属,污染环境,需特殊处理"});
        garbageTemplates.push_back({0, 0, HAZARDOUS, "过期药品", "[药]", "有害垃圾:化学物质可能污染水土,需专业处理"});
        garbageTemplates.push_back({0, 0, HAZARDOUS, "废灯管", "[灯]", "有害垃圾:含有汞等有害物质,需特殊回收"});
        garbageTemplates.push_back({0, 0, HAZARDOUS, "废油漆", "[漆]", "有害垃圾:化学溶剂污染环境,需专业处理"});
    
        // 厨余垃圾
        garbageTemplates.push_back({0, 0, KITCHEN_WASTE, "剩饭剩菜", "[饭]", "厨余垃圾:易腐垃圾,可用于堆肥或沼气发电"});
        garbageTemplates.push_back({0, 0, KITCHEN_WASTE, "果皮", "[果]", "厨余垃圾:水果皮,可堆肥或生物处理"});
        garbageTemplates.push_back({0, 0, KITCHEN_WASTE, "茶叶渣", "[茶]", "厨余垃圾:茶叶残渣,可堆肥改善土壤"});
        garbageTemplates.push_back({0, 0, KITCHEN_WASTE, "蛋壳", "[蛋]", "厨余垃圾:蛋壳,可粉碎后作为肥料"});
    
        // 其他垃圾
        garbageTemplates.push_back({0, 0, OTHER_WASTE, "卫生纸", "[纸]", "其他垃圾:受污染纸张,不适合回收"});
        garbageTemplates.push_back({0, 0, OTHER_WASTE, "陶瓷", "[陶]", "其他垃圾:陶瓷碎片,回收价值低"});
        garbageTemplates.push_back({0, 0, OTHER_WASTE, "烟蒂", "[烟]", "其他垃圾:烟草残留物,需卫生填埋"});
        garbageTemplates.push_back({0, 0, OTHER_WASTE, "塑料袋", "[袋]", "其他垃圾:受污染塑料,回收困难"});
    }
    
    // 生成随机垃圾
    void generateGarbage() {
        int index = rand() % garbageTemplates.size();
        currentGarbage = garbageTemplates[index];
    
        // 随机位置,避开垃圾车身体
        bool validPosition = false;
        while (!validPosition) {
            currentGarbage.x = rand() % (WIDTH - 2) + 1;
            currentGarbage.y = rand() % (HEIGHT - 2) + 1;
    
            validPosition = true;
            for (const auto& segment : truck.body) {
                if (segment.first == currentGarbage.x && segment.second == currentGarbage.y) {
                    validPosition = false;
                    break;
                }
            }
        }
    }
    
    // 移动垃圾车
    void moveTruck() {
        // 保存尾部位置用于增长
        pair<int, int> tail = truck.body.back();
    
        // 移动身体
        for (int i = truck.body.size() - 1; i > 0; i--) {
            truck.body[i] = truck.body[i - 1];
        }
    
        // 移动头部
        pair<int, int>& head = truck.body[0];
        switch (truck.direction) {
            case 0: head.second--; break; // 上
            case 1: head.first++; break;  // 右
            case 2: head.second++; break; // 下
            case 3: head.first--; break;  // 左
        }
    
        // 检查边界碰撞
        if (head.first <= 0 || head.first >= WIDTH - 1 ||
            head.second <= 0 || head.second >= HEIGHT - 1) {
            gameOver = true;
            return;
        }
    
        // 检查自身碰撞
        for (int i = 1; i < truck.body.size(); i++) {
            if (head.first == truck.body[i].first && head.second == truck.body[i].second) {
                gameOver = true;
                return;
            }
        }
    
        // 检查是否吃到垃圾
        if (head.first == currentGarbage.x && head.second == currentGarbage.y) {
            // 增加长度
            truck.body.push_back(tail);
            truck.length++;
    
            // 根据垃圾类型加分
            switch (currentGarbage.type) {
                case RECYCLABLE: score += 10; break;
                case HAZARDOUS: score += 15; break;
                case KITCHEN_WASTE: score += 8; break;
                case OTHER_WASTE: score += 5; break;
            }
    
            // 生成新垃圾
            generateGarbage();
            garbageMissed = false;
        }
    }
    
    // 处理输入
    void processInput() {
        if (_kbhit()) {
            char key = _getch();
            
            // 处理方向键(方向键会产生两个字节)
            if (key == 0 || key == -32) { // 224 在 char 中是 -32
                key = _getch(); // 读取第二个字节
                switch (key) {
                    case 72: // 上箭头
                        if (truck.direction != 2) truck.direction = 0;
                        break;
                    case 77: // 右箭头
                        if (truck.direction != 3) truck.direction = 1;
                        break;
                    case 80: // 下箭头
                        if (truck.direction != 0) truck.direction = 2;
                        break;
                    case 75: // 左箭头
                        if (truck.direction != 1) truck.direction = 3;
                        break;
                }
            }
            // 处理普通按键(WASD)
            else {
                switch (key) {
                    case 'w': case 'W':
                        if (truck.direction != 2) truck.direction = 0;
                        break;
                    case 'd': case 'D':
                        if (truck.direction != 3) truck.direction = 1;
                        break;
                    case 's': case 'S':
                        if (truck.direction != 0) truck.direction = 2;
                        break;
                    case 'a': case 'A':
                        if (truck.direction != 1) truck.direction = 3;
                        break;
                    case 27: // ESC键
                        gameOver = true;
                        break;
                }
            }
        }
    }
    
    // 渲染游戏界面
    void render() {
        stringstream buffer;
        const int LINE_WIDTH = 35;  // 固定行宽(与游戏区域宽度一致)
        
        // 绘制标题 - 宽度与游戏区域完全一致
        buffer << string(WIDTH, '=') << endl;
        buffer << padLine("   垃圾分类贪吃蛇", LINE_WIDTH) << endl;
        buffer << string(WIDTH, '=') << endl;
    
        // 绘制游戏区域
        for (int y = 0; y < HEIGHT; y++) {
            stringstream line;
            for (int x = 0; x < WIDTH; x++) {
                // 绘制边框
                if (x == 0 || x == WIDTH - 1 || y == 0 || y == HEIGHT - 1) {
                    line << "#";
                }
                // 绘制垃圾车
                else if (isTruckSegment(x, y)) {
                    if (x == truck.body[0].first && y == truck.body[0].second) {
                        // 车头
                        switch (truck.direction) {
                            case 0: line << "^"; break; // 上
                            case 1: line << ">"; break; // 右
                            case 2: line << "v"; break; // 下
                            case 3: line << "<"; break; // 左
                        }
                    } else {
                        // 车身
                        line << "O";
                    }
                }
                // 绘制垃圾 - 使用单字符符号避免中文对齐问题
                else if (x == currentGarbage.x && y == currentGarbage.y) {
                    line << "@";  // 统一使用 @ 符号
                }
                // 绘制公路地面
                else {
                    line << " ";
                }
            }
            // 确保每行正好是 WIDTH 个字符
            string lineStr = line.str();
            if (lineStr.length() == WIDTH) {
                buffer << lineStr << endl;
            }
        }
    
        // 绘制底部分隔线
        buffer << string(WIDTH, '=') << endl;
    
        // 显示游戏信息 - 使用 stringstream 构建每一行再填充
        stringstream line1, line2, line4;
        line1 << "分数:" << score << " | 长度:" << truck.length;
        buffer << padLine(line1.str(), LINE_WIDTH) << endl;
        
        line2 << "垃圾:" << currentGarbage.name << "(" << getTypeName(currentGarbage.type) << ")";
        buffer << padLine(line2.str(), LINE_WIDTH) << endl;
        
        buffer << string(WIDTH, '=') << endl;
        
        line4 << "控制:方向键/WASD | ESC退出";
        buffer << padLine(line4.str(), LINE_WIDTH) << endl;
        
        buffer << string(WIDTH, '=') << endl;
        
        // 一次性输出整个画面
        setCursorPosition(0, 0);
        cout << buffer.str();
    }
    
    // 检查是否为垃圾车身体部分
    bool isTruckSegment(int x, int y) {
        for (const auto& segment : truck.body) {
            if (segment.first == x && segment.second == y) {
                return true;
            }
        }
        return false;
    }
    
    // 获取垃圾类型名称
    string getTypeName(GarbageType type) {
        switch (type) {
            case RECYCLABLE: return "可回收";
            case HAZARDOUS: return "有害";
            case KITCHEN_WASTE: return "厨余";
            case OTHER_WASTE: return "其他";
            default: return "未知";
        }
    }
    

    // 显示游戏结束界面 void showGameOver() { stringstream buffer; const int LINE_WIDTH = 35; // 固定行宽(与游戏区域一致)

        // 计算需要的总行数:标题(3行) + 游戏区域(HEIGHT行) + 底部信息(5行)
        const int TOTAL_LINES = 3 + HEIGHT + 5;
        
        buffer << string(WIDTH, '=') << endl;
        buffer << padLine("          游戏结束!", LINE_WIDTH) << endl;
        buffer << string(WIDTH, '=') << endl;
        buffer << padLine("", LINE_WIDTH) << endl;
        
        stringstream scoreLine, lengthLine;
        scoreLine << " 最终得分: " << score;
        buffer << padLine(scoreLine.str(), LINE_WIDTH) << endl;
        
        lengthLine << " 车长: " << truck.length;
        buffer << padLine(lengthLine.str(), LINE_WIDTH) << endl;
        
        buffer << padLine("", LINE_WIDTH) << endl;
        buffer << padLine(" 撞墙或撞到自己了!", LINE_WIDTH) << endl;
        buffer << padLine("", LINE_WIDTH) << endl;
        
        // 显示垃圾分类知识
        buffer << padLine("--- 垃圾分类小知识 ---", LINE_WIDTH) << endl;
        buffer << padLine("", LINE_WIDTH) << endl;
        
        stringstream garbageInfo;
        garbageInfo << " " << currentGarbage.name << " [" << getTypeName(currentGarbage.type) << "]";
        buffer << padLine(garbageInfo.str(), LINE_WIDTH) << endl;
        buffer << padLine("", LINE_WIDTH) << endl;
        
        // 显示垃圾详细描述(自动换行)
        vector<string> descLines = wrapText(currentGarbage.description, LINE_WIDTH);
        int descLineCount = 0;
        for (const string& line : descLines) {
            buffer << padLine(line, LINE_WIDTH) << endl;
            descLineCount++;
        }
        
        buffer << padLine("", LINE_WIDTH) << endl;
        buffer << string(WIDTH, '=') << endl;
        buffer << padLine(" 按任意键重新开始...", LINE_WIDTH) << endl;
        buffer << string(WIDTH, '=') << endl;
        
        // 填充空白行,确保覆盖整个游戏界面
        int currentLines = 19 + descLineCount;  // 基础行数 + 描述行数
        for (int i = currentLines; i < TOTAL_LINES; i++) {
            buffer << padLine("", LINE_WIDTH) << endl;
        }
    
        setCursorPosition(0, 0);
        cout << buffer.str();
        _getch(); // 等待按键
    }
    

    public: GarbageSnakeGame() { srand(time(NULL)); hConsole = GetStdHandle(STD_OUTPUT_HANDLE); hideCursor(); initGarbageTemplates(); resetGame(); }

    // 重置游戏
    void resetGame() {
        // 初始化垃圾车
        truck.body.clear();
        truck.body.push_back({WIDTH / 2, HEIGHT / 2}); // 头部
        truck.body.push_back({WIDTH / 2 - 1, HEIGHT / 2}); // 身体部分
        truck.body.push_back({WIDTH / 2 - 2, HEIGHT / 2}); // 身体部分
        truck.direction = 1; // 初始向右移动
        truck.length = 3;
    
        // 初始化游戏状态
        score = 0;
        gameOver = false;
        garbageMissed = false;
    
        // 生成第一个垃圾
        generateGarbage();
    }
    
    // 运行游戏
    void run() {
        system("cls"); // 初始清屏一次
        
        while (true) {
            resetGame();
    
            // 游戏主循环
            while (!gameOver) {
                processInput();
                moveTruck();
                if (gameOver) break;
                render();
                Sleep(120); // 控制游戏速度
            }
    
            showGameOver();
        }
    }
    

    };

    int main() { // 设置控制台代码页为 GBK (936) - Dev C++ 5.x 兼容 system("chcp 936 > nul");

    //设置控制台窗口大小
    system("mode con cols=60 lines=26");
    
    // 设置控制台标题
    system("title 垃圾分类贪吃蛇");
    
    GarbageSnakeGame game;
    game.run();
    
    return 0;
    

    }

  • 通过的题目

  • 最近活动

  • 最近编写的题解

题目标签

语言基础
26
循环语句
21
贪心
14
字符串
14
其他
13
数据结构
13
二维数组
10
字符数组
9
高精度
7
递归
6
NOIP
6
二叉堆
6
竞赛
5
模拟
4
位运算
4
二分
4
排序
4
4
Trie
4
普及组
4