如何创建Worlds父类优化C++代码并实现随机加载世界
实现Worlds父类与随机世界加载的完整方案
1. 定义Worlds抽象基类
将通用逻辑(问候函数、商人库存)封装到基类中,通过纯虚函数强制子类实现特有加载逻辑:
#include <iostream> #include <string> #include <unordered_map> #include <vector> #include <cstdlib> #include <ctime> #include <memory> // 前向声明Player类 class Player; class Worlds { protected: // 统一存储商人库存:键为物品名称,值为数量 std::unordered_map<std::string, int> merchantInventory; // 世界名称,由子类初始化 std::string worldName; public: // 构造函数:初始化世界名称 Worlds(const std::string& name) : worldName(name) {} // 虚析构函数:确保子类对象能正确析构 virtual ~Worlds() = default; // 复用的通用问候函数 void greetPlayer(const Player& player) const; // 纯虚函数:子类必须实现的世界加载逻辑 virtual void loadWorld() = 0; // 只读接口:供外部访问商人库存 const std::unordered_map<std::string, int>& getMerchantInventory() const { return merchantInventory; } // 获取世界名称 const std::string& getWorldName() const { return worldName; } };
2. 实现Player类(适配世界交互)
class Player { private: std::string name; public: Player(const std::string& playerName) : name(playerName) {} const std::string& getName() const { return name; } // 玩家浏览商人库存的示例方法 void browseMerchant(const Worlds& world) const { std::cout << "\n" << name << " is browsing merchant inventory in " << world.getWorldName() << ":" << std::endl; for (const auto& item : world.getMerchantInventory()) { std::cout << "- " << item.first << ": " << item.second << std::endl; } } }; // 实现Worlds类的问候函数 void Worlds::greetPlayer(const Player& player) const { std::cout << "Welcome to " << worldName << ", " << player.getName() << "! Prepare your adventure!" << std::endl; }
3. 实现子类CelestialFalls与Skypedia
继承Worlds类,重写加载函数并初始化特有商人库存:
class CelestialFalls : public Worlds { public: CelestialFalls() : Worlds("Celestial Falls") {} void loadWorld() override { std::cout << "Loading Celestial Falls..." << std::endl; // 初始化该世界的商人库存 merchantInventory["Starflower"] = 10; merchantInventory["Moonstone"] = 5; merchantInventory["Cloud Potion"] = 3; // 可添加特有加载逻辑(如生成地形、NPC) std::cout << "Celestial Falls loaded successfully!" << std::endl; } // 子类特有功能(可选) void activateWaterfall() { std::cout << "The celestial waterfall glows with magical light!" << std::endl; } }; class Skypedia : public Worlds { public: Skypedia() : Worlds("Skypedia") {} void loadWorld() override { std::cout << "Loading Skypedia..." << std::endl; // 初始化该世界的商人库存 merchantInventory["Sky Feather"] = 15; merchantInventory["Wind Crystal"] = 7; merchantInventory["Flying Carpet"] = 1; // 可添加特有加载逻辑 std::cout << "Skypedia loaded successfully!" << std::endl; } // 子类特有功能(可选) void openSkyLibrary() { std::cout << "The sky library's doors open, revealing ancient scrolls!" << std::endl; } };
4. 实现随机世界加载逻辑
用智能指针管理世界实例,通过随机索引选择并加载目标世界:
int main() { // 初始化随机数种子,确保每次运行结果不同 std::srand(std::time(nullptr)); // 创建玩家实例 Player player("Hero"); // 存储所有可用世界的智能指针,避免内存泄漏 std::vector<std::unique_ptr<Worlds>> availableWorlds; availableWorlds.push_back(std::make_unique<CelestialFalls>()); availableWorlds.push_back(std::make_unique<Skypedia>()); // 随机选择一个世界 int randomIndex = std::rand() % availableWorlds.size(); Worlds* selectedWorld = availableWorlds[randomIndex].get(); // 执行世界加载流程 selectedWorld->loadWorld(); selectedWorld->greetPlayer(player); player.browseMerchant(*selectedWorld); // 调用子类特有功能(可选,通过dynamic_cast判断类型) if (auto celestialWorld = dynamic_cast<CelestialFalls*>(selectedWorld)) { celestialWorld->activateWaterfall(); } else if (auto skypediaWorld = dynamic_cast<Skypedia*>(selectedWorld)) { skypediaWorld->openSkyLibrary(); } return 0; }
关键注意事项
- 基类必须添加虚析构函数:否则通过父类指针销毁子类对象会触发未定义行为。
- 纯虚函数
loadWorld():强制子类实现特有加载逻辑,保证每个世界的初始化一致性。 - 商人库存的封装:基类用protected存储库存,子类可直接修改,同时提供只读接口供外部访问,兼顾灵活性和安全性。
- 随机数生成:用
std::time(nullptr)初始化种子,确保每次运行的随机结果不同;若需要更精准的随机逻辑,可替换为C++11的<random>库。
内容的提问来源于stack exchange,提问作者Ali Jabri
相关产品推荐
相关产品推荐

