简易版2D我的世界C++程序(有点BUG,但是可以玩!!!)
1、按空格键来切换模式(挖掘模式和放置模式),一律用鼠标右键来操作!!! 2、按数字1和2键来切换放置的方块(1是草,2是木),树叶不能放置!!! 3、树木生成时可能有点BUG。 4、在操作时位置会有点偏移,请见谅。 5、地图默认大小为20*20,可以自己修改。(第15行和第16行) 6、本程序应该会持续更新
更新日志:
4月25日: 1、更新了新方块“石”,按数字3键切换(没错,树叶依然不可以放置) 2、石头会生成在草方块下面,会生成5层。 3、更改了地图的大小,为25*18。 4、操作偏移的bug依然存在(改了好几次,结果改的更离谱了)
#include <iostream>
#include <vector>
#include <string>
#include <cstdlib>
#include <ctime>
#include <windows.h>// 定义方块类型
typedef int BlockType;// 定义方块名称
const std::string BLOCK_NAMES[] = { "", "草", "木", "叶", "石" };// 定义世界的大小
const int WORLD_WIDTH = 25;
const int WORLD_HEIGHT = 18;// 定义世界地图
class World {
private:std::vector<std::vector<BlockType> > blocks;public:World() {blocks.resize(WORLD_HEIGHT);for (int y = 0; y < WORLD_HEIGHT; ++y) {blocks[y].resize(WORLD_WIDTH, 0);}generateTerrain();generateTrees();}// 生成简单地形void generateTerrain() {srand(static_cast<unsigned int>(time(NULL)));for (int x = 0; x < WORLD_WIDTH; ++x) {int height = rand() % 3 + 1;// 生成石头for (int y = WORLD_HEIGHT - 1; y >= WORLD_HEIGHT - 5; --y) {blocks[y][x] = 4;}// 生成草for (int y = WORLD_HEIGHT - 6; y >= WORLD_HEIGHT - 6 - height + 1; --y) {blocks[y][x] = 1;}}}// 生成树木void generateTrees() {for (int x = 0; x < WORLD_WIDTH; x += 5) { // 每隔 5 个方块尝试生成树木if (rand() % 2 == 0) { // 50% 的概率生成树木int baseY = WORLD_HEIGHT - 7; // 从可能的最上层草方块开始找while (baseY >= 0 && blocks[baseY][x] != 1) baseY--; // 找到最上层的草方块if (baseY > 0) {int treeHeight = rand() % 3 + 3; // 树高 3 - 5// 生成树干for (int i = 0; i < treeHeight; ++i) {if (baseY - i >= 0) {blocks[baseY - i][x] = 2;}}// 生成树叶int leafTop = baseY - treeHeight;for (int dy = -1; dy <= 1; ++dy) {for (int dx = -1; dx <= 1; ++dx) {if (leafTop + dy >= 0 && x + dx >= 0 && x + dx < WORLD_WIDTH) {blocks[leafTop + dy][x + dx] = 3;}}}}}}}// 放置方块void placeBlock(int x, int y, BlockType block) {if (x >= 0 && x < WORLD_WIDTH && y >= 0 && y < WORLD_HEIGHT) {blocks[y][x] = block;}}// 挖掘方块void digBlock(int x, int y) {if (x >= 0 && x < WORLD_WIDTH && y >= 0 && y < WORLD_HEIGHT) {blocks[y][x] = 0;}}// 查看方块BlockType getBlock(int x, int y) {if (x >= 0 && x < WORLD_WIDTH && y >= 0 && y < WORLD_HEIGHT) {return blocks[y][x];}return 0;}// 显示世界void display(HANDLE hOut) {COORD coord = { 0, 0 };SetConsoleCursorPosition(hOut, coord);for (int y = 0; y < WORLD_HEIGHT; ++y) {for (int x = 0; x < WORLD_WIDTH; ++x) {std::string blockName = BLOCK_NAMES[blocks[y][x]];if (blockName.empty()) {std::cout << " ";} else {std::cout << blockName;if (blockName.length() == 1) {std::cout << " ";}}std::cout << " "; // 方块之间添加一个空格}std::cout << std::endl;}}
};// 获取鼠标点击的坐标并转换为地图坐标
void getMouseCoordinates(int& x, int& y) {POINT cursorPos;GetCursorPos(&cursorPos);HWND consoleWindow = GetConsoleWindow();RECT consoleRect;GetWindowRect(consoleWindow, &consoleRect);// 修正鼠标坐标转换,确保准确对应方块x = (cursorPos.x - consoleRect.left) / 25;y = (cursorPos.y - consoleRect.top) / 20;if (x < 0) x = 0;if (x >= WORLD_WIDTH) x = WORLD_WIDTH - 1;if (y < 0) y = 0;if (y >= WORLD_HEIGHT) y = WORLD_HEIGHT - 1;
}int main() {World world;BlockType currentBlock = 1; // 初始方块类型为草bool rightButtonDown = false;bool key1Down = false;bool key2Down = false;bool key3Down = false;bool spaceDown = false;bool isDigging = false; // 初始为放置模式HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);while (true) {// 双缓冲技术:先移动光标到屏幕左上角world.display(hOut);std::cout << "当前选择的方块:" << BLOCK_NAMES[currentBlock] << std::endl;std::cout << "当前模式:" << (isDigging ? "挖掘" : "放置") << std::endl;// 检测空格键切换模式if ((GetAsyncKeyState(VK_SPACE) & 0x8000) && !spaceDown) {isDigging = !isDigging;spaceDown = true;} else if (!(GetAsyncKeyState(VK_SPACE) & 0x8000)) {spaceDown = false;}// 检测鼠标右键if ((GetAsyncKeyState(VK_RBUTTON) & 0x8000) && !rightButtonDown) {int x, y;getMouseCoordinates(x, y);if (isDigging) {world.digBlock(x, y);} else {world.placeBlock(x, y, currentBlock);}rightButtonDown = true;} else if (!(GetAsyncKeyState(VK_RBUTTON) & 0x8000)) {rightButtonDown = false;}// 检测数字 1 键if ((GetAsyncKeyState(0x31) & 0x8000) && !key1Down) {currentBlock = 1;key1Down = true;} else if (!(GetAsyncKeyState(0x31) & 0x8000)) {key1Down = false;}// 检测数字 2 键if ((GetAsyncKeyState(0x32) & 0x8000) && !key2Down) {currentBlock = 2;key2Down = true;} else if (!(GetAsyncKeyState(0x32) & 0x8000)) {key2Down = false;}// 检测数字 3 键if ((GetAsyncKeyState(0x33) & 0x8000) && !key3Down) {currentBlock = 4;key3Down = true;} else if (!(GetAsyncKeyState(0x33) & 0x8000)) {key3Down = false;}if (GetAsyncKeyState(VK_ESCAPE) & 0x8000) { // 按下 ESC 键退出break;}Sleep(50);}return 0;
}