简易版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;
}
相关推荐
nuannuan2311a3 小时前
97AB-ASEMI机器人功率器件专用97AB
单片机
落雨封海5 小时前
【5】GD32 基础通信外设:USART、I2C、SPI
单片机
yt948328 小时前
STM32裸机编程架构与思路
单片机·嵌入式硬件
夜月yeyue11 小时前
STM32 USB配置详解
stm32·单片机·嵌入式硬件
技术干货贩卖机12 小时前
0基础 | Proteus仿真 | 继电器
嵌入式硬件·51单片机·proteus·继电器·0基础
熬夜的猪仔12 小时前
零基础制作Freertos智能小车(教程非常简易)持续更新中....
stm32·freertos·智能小车
逼子格14 小时前
电路中的DGND、GROUND、GROUND_REF的区别,VREF、VCC、VDD、VEE和VSS的区别?
嵌入式硬件·硬件工程·硬件工程师·电源·接地·硬件工程师真题
总结所学14 小时前
擦除整片flash后,程序下载到单片机,单片机不运行
单片机·嵌入式硬件
2401_8888597115 小时前
STM32 ADC模数转换器
stm32·单片机·嵌入式硬件