当前位置: 首页 > news >正文

简易版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;
}

相关文章:

  • 教育领域的AIGC革命:构建多模态智能教学系统
  • Java 安全:如何保护敏感数据?
  • pytorch python常用指令
  • GoLang基础
  • Java ThreadLocal与内存泄漏
  • SD模型的评估指标(挖坑中..)
  • 【强化学习(实践篇)】#1 多臂赌博机网格世界
  • 腾讯云智三道算法题
  • chrony服务器(1)
  • Python赋能教育:构建智能考试评分系统的最佳实践
  • 上位机知识篇---时钟分频
  • Android学习总结之自定义View绘制源码理解
  • springboot入门-controller层
  • 多系统安装经验,移动硬盘,ubuntu grub修改/etc/fstab 移动硬盘需要改成nfts格式才能放steam游戏
  • YOLOv8改进新路径:Damo-YOLO与Dyhead融合的创新检测策略
  • 第三方测试机构如何保障软件质量并节省企业成本?
  • Xilinx FPGA支持的FLASH型号汇总
  • git 工具
  • 架构进阶:105页PPT学习数字化转型企业架构设计手册【附全文阅读】
  • ARM架构的微控制器总线矩阵仲裁策略
  • 第一集丨《无尽的尽头》值得关注,《榜上佳婿》平平无奇
  • 首映|《人生开门红》:段子背后都是案子
  • 如何做大中国拳击产业的蛋糕?这项赛事给出办赛新思考
  • 王毅会见乌兹别克斯坦外长赛义多夫
  • 亚振家居控制权将变更:济南域潇集团实控人成新控股股东
  • 石磊当选河北秦皇岛市市长