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;
}