#include <iostream>
#include <conio.h>
#include <windows.h>
#include <string>
#include <vector>
#include <ctime>
#include <cstdlib>
#include <map>
#include <algorithm>
using namespace std;
// ======================== 颜色控制 ========================
void setColor(int color) {
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(hConsole, color);
}
void gotoxy(int x, int y) {
COORD coord;
coord.X = x;
coord.Y = y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
}
void hideCursor() {
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_CURSOR_INFO info;
info.dwSize = 100;
info.bVisible = FALSE;
SetConsoleCursorInfo(hConsole, &info);
}
// ======================== 常量 ========================
const int WORLD_SIZE = 1000;
const int CHUNK_SIZE = 100;
const int VIEW_RADIUS = 12;
// 地形类型(全部改用ASCII字符)
enum Terrain {
PLAIN, // 平原 .
FOREST, // 森林 f
MOUNTAIN, // 山地 ^
WATER, // 水域 ~
DESERT, // 沙漠 :
GRASS, // 草地 , (大量)
ROAD // 白色道路 #
};
char getTerrainChar(Terrain t) {
switch(t) {
case PLAIN: return '.';
case FOREST: return 'f';
case MOUNTAIN:return '^';
case WATER: return '~';
case DESERT: return ':';
case GRASS: return ',';
case ROAD: return '#';
default: return ' ';
}
}
int getTerrainColor(Terrain t) {
switch(t) {
case PLAIN: return 8;
case FOREST: return 2;
case MOUNTAIN:return 6;
case WATER: return 9;
case DESERT: return 14;
case GRASS: return 10;
case ROAD: return 7;
default: return 7;
}
}
// ======================== 怪物系统 ========================
enum MonsterType { SLIME, BAT, SKELETON, WOLF, GOBLIN, ORC, TROLL, DRAGON };
struct Monster {
string name;
char symbol;
int hp, maxHp, atk, def, exp;
bool alive;
MonsterType type;
};
Monster createMonster(MonsterType type, int levelScale) {
Monster m;
m.alive = true;
m.type = type;
int atkBonus = (int)(levelScale * 0.8);
int defBonus = (int)(levelScale * 0.4);
switch(type) {
case SLIME: m.name="史莱姆"; m.symbol='S'; m.hp=8+levelScale3; m.atk=2+atkBonus; m.def=0+defBonus; m.exp=5+levelScale2; break;
case BAT: m.name="蝙蝠"; m.symbol='B'; m.hp=6+levelScale2; m.atk=4+atkBonus; m.def=1+defBonus; m.exp=6+levelScale2; break;
case SKELETON:m.name="骷髅"; m.symbol='K'; m.hp=12+levelScale4; m.atk=6+atkBonus; m.def=2+defBonus; m.exp=10+levelScale3; break;
case WOLF: m.name="狼"; m.symbol='W'; m.hp=15+levelScale3; m.atk=7+atkBonus; m.def=3+defBonus; m.exp=12+levelScale3; break;
case GOBLIN: m.name="哥布林"; m.symbol='G'; m.hp=10+levelScale3; m.atk=5+atkBonus; m.def=2+defBonus; m.exp=8+levelScale2; break;
case ORC: m.name="兽人"; m.symbol='O'; m.hp=20+levelScale5; m.atk=8+atkBonus; m.def=4+defBonus; m.exp=15+levelScale4; break;
case TROLL: m.name="巨魔"; m.symbol='T'; m.hp=30+levelScale6; m.atk=10+atkBonus; m.def=5+defBonus; m.exp=20+levelScale5; break;
case DRAGON: m.name="龙"; m.symbol='D'; m.hp=50+levelScale10; m.atk=15+atkBonus; m.def=8+defBonus; m.exp=50+levelScale10; break;
}
m.maxHp = m.hp;
return m;
}
struct MonsterGroup {
vector<Monster> monsters;
bool hasAlive() const {
for (size_t i=0; i<monsters.size(); ++i)
if (monsters[i].alive) return true;
return false;
}
bool isEmpty() const { return monsters.empty() || !hasAlive(); }
void removeDead() {
vector<Monster> alive;
for (size_t i=0; i<monsters.size(); ++i)
if (monsters[i].alive) alive.push_back(monsters[i]);
monsters = alive;
}
void clearAll() { monsters.clear(); }
};
// ======================== 实体系统 ========================
enum EntityType { ENT_NPC, ENT_SHOP, ENT_CHEST };
struct Entity {
int x, y;
int type;
string name;
bool active;
vector<string> shopItems;
vector<int> shopPrices;
string dialogue;
bool opened;
};
// ======================== 区块 ========================
struct ChunkKey {
int cx, cy;
bool operator<(const ChunkKey& other) const {
if (cx != other.cx) return cx < other.cx;
return cy < other.cy;
}
};
struct Chunk {
Terrain terrain[CHUNK_SIZE][CHUNK_SIZE];
map<int, MonsterGroup> monsterGroups;
vector<Entity> entities;
bool generated;
Chunk() : generated(false) {}
};
map<ChunkKey, Chunk> world;
Terrain getTerrainAt(int wx, int wy) {
if (wx<0 || wx>=WORLD_SIZE || wy<0 || wy>=WORLD_SIZE) return GRASS;
int cx = wx / CHUNK_SIZE, cy = wy / CHUNK_SIZE;
int lx = wx % CHUNK_SIZE, ly = wy % CHUNK_SIZE;
ChunkKey key; key.cx=cx; key.cy=cy;
map<ChunkKey, Chunk>::iterator it = world.find(key);
if (it == world.end()) return GRASS;
return it->second.terrain[lx][ly];
}
Entity* getEntityAt(int wx, int wy) {
if (wx<0 || wx>=WORLD_SIZE || wy<0 || wy>=WORLD_SIZE) return NULL;
int cx = wx / CHUNK_SIZE, cy = wy / CHUNK_SIZE;
int lx = wx % CHUNK_SIZE, ly = wy % CHUNK_SIZE;
ChunkKey key; key.cx=cx; key.cy=cy;
map<ChunkKey, Chunk>::iterator it = world.find(key);
if (it == world.end()) return NULL;
vector<Entity>& ents = it->second.entities;
for (size_t i=0; i<ents.size(); ++i) {
if (ents[i].active && ents[i].x == wx && ents[i].y == wy)
return &ents[i];
}
return NULL;
}
MonsterGroup* getMonsterGroupAt(int wx, int wy) {
if (wx<0 || wx>=WORLD_SIZE || wy<0 || wy>=WORLD_SIZE) return NULL;
int cx = wx / CHUNK_SIZE, cy = wy / CHUNK_SIZE;
int lx = wx % CHUNK_SIZE, ly = wy % CHUNK_SIZE;
ChunkKey key; key.cx=cx; key.cy=cy;
map<ChunkKey, Chunk>::iterator it = world.find(key);
if (it == world.end()) return NULL;
int code = lx * CHUNK_SIZE + ly;
map<int, MonsterGroup>::iterator git = it->second.monsterGroups.find(code);
if (git == it->second.monsterGroups.end()) return NULL;
return &(git->second);
}
// ======================== 生成区块 ========================
void generateChunk(int cx, int cy) {
ChunkKey key; key.cx=cx; key.cy=cy;
if (world.find(key) != world.end()) return;
}
void ensureChunksAround(int wx, int wy) {
int cx = wx / CHUNK_SIZE, cy = wy / CHUNK_SIZE;
for (int dx=-2; dx<=2; ++dx)
for (int dy=-2; dy<=2; ++dy)
if (world.find(ChunkKey{cx+dx, cy+dy}) == world.end())
generateChunk(cx+dx, cy+dy);
}
// ======================== 玩家 ========================
struct Player {
int x, y;
int hp, maxHp;
int atk, def;
int level, exp, maxExp;
int gold;
string name;
vector<string> inventory;
int weaponBonus, armorBonus;
Player() : x(WORLD_SIZE/2), y(WORLD_SIZE/2), hp(30), maxHp(30),
atk(5), def(3), level(1), exp(0), maxExp(10),
gold(20), name("勇者"), weaponBonus(0), armorBonus(0) {}
};
Player player;
// ======================== 战斗系统 ========================
void battleMonsterGroup(MonsterGroup* group) {
if (!group) return;
group->removeDead();
if (group->monsters.empty()) return;
}
// ======================== 交互系统 ========================
void interactWithEntity(Entity* ent) {
if (!ent || !ent->active) return;
system("cls");
if (ent->type == ENT_NPC) {
setColor(13);
cout << "?? " << ent->name << " 说: " << ent->dialogue << endl;
setColor(7);
cout << "按任意键继续..." << endl;
_getch();
} else if (ent->type == ENT_SHOP) {
setColor(14);
cout << "?? " << ent->name << " 的商店" << endl;
setColor(7);
cout << "你的金币: " << player.gold << endl;
cout << "商品列表:" << endl;
for (size_t i=0; i<ent->shopItems.size(); ++i) {
cout << " [" << i+1 << "] " << ent->shopItems[i] << " - " << ent->shopPrices[i] << " 金币" << endl;
}
cout << " [0] 离开" << endl;
cout << "选择: ";
char c = _getch(); cout << c << endl;
int idx = c - '1';
if (idx >= 0 && idx < (int)ent->shopItems.size()) {
if (player.gold >= ent->shopPrices[idx]) {
player.gold -= ent->shopPrices[idx];
player.inventory.push_back(ent->shopItems[idx]);
setColor(11);
cout << "购买了 " << ent->shopItems[idx] << "!" << endl;
setColor(7);
} else {
setColor(12);
cout << "金币不足!" << endl;
setColor(7);
}
}
cout << "按任意键继续..." << endl;
_getch();
} else if (ent->type == ENT_CHEST) {
if (ent->opened) {
setColor(14);
cout << "宝箱已经空了。" << endl;
setColor(7);
_getch();
return;
}
setColor(14);
cout << "?? 打开宝箱!" << endl;
ent->opened = true;
int reward = rand() % 100;
if (reward < 50) {
int gold = 10 + rand() % 30;
player.gold += gold;
setColor(11);
cout << "获得 " << gold << " 金币!" << endl;
} else if (reward < 80) {
player.inventory.push_back("小红瓶");
setColor(11);
cout << "获得 小红瓶!" << endl;
} else {
player.inventory.push_back("大药水");
setColor(11);
cout << "获得 大药水!" << endl;
}
setColor(7);
_getch();
}
}
// ======================== 渲染 ========================
void render() {
system("cls");
setColor(14);
cout << "=== 大世界探索 ===";
setColor(10);
cout << " Lv." << player.level << " HP:" << player.hp << "/" << player.maxHp;
setColor(13);
cout << " 经验:" << player.exp << "/" << player.maxExp;
setColor(11);
cout << " 金币:" << player.gold;
setColor(7);
cout << " (" << player.x << "," << player.y << ")" << endl;
setColor(8);
cout << "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" << endl;
}
// ======================== 背包 ========================
void showInventory() {
system("cls");
setColor(14);
cout << "=== 背包 ===" << endl;
setColor(7);
cout << "HP:" << player.hp << "/" << player.maxHp
<< " 攻击:" << player.atk+player.weaponBonus
<< " 防御:" << player.def+player.armorBonus << endl;
cout << "金币:" << player.gold << " 等级:" << player.level << endl;
setColor(10);
cout << "物品 (" << player.inventory.size() << "):" << endl;
setColor(7);
if (player.inventory.empty()) cout << " (空)" << endl;
else for (size_t i=0; i<player.inventory.size(); ++i)
cout << " " << i+1 << ". " << player.inventory[i] << endl;
setColor(14);
cout << "按任意键返回..." << endl;
setColor(7);
_getch();
}
// ======================== 主循环 ========================
void gameLoop() {
char key;
while (player.hp > 0) {
ensureChunksAround(player.x, player.y);
render();
}
// ======================== 菜单 ========================
void showMenu() {
system("cls");
setColor(14);
cout << "╔═══════════════════════════════════╗" << endl;
cout << "║ ?? 大世界探索游戏 ║" << endl;
cout << "║ (1000x1000 开放世界) ║" << endl;
cout << "║ NPC(N) · 商店($) · 宝箱(?) ║" << endl;
cout << "╚═══════════════════════════════════╝" << endl;
setColor(7);
cout << "[1] 开始游戏" << endl;
cout << "[2] 退出" << endl;
cout << "选择: ";
char c = _getch();
if (c == '1') {
player = Player();
ensureChunksAround(player.x, player.y);
gameLoop();
// 从游戏循环返回后,重新显示菜单(即允许重新开始)
showMenu(); // 递归调用,但会重新显示菜单
} else exit(0);
}
// ======================== main ========================
int main() {
srand((unsigned)time(0));
hideCursor();
showMenu();
return 0;
}