-
个人简介
#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;}
-
通过的题目
-
最近活动
- 红盾算法班(综合练习) 作业
- 红盾周六晚上班(函数) 作业
- 少年宫周五晚上中级A2班【吴飞】(位运算2) 作业
- 少年宫周日晚上初级A2班【ZZB】(二维数组) 作业
- 少年宫周日晚上初级A1班【ZZB】(循环、一维数组综合练习) 作业
- 红盾周六晚上班(高精度算法) 作业
- 少年宫周日晚上初级A1班【ZZB】(一维数组2) 作业
- 红盾周六晚上班(字符数组) 作业
- 红盾周六晚上班(二维数组2) 作业
- 少年宫周日晚上初级A2班【ZZB】(循环嵌套2) 作业
- 红盾周六晚上班(二维数组) 作业
- GESP202509一级题目 IOI
- 少年宫周日晚上初级A2班 IOI
- 红盾周六晚上班(一维数组2) 作业
- 少年宫周日晚上初级A2班【ZZB】(循环嵌套) 作业
- 少年宫周日晚上初级A2班【ZZB】(while循环) 作业
- 少年宫周日晚上初级A2班【ZZB】(for循环) 作业
-
最近编写的题解
题目标签
- 语言基础
- 26
- 循环语句
- 21
- 贪心
- 14
- 字符串
- 14
- 其他
- 13
- 数据结构
- 13
- 二维数组
- 10
- 字符数组
- 9
- 高精度
- 7
- 递归
- 6
- NOIP
- 6
- 二叉堆
- 6
- 竞赛
- 5
- 模拟
- 4
- 位运算
- 4
- 二分
- 4
- 排序
- 4
- 栈
- 4
- Trie
- 4
- 普及组
- 4