自从我上一篇文章以来,我对代码进行了彻底的修改,到目前为止我已经做到了这一点,但我需要从这里开始,我感觉被困住了。我犯的最后一个错误是有太多 if else 语句,我不想在这里重复。我想为每个交易者创建不同的库存,并且让用户可以选择他想要购买/出售的交易者,然后当他完成后可以退出游戏,选择不同的交易者或切换世界。然后在不同的世界中,我也希望有不同的交易者,而不是,我希望它是随机的。
#include <iostream>
#include <map>
#include <vector>
using namespace std;
class World {
// A class to create the worlds
private:
string world_name;
string world_description;
public:
void create_world(string name, string w_description) {
// Creates different worlds
world_name = name;
world_description = w_description;
}
string greet() const {
// A greeting function
return "Welcome to the world of " + world_name + "!\n" + world_description + '\n';
}
string get_world_name() const {
return world_name;
}
string get_world_description() const {
return world_description;
}
};
class Inventory {
// A class to initialize the inventory
private:
map<string, int> inventory;
public:
void create_inventory(string item_name, int item_price) {
// Creates the inventory
inventory[item_name] = item_price;
}
void show_inventory(string currency_name) {
cout << "Inventory: \n";
for (const auto& item : inventory) {
cout << item.first << " - " << item.second << ' ' << currency_name << '\n';
}
}
};
class Trader {
// A class to initialize the traders
private:
string trader_name;
public:
void create_traders(string name) {
// Creates the traders
trader_name = name;
}
string get_trader_names() const {
return trader_name;
}
};
int main() {
// World initializing and creating
vector<World> worlds;
World w1, w2, w3;
w1.create_world("Celestia Falls","A world hidden in the waterfalls of Gonkun.");
w2.create_world("Skypedia", "A world hidden in the clouds of Gonkun.");
w3.create_world("Wano", "A world hidden somewhere in the oceans of Gonkun.");
// Adds the worlds to the vector
worlds.push_back(w1);
worlds.push_back(w2);
worlds.push_back(w3);
cout << "Welcome to the world of Gonkun where you can find anything you'd want in the many islands here.\n";
cout << "Select the number of the world you'd first like to go to.\n";
cout << "Press return after selecting an option.\n\n";
// Displays the world options
for (size_t i = 0; i < worlds.size(); ++i) {
cout << i + 1 << ". " << worlds[i].get_world_name() << '\n';
}
bool run = true;
while (run) {
int world_choice;
cin >> world_choice;
// Validate the input and display the chosen world
if (world_choice >= 1 && world_choice <= worlds.size()) {
cout << '\n' << worlds[world_choice - 1].greet() << "\n";
run = false;
}
else {
cout << "Please select a valid choice.\n";
}
}
vector<Trader> traders;
vector<string> trader_names = {
"Zephyr", "Cyrus", "Luna", "Eos"
};
for (size_t i = 0; i < 4; ++i) {
Trader trader;
trader.create_traders(trader_names[i]);
traders.push_back(trader);
}
for (size_t i = 0; i < traders.size(); ++i) {
cout << i + 1 << ". " << traders[i].get_trader_names() << '\n';
}
cout << "Pick the number of the trader you'd like to trade with.\n\n";
return 0;
}
我尝试过 if else 语句,但它们太长了,我想优化我的代码。我也尝试过 while 循环,但我迷失在它们中,并且我不完全知道如何以正常工作的方式构建它。
对于初学者: 看来您对于如何执行程序工作流程没有明确的设计/布局。我建议你花一些时间在纸上记下你的想法以及你希望整个流程如何运作。我已经为您做了一些关于我对游戏运行方式的更新。您还会在这里看到一些更现代化的概念。
我认为你需要了解 while 循环内部的 while 循环的概念,以及如何在适当的时候成功地摆脱它们。
尽管如此,这里有一些更新代码可以帮助您入门。
#include <iostream>
#include <map>
#include <vector>
#include <string>
#include <thread>
// Constant for exit code from working while loop
constexpr int EXIT_CODE = -1;
/// @brief Forces a user to input a valid numeric input
/// @param min - minimum acceptable input value
/// @param max - maximum acceptable input value
/// @return - validated user input
static int GetValidInput(int min, int max, int breakout)
{
int userInput;
bool valid = false;
while (!valid)
{
std::cin.clear();
std::cout << "Please enter a valid numeric value (" << breakout << " to exit): ";
std::cin >> userInput;
// Check if the input failed (not a number)
if (std::cin.fail())
{
// Clear error flags and ignore invalid input
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::cout << "That's not a valid number. Please try again." << std::endl;
}
else if (userInput == breakout)
{
return breakout;
}
else if (userInput < min || userInput > max)
{
// Check if the number is within the valid range
std::cout << "The number is out of range. Please enter a number between 0 and 3." << std::endl;
}
else {
// Input is valid and within the range
valid = true;
}
}
std::cin.clear();
return userInput;
}
/// @brief A class to represent an item
class Item
{
public:
Item() {}
Item(std::string name, std::string description, unsigned int quantity, double price) : Item()
{
m_name = name;
m_description = description;
m_quantity = quantity;
m_price = price;
}
std::string GetName() const
{
return m_name;
}
std::string GetDescription() const
{
return m_description;
}
unsigned int GetQuantity() const
{
return m_quantity;
}
double GetPrice() const
{
return m_price;
}
bool SetPrice(const double price)
{
m_price = price;
return m_price == price;
}
unsigned int IncrementQuantity(const unsigned int increment)
{
return (m_quantity += increment);
}
unsigned int DecrementQuantity(const unsigned int deccrement)
{
m_quantity = (m_quantity - deccrement) <= 0 ? 0 : m_quantity -= deccrement;
return m_quantity;
}
private:
unsigned int m_quantity = 0;
std::string m_name;
std::string m_description;
double m_price = 0;
};
/// @brief A class to initialize the traders
class Trader {
private:
std::string m_name;
std::string m_bio;
std::vector<Item> m_inventory;
public:
Trader(std::string name, std::string bio)
{
m_name = name;
m_bio = bio;
}
std::string GetName() const
{
return m_name;
}
std::string GetBio() const
{
return m_bio;
}
void AddInventory(Item item)
{
m_inventory.push_back(item);
}
};
/// @brief A class to create the worlds
class World
{
private:
std::string m_worldName;
std::string m_worldDescription;
std::vector<Trader> m_traders;
public:
World() = default;
World(std::string name, std::string w_description)
: m_worldName(std::move(name)), m_worldDescription(std::move(w_description)) {}
// Default Destructor
~World() = default;
// Default Copy Constructor
World(const World&) = default;
// Default Copy Assignment Operator
World& operator=(const World&) = default;
// Default Move Constructor
World(World&&) noexcept = default;
// Default Move Assignment Operator
World& operator=(World&&) noexcept = default;
void CreateWorld(std::string name, std::string w_description) {
// Creates different worlds
m_worldName = name;
m_worldDescription = w_description;
}
std::string Greet() const {
// A greeting function
return "\nWelcome to the world of " + m_worldName + "!\n" + m_worldDescription + '\n';
}
std::string GetWorldName() const {
return m_worldName;
}
std::string GetWorldDescription() const {
return m_worldDescription;
}
void AddTrader(Trader newTrader)
{
m_traders.push_back(newTrader);
}
void PrintTraders()
{
if (m_traders.size() == 0)
{
std::cout << "No Active Traders In This World!\nReturning to transport hub!\n\n";
}
else
{
std::cout << "\nTraders:\n";
for (size_t i = 0; i < m_traders.size(); ++i)
{
Trader temp = m_traders[i];
std::cout << "\t" << i << ": " << temp.GetName() << " - " << temp.GetBio() << "\n";
}
}
std::cout << std::endl;
}
void WorldInterface()
{
bool run = true;
std::cout << Greet();
PrintTraders();
if (m_traders.size() <= 0)
{
std::cout << "No traders on this world!\n";
run = false;
}
while (run)
{
// Allow the user to interact with the world;
int input = GetValidInput(1, m_traders.size(), EXIT_CODE);
switch (input)
{
case EXIT_CODE:
run = false;
continue;
case 1:
break;
case 2:
break;
case 3:
break;
default:
break;
}
}
std::cout << "Returning to transport hub!\n";
}
};
class GameMap
{
public:
GameMap()
{
// Adds the worlds to the vector
m_worlds.push_back(World("Celestia Falls", "A world hidden in the waterfalls of Gonkun."));
m_worlds.push_back(World("Skypedia", "A world hidden in the clouds of Gonkun."));
m_worlds.push_back(World("Wano", "A world hidden somewhere in the oceans of Gonkun."));
m_worlds[0].AddTrader(Trader("Chip", "A helpful trader specializing in software."));
m_worlds[0].AddTrader(Trader("Cyborg", "A unique trader specializing in rare electronics."));
}
void PrintWelcome()
{
std::cout << "Welcome to the world of Gonkun where you can find anything you'd want in the many islands here.\n"
<< "Select the number of the world you'd like to visit.\n"
<< "Press return after selecting an option.\n\n";
}
void PrintWorlds()
{
std::cout << "\nWorlds:\n";
for (size_t i = 0; i < m_worlds.size(); ++i)
{
World temp = m_worlds[i];
std::cout << "\t" << i + 1 << ": " << temp.GetWorldName() << " - " << temp.GetWorldDescription() << "\n";
}
std::cout << std::endl;
}
int GetNumberOfWorlds()
{
return m_worlds.size();
}
bool ChangeWorld(unsigned int worldNumber)
{
try {
m_activeWorld = &m_worlds.at(worldNumber);
return true;
}
catch (const std::out_of_range& e) {
// Handle the case where the index is out of range
std::cerr << "Caught an out_of_range exception: " << e.what() << std::endl;
}
catch (const std::exception& e) {
// Handle other potential exceptions
std::cerr << "Caught an exception: " << e.what() << std::endl;
}
return false;
}
World* GetActiveWorld()
{
return m_activeWorld;
}
private:
std::vector<World> m_worlds;
World* m_activeWorld = nullptr;
};
int main()
{
GameMap map;
map.PrintWelcome();
bool run = true;
while (run)
{
map.PrintWorlds();
int input = GetValidInput(1, map.GetNumberOfWorlds(), EXIT_CODE);
bool goodTransport = false;
switch (input)
{
case EXIT_CODE:
run = false;
continue; // continue to next iteration of loop. Will exit.
case 1:
[[fallthrough]];
case 2:
[[fallthrough]];
case 3:
goodTransport = map.ChangeWorld(input-1);
break;
case 0:
default:
break;
}
if (not goodTransport)
{
std::cout << "[ERROR] - Failed to transport to new world!\n";
continue;
}
else
{
std::string message = "Transporting.....";
std::cout << message;
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << "\r" << std::string(message.size(), ' ') << "\r";
}
World* currentWorld = map.GetActiveWorld();
if (currentWorld != nullptr)
{
currentWorld->WorldInterface();
}
else
{
std::cout << "[ERROR] - Got lost transporting to new world!";
}
std::cout << "\n\n\n";
}
std::cout << "Closing!";
return 0;
}