683. K Empty Slots

问题描述
There is a garden with N slots. In each slot, there is a flower. The N flowers will bloom one by one in N days. In each day, there will be exactly one flower blooming and it will be in the status of blooming since then.
Given an array flowers consists of number from 1 to N. Each number in the array represents the place where the flower will open in that day.
For example, flowers[i] = x means that the unique flower that blooms at day i will be at position x, where i and x will be in the range from 1 to N.
Also given an integer k, you need to output in which day there exists two flowers in the status of blooming, and also the number of flowers between them is k and these flowers are not blooming.
If there isn’t such day, output -1.
Example1:
这里写图片描述
Example2:
这里写图片描述
Note: The given array will be in the range [1, 20000].

解题思路
该问题是花园中有N个槽,每次在槽中种一朵花。给定种花的顺序flowers,flowers[i] = x表示第i天,在第x个槽种下一朵花。另外给定数字k,求flowers中是否存在某一天,满足相隔k距离的两个端点恰好各有一朵花,而这两朵花之间的k个槽都没有花。我们可以用一个数组k来存储种花的信息数组的下标表示在第几个槽,而数组的元素值表示这个槽种花的日期,首先可以遍历flowers将所有花种下去,信息存储在day[]中,定义好两个相距k的点在数组中移动,然后遍历day[]寻找满足条件的结果。

代码展示

#include<iostream>
#include<stdlib.h>
#include<vector>
#include<math.h>

using namespace std;

class Solution {
public:
    int kEmptySlots(vector<int>& flowers, int k) {
        int n = flowers.size();
        int day[n];
        for(int i=0;i<n;i++){
            day[flowers[i]-1] = i+1;
        }
        int L=0, R= k+1, res=20000; 
        for(int i=0;R<n;i++){
            if(day[i] < day[L] || day[i] <= day[R]){   
                if(i == R)  res = min(res, max(day[L], day[R])); 
                L = i;
                R = k + 1 + i;
            }
        } 
        return (res == 20000)?-1:res;
    }
}; 

int main(){
    int n, a;
    vector<int> flowers;
    cout<<"请输入flowers的大小:";
    cin>>n;
    for(int i = 0;i<n;i++){
        cin>>a;
        flowers.push_back(a);
    }
    int k;
    cout<<"请输入k值:"; 
    cin>>k;
    Solution solution;
    int result=solution.kEmptySlots(flowers, k);

     cout<<result<<endl;
}

运行结果展示
这里写图片描述
这里写图片描述

整合这个代码与之前的合成表系统,并请你解决使用任意格数的合成方块输入合成表时依然是9格输入的问题,并且在设置了输出槽后,不应该有输出数量询问了(直接在输出槽里回答),并且,统计材料和逐步合成都是看输入框里的物品的,合成出的是输出框里的物品,此外,我们发现程序在启动时并不能找到之前的保存位置,请用一个文件来设置保存位置,另外,由于一些问题,导致输入的代码补全,请你补全他。 代码: #include #include #include #include #include #include #include #include #include #include #include #include #include #include <unordered_map> #include <unordered_set> #include #include #include #include #include #include #include #include #include #include <type_traits> #include <string_view> using namespace std; namespace fs = filesystem; using namespace std::literals; // ===================== 函数预定义 ===================== void clear(), wait(int),pause(); // ====================== 类型定义 ====================== using CraftGrid = array<array<pair<string, short>, 3>, 3>; using MaterialMap = unordered_map<string, long long>; // ====================== 常量定义 ====================== constexpr short DEFAULT_MAX_STACK = 64; constexpr short MAX_RECIPES_PER_ITEM = 10; constexpr short MAX_CRAFTING_BLOCKS = 20; // ====================== 合成表类 ====================== class ItemTable { public: enum PathMode : uint8_t { SHORTEST, LONGEST, EXACT }; enum BatchMode : uint8_t { EXACT_BATCH, MERGE_BATCH }; private: CraftGrid grid; vector<pair<string, short>> outputs; // 多输出槽支持 string blockID; // 关联的合成方块ID short craftCount = 1; // 每次合成产出数量 public: ItemTable() = default; // 设置网格项 void setItem(int x, int y, const string& id, short count) noexcept { if (x >= 0 && x < 3 && y >= 0 && y < 3) { grid[x][y] = make_pair(id, count); } } // 获取网格项 const pair<string, short>& getItem(int x, int y) const noexcept { static const pair<string, short> empty = make_pair("", 0); return (x >= 0 && x < 3 && y >= 0 && y < 3) ? grid[x][y] : empty; } // 设置输出槽 void setOutputSlot(size_t slot, const string& id, short count) { if (slot >= outputs.size()) outputs.resize(slot + 1, make_pair("", 0)); outputs[slot] = make_pair(id, count); } // 获取输出槽 const pair<string, short>& getOutputSlot(size_t slot) const noexcept { static const pair<string, short> empty = make_pair("", 0); return (slot < outputs.size()) ? outputs[slot] : empty; } // 获取所有输出 const vector<pair<string, short>>& getAllOutputs() const noexcept { return outputs; } // 获取主输出 pair<string, short> getMainOutput() const noexcept { for (const auto& output : outputs) { if (!output.first.empty() && output.second > 0) { return output; } } return make_pair("", 0); } // 设置关联的合成方块 void setBlockID(const string& id) noexcept { blockID = id; } const string& getBlockID() const noexcept { return blockID; } // 设置每次合成产出数量 void setCraftCount(short count) noexcept { craftCount = max<short>(1, count); } short getCraftCount() const noexcept { return craftCount; } // 移除对特定物品的引用 void removeReferencesTo(const string& id) noexcept { // 清理输入网格 for (auto& row : grid) { for (auto& slot : row) { if (slot.first == id) { slot.first = ""; slot.second = 0; } } } // 清理输出槽 for (auto& output : outputs) { if (output.first == id) { output.first = ""; output.second = 0; } } } // 获取路径描述 string getPathDescription() const { ostringstream oss; if (!blockID.empty()) oss << "[" << blockID << "] "; const auto& mainOut = getMainOutput(); if (!mainOut.first.empty()) { oss << mainOut.first << " x" << mainOut.second; if (outputs.size() > 1) { oss << " (+" << (outputs.size() - 1) << " 其他输出)"; } } return oss.str(); } }; // ====================== 物品类 ====================== class Item { string id; short maxStack = DEFAULT_MAX_STACK; vector tables; public: explicit Item(string id, short maxStack = DEFAULT_MAX_STACK) : id(move(id)), maxStack(maxStack) { tables.reserve(MAX_RECIPES_PER_ITEM); } const string& getID() const noexcept { return id; } short getMaxStack() const noexcept { return maxStack; } // 添加合成表 void addTable(ItemTable table) { if (tables.size() < MAX_RECIPES_PER_ITEM) { tables.emplace_back(move(table)); } } // 获取所有合成表 const vector<ItemTable>& getTables() const noexcept { return tables; } // 移除对特定物品的引用 void removeReferencesTo(const string& id) noexcept { for (auto& table : tables) { table.removeReferencesTo(id); } } }; // ====================== 合成方块类 ====================== class CraftingBlock { string id; string name; int inputSlots; int outputSlots; vector recipes; // 关联的合成配方 public: CraftingBlock(string id, string name, int inSlots, int outSlots) : id(move(id)), name(move(name)), inputSlots(inSlots), outputSlots(outSlots) { recipes.reserve(MAX_RECIPES_PER_ITEM); } // 添加配方 void addRecipe(const ItemTable& recipe) { if (recipes.size() < MAX_RECIPES_PER_ITEM) { recipes.push_back(recipe); } } // 获取属性 const string& getID() const noexcept { return id; } const string& getName() const noexcept { return name; } int getInputSlots() const noexcept { return inputSlots; } int getOutputSlots() const noexcept { return outputSlots; } const vector<ItemTable>& getRecipes() const noexcept { return recipes; } }; // ====================== 物品集合类 ====================== class ItemCollection { unordered_map<string, Item> items; unordered_map<string, CraftingBlock> craftingBlocks; public: // 添加物品 bool add(Item item) { auto [it, inserted] = items.try_emplace(item.getID(), move(item)); return inserted; } // 获取物品 Item* getItem(const string& id) noexcept { auto it = items.find(id); return (it != items.end()) ? &it->second : nullptr; } const Item* getItem(const string& id) const noexcept { auto it = items.find(id); return (it != items.end()) ? &it->second : nullptr; } // 删除物品 bool removeItem(const string& id) { auto it = items.find(id); if (it == items.end()) return false; // 移除所有引用 for (auto& [_, item] : items) { item.removeReferencesTo(id); } // 从方块中移除引用 for (auto& [_, block] : craftingBlocks) { for (auto& recipe : const_cast<vector<ItemTable>&>(block.getRecipes())) { recipe.removeReferencesTo(id); } } items.erase(it); return true; } // 获取所有物品ID(排序后) vector<string> getSortedIDs() const { vector<string> ids; ids.reserve(items.size()); for (const auto& [id, _] : items) ids.push_back(id); sort(ids.begin(), ids.end()); return ids; } // 检查物品是否存在 bool contains(const string& id) const noexcept { return items.find(id) != items.end(); } // 物品数量 size_t size() const noexcept { return items.size(); } // 添加合成方块 bool addCraftingBlock(CraftingBlock block) { auto [it, inserted] = craftingBlocks.try_emplace(block.getID(), move(block)); return inserted; } // 获取合成方块 CraftingBlock* getCraftingBlock(const string& id) noexcept { auto it = craftingBlocks.find(id); return (it != craftingBlocks.end()) ? &it->second : nullptr; } // 获取所有合成方块 const unordered_map<string, CraftingBlock>& getAllCraftingBlocks() const noexcept { return craftingBlocks; } // 删除合成方块 bool removeCraftingBlock(const string& id) { auto it = craftingBlocks.find(id); if (it == craftingBlocks.end()) return false; // 移除所有关联的配方引用 for (auto& [_, item] : items) { auto& tables = const_cast<vector<ItemTable>&>(item.getTables()); for (auto itTable = tables.begin(); itTable != tables.end(); ) { if (itTable->getBlockID() == id) { itTable = tables.erase(itTable); } else { ++itTable; } } } craftingBlocks.erase(it); return true; } // 文件存储 void saveToFile(const fs::path& path) const { ofstream out(path, ios::binary); if (!out) throw runtime_error("无法打开文件进行写入: " + path.string()); // 保存物品 size_t itemCount = items.size(); out.write(reinterpret_cast<const char*>(&itemCount), sizeof(itemCount)); for (const auto& [id, item] : items) { // 保存ID size_t len = id.size(); out.write(reinterpret_cast<const char*>(&len), sizeof(len)); out.write(id.c_str(), len); // 保存属性 short maxStack = item.getMaxStack(); out.write(reinterpret_cast<const char*>(&maxStack), sizeof(maxStack)); // 保存合成表 size_t tableCount = item.getTables().size(); out.write(reinterpret_cast<const char*>(&tableCount), sizeof(tableCount)); for (const auto& table : item.getTables()) { // 保存输入网格 for (int x = 0; x < 3; x++) { for (int y = 0; y < 3; y++) { const auto& slot = table.getItem(x, y); len = slot.first.size(); out.write(reinterpret_cast<const char*>(&len), sizeof(len)); out.write(slot.first.c_str(), len); out.write(reinterpret_cast<const char*>(&slot.second), sizeof(slot.second)); } } // 保存输出槽 const auto& outputs = table.getAllOutputs(); size_t outputCount = outputs.size(); out.write(reinterpret_cast<const char*>(&outputCount), sizeof(outputCount)); for (const auto& output : outputs) { len = output.first.size(); out.write(reinterpret_cast<const char*>(&len), sizeof(len)); out.write(output.first.c_str(), len); out.write(reinterpret_cast<const char*>(&output.second), sizeof(output.second)); } // 保存关联方块ID const string& blockID = table.getBlockID(); len = blockID.size(); out.write(reinterpret_cast<const char*>(&len), sizeof(len)); out.write(blockID.c_str(), len); // 保存每次合成产出数量 short craftCount = table.getCraftCount(); out.write(reinterpret_cast<const char*>(&craftCount), sizeof(craftCount)); } } // 保存合成方块 size_t blockCount = craftingBlocks.size(); out.write(reinterpret_cast<const char*>(&blockCount), sizeof(blockCount)); for (const auto& [id, block] : craftingBlocks) { // 保存ID size_t len = id.size(); out.write(reinterpret_cast<const char*>(&len), sizeof(len)); out.write(id.c_str(), len); // 保存名称 len = block.getName().size(); out.write(reinterpret_cast<const char*>(&len), sizeof(len)); out.write(block.getName().c_str(), len); // 保存槽位 int slots = block.getInputSlots(); out.write(reinterpret_cast<const char*>(&slots), sizeof(slots)); slots = block.getOutputSlots(); out.write(reinterpret_cast<const char*>(&slots), sizeof(slots)); // 保存关联配方 size_t recipeCount = block.getRecipes().size(); out.write(reinterpret_cast<const char*>(&recipeCount), sizeof(recipeCount)); for (const auto& recipe : block.getRecipes()) { // 保存配方数据 for (int x = 0; x < 3; x++) { for (int y = 0; y < 3; y++) { const auto& slot = recipe.getItem(x, y); len = slot.first.size(); out.write(reinterpret_cast<const char*>(&len), sizeof(len)); out.write(slot.first.c_str(), len); out.write(reinterpret_cast<const char*>(&slot.second), sizeof(slot.second)); } } const auto& outputs = recipe.getAllOutputs(); size_t outputCount = outputs.size(); out.write(reinterpret_cast<const char*>(&outputCount), sizeof(outputCount)); for (const auto& output : outputs) { len = output.first.size(); out.write(reinterpret_cast<const char*>(&len), sizeof(len)); out.write(output.first.c_str(), len); out.write(reinterpret_cast<const char*>(&output.second), sizeof(output.second)); } const string& blockID = recipe.getBlockID(); len = blockID.size(); out.write(reinterpret_cast<const char*>(&len), sizeof(len)); out.write(blockID.c_str(), len); short craftCount = recipe.getCraftCount(); out.write(reinterpret_cast<const char*>(&craftCount), sizeof(craftCount)); } } } // 文件加载 void loadFromFile(const fs::path& path) { ifstream in(path, ios::binary); if (!in) throw runtime_error("无法打开文件进行读取: " + path.string()); items.clear(); craftingBlocks.clear(); // 加载物品 size_t itemCount; in.read(reinterpret_cast<char*>(&itemCount), sizeof(itemCount)); for (size_t i = 0; i < itemCount; i++) { // 加载ID size_t len; in.read(reinterpret_cast<char*>(&len), sizeof(len)); string id(len, ' '); in.read(id.data(), len); // 加载属性 short maxStack; in.read(reinterpret_cast<char*>(&maxStack), sizeof(maxStack)); Item item(id, maxStack); // 加载合成表 size_t tableCount; in.read(reinterpret_cast<char*>(&tableCount), sizeof(tableCount)); for (size_t j = 0; j < tableCount; j++) { ItemTable table; // 加载输入网格 for (int x = 0; x < 3; x++) { for (int y = 0; y < 3; y++) { in.read(reinterpret_cast<char*>(&len), sizeof(len)); string id(len, ' '); in.read(id.data(), len); short cnt; in.read(reinterpret_cast<char*>(&cnt), sizeof(cnt)); table.setItem(x, y, id, cnt); } } // 加载输出槽 size_t outputCount; in.read(reinterpret_cast<char*>(&outputCount), sizeof(outputCount)); for (size_t k = 0; k < outputCount; k++) { in.read(reinterpret_cast<char*>(&len), sizeof(len)); string id(len, ' '); in.read(id.data(), len); short cnt; in.read(reinterpret_cast<char*>(&cnt), sizeof(cnt)); table.setOutputSlot(k, id, cnt); } // 加载关联方块ID in.read(reinterpret_cast<char*>(&len), sizeof(len)); string blockID(len, ’ '); in.read(blockID.data(), len); table.setBlockID(blockID); // 加载每次合成产出数量 short craftCount; in.read(reinterpret_cast<char*>(&craftCount), sizeof(craftCount)); table.setCraftCount(craftCount); item.addTable(move(table)); } items.emplace(id, move(item)); } // 加载合成方块 size_t blockCount; in.read(reinterpret_cast<char*>(&blockCount), sizeof(blockCount)); for (size_t i = 0; i < blockCount; i++) { // 加载ID size_t len; in.read(reinterpret_cast<char*>(&len), sizeof(len)); string id(len, ’ '); in.read(id.data(), len); // 加载名称 in.read(reinterpret_cast<char*>(&len), sizeof(len)); string name(len, ' '); in.read(name.data(), len); // 加载槽位 int inSlots, outSlots; in.read(reinterpret_cast<char*>(&inSlots), sizeof(inSlots)); in.read(reinterpret_cast<char*>(&outSlots), sizeof(outSlots)); CraftingBlock block(id, name, inSlots, outSlots); // 加载关联配方 size_t recipeCount; in.read(reinterpret_cast<char*>(&recipeCount), sizeof(recipeCount)); for (size_t j = 0; j < recipeCount; j++) { ItemTable table; // 加载输入网格 for (int x = 0; x < 3; x++) { for (int y = 0; y < 3; y++) { in.read(reinterpret_cast<char*>(&len), sizeof(len)); string id(len, ' '); in.read(id.data(), len); short cnt; in.read(reinterpret_cast<char*>(&cnt), sizeof(cnt)); table.setItem(x, y, id, cnt); } } // 加载输出槽 size_t outputCount; in.read(reinterpret_cast<char*>(&outputCount), sizeof(outputCount)); for (size_t k = 0; k < outputCount; k++) { in.read(reinterpret_cast<char*>(&len), sizeof(len)); string id(len, ' '); in.read(id.data(), len); short cnt; in.read(reinterpret_cast<char*>(&cnt), sizeof(cnt)); table.setOutputSlot(k, id, cnt); } // 加载关联方块ID in.read(reinterpret_cast<char*>(&len), sizeof(len)); string blockID(len, ' '); in.read(blockID.data(), len); table.setBlockID(blockID); // 加载每次合成产出数量 short craftCount; in.read(reinterpret_cast<char*>(&craftCount), sizeof(craftCount)); table.setCraftCount(craftCount); block.addRecipe(table); } craftingBlocks.emplace(id, move(block)); } } }; // ====================== 材料计算引擎 ====================== class MaterialCalculator { const ItemCollection& itemDB; mutable unordered_map<string, int> depthCache; public: explicit MaterialCalculator(const ItemCollection& db) : itemDB(db) {} // 计算材料需求 MaterialMap calculateMaterials(const string& id, long long count, ItemTable::PathMode pathMode = ItemTable::SHORTEST, ItemTable::BatchMode batchMode = ItemTable::EXACT_BATCH) { MaterialMap materials; set<string> visited; CalcMaterialsRecursive(id, count, materials, visited, pathMode, batchMode); return materials; } private: void CalcMaterialsRecursive(const string& id, long long count, MaterialMap& materials, set& visited, ItemTable::PathMode pathMode, ItemTable::BatchMode batchMode) { // 检查循环依赖 if (visited.find(id) != visited.end()) return; visited.insert(id); // 获取物品 const Item* item = itemDB.getItem(id); if (!item || item->getTables().empty()) { materials[id] += count; // 基础材料 return; } // 选择最佳合成路径 const ItemTable* bestTable = selectBestTable(id, pathMode); if (!bestTable) return; // 计算合成批次 long long craftCnt = bestTable->getCraftCount(); long long batches = (batchMode == ItemTable::EXACT_BATCH) ? (count + craftCnt - 1) / craftCnt : static_cast<long long>(ceil(static_cast<double>(count) / craftCnt)); // 处理输入材料 for (int x = 0; x < 3; x++) { for (int y = 0; y < 3; y++) { const auto& slot = bestTable->getItem(x, y); if (!slot.first.empty() && slot.second > 0) { long long totalNeeded = batches * slot.second; CalcMaterialsRecursive(slot.first, totalNeeded, materials, visited, pathMode, batchMode); } } } } const ItemTable* selectBestTable(const string& id, ItemTable::PathMode mode) { const Item* item = itemDB.getItem(id); if (!item || item->getTables().empty()) return nullptr; const ItemTable* bestTable = &item->getTables()[0]; if (mode == ItemTable::SHORTEST || mode == ItemTable::LONGEST) { int bestDepth = (mode == ItemTable::SHORTEST) ? INT_MAX : 0; for (const auto& table : item->getTables()) { int depth = getCachedPathDepth(table); if ((mode == ItemTable::SHORTEST && depth < bestDepth) || (mode == ItemTable::LONGEST && depth > bestDepth)) { bestDepth = depth; bestTable = &table; } } } return bestTable; } int getCachedPathDepth(const ItemTable& table) const { int maxDepth = 0; for (int x = 0; x < 3; x++) { for (int y = 0; y < 3; y++) { const auto& slot = table.getItem(x, y); if (!slot.first.empty() && slot.second > 0) { // 使用缓存查询 auto it = depthCache.find(slot.first); if (it != depthCache.end()) { maxDepth = max(maxDepth, it->second); } else { int depth = calculateItemDepth(slot.first); depthCache[slot.first] = depth; maxDepth = max(maxDepth, depth); } } } } return maxDepth; } int calculateItemDepth(const string& id) const { // 获取物品 const Item* item = itemDB.getItem(id); if (!item || item->getTables().empty()) { return 0; // 基础材料 } // 计算最大深度 int maxDepth = 0; for (const auto& table : item->getTables()) { for (int x = 0; x < 3; x++) { for (int y = 0; y < 3; y++) { const auto& slot = table.getItem(x, y); if (!slot.first.empty() && slot.second > 0) { int depth = calculateItemDepth(slot.first) + 1; maxDepth = max(maxDepth, depth); } } } } return maxDepth; } }; // ====================== 逐步合成状态 ====================== struct CraftingStep { string itemID; long long required; uint8_t recipeIndex; bool completed; }; class StepByStepCrafting { const ItemCollection& db; MaterialCalculator& calc; string targetID; long long targetCount; stack stepStack; unordered_set synthesizedItems; MaterialMap totalMaterials; public: StepByStepCrafting(const ItemCollection& db, MaterialCalculator& calc, const string& id, long long count) : db(db), calc(calc), targetID(id), targetCount(count) {} // 开始逐步合成 void start() { // 初始化第一个步骤 stepStack.push({targetID, targetCount, 0, false}); synthesizedItems.clear(); totalMaterials.clear(); // 开始交互 interactiveCrafting(); } private: // 交互式合成过程 void interactiveCrafting() { while (!stepStack.empty()) { CraftingStep& current = stepStack.top(); // 显示当前步骤信息 clear(); displayCurrentStep(current); // 获取用户选择 int choice = getUserChoice(); // 处理用户选择 switch (choice) { case 0: handleUndo(); break; case 1: processCurrentStep(current); break; case 2: stepStack.pop(); break; // 跳过 case 3: displayMaterialSummary(); pause(); break; case 4: return; // 退出 default: cout << "无效选择!" << endl; wait(1); } } cout << "恭喜! 所有材料已准备完成!" << endl; pause(); } void handleUndo() { if (stepStack.size() > 1) { CraftingStep current = stepStack.top(); stepStack.pop(); synthesizedItems.erase(current.itemID); if (db.getItem(current.itemID) == nullptr || db.getItem(current.itemID)->getTables().empty()) { totalMaterials[current.itemID] -= current.required; } } else { cout << "已在第一步,无法返回!" << endl; wait(1); } } // 显示当前步骤信息 void displayCurrentStep(const CraftingStep& step) const { cout << "===== 当前合成步骤 =====" << endl; cout << "物品: " << step.itemID << " x " << step.required << endl; const Item* item = db.getItem(step.itemID); if (!item || item->getTables().empty()) { cout << "\n这是基础材料,无法合成!" << endl; return; } // 显示当前配方 const auto& table = item->getTables()[step.recipeIndex]; cout << "使用配方: " << table.getPathDescription() << endl; // 显示当前材料 cout << "\n所需材料:" << endl; for (int x = 0; x < 3; x++) { for (int y = 0; y < 3; y++) { const auto& slot = table.getItem(x, y); if (!slot.first.empty() && slot.second > 0) { long long totalNeeded = step.required * slot.second; cout << " - " << slot.first << " x " << totalNeeded << endl; } } } // 显示当前状态 cout << "\n当前状态: " << (step.completed ? "已完成" : "待处理") << "\n========================" << endl; } // 获取用户选择 int getUserChoice() const { cout << "\n选项:" << endl; cout << "0. 返回上一步" << endl; cout << "1. 合成此物品" << endl; cout << "2. 跳过此物品" << endl; cout << "3. 查看材料汇总" << endl; cout << "4. 退出逐步合成" << endl; cout << "选择: "; int choice; cin >> choice; return choice; } // 处理当前步骤 void processCurrentStep(CraftingStep& step) { const Item* item = db.getItem(step.itemID); if (!item || item->getTables().empty()) { // 基础材料,直接完成 totalMaterials[step.itemID] += step.required; stepStack.pop(); return; } const auto& table = item->getTables()[step.recipeIndex]; short craftCount = table.getCraftCount(); long long batches = (step.required + craftCount - 1) / craftCount; // 整数除法 // 添加子步骤 for (int x = 0; x < 3; x++) { for (int y = 0; y < 3; y++) { const auto& slot = table.getItem(x, y); // 跳过空槽位和已合成物品 if (slot.first.empty() || slot.second == 0 || synthesizedItems.find(slot.first) != synthesizedItems.end()) continue; // 创建新步骤 stepStack.push({slot.first, batches * slot.second, 0, false}); } } // 标记当前步骤为已完成 step.completed = true; synthesizedItems.insert(step.itemID); } // 显示材料汇总 void displayMaterialSummary() const { clear(); cout << "===== 材料汇总 =====" << endl; cout << "目标: " << targetID << " x " << targetCount << endl; cout << "已准备材料:" << endl; for (const auto& [id, cnt] : totalMaterials) { cout << " - " << id << ": " << cnt << endl; } cout << "=====================" << endl; } }; // ====================== 用户界面工具 ====================== void clear() { #ifdef _WIN32 system(“cls”); #else system(“clear”); #endif } void pause() { cout << “\n按回车键继续…”; cin.ignore(numeric_limits::max(), ‘\n’); cin.get(); } void wait(int seconds) { this_thread::sleep_for(chrono::seconds(seconds)); } // ====================== 全局数据 ====================== ItemCollection itemDB; MaterialCalculator calculator(itemDB); fs::path savePath = fs::current_path() / “items.dat”; // ====================== 文件操作 ====================== void SaveItems(bool showMessage = true) { try { if (!fs::exists(savePath.parent_path())) { fs::create_directories(savePath.parent_path()); } itemDB.saveToFile(savePath); if (showMessage) cout << “物品数据已保存!” << endl; } catch (const exception& e) { cerr << "保存错误: " << e.what() << endl; } } void LoadItems() { try { if (fs::exists(savePath)) { itemDB.loadFromFile(savePath); cout << “物品数据已加载 (” << itemDB.size() << " 物品)" << endl; } else { cout << “未找到保存文件,创建新数据库” << endl; } } catch (const exception& e) { cerr << "加载错误: " << e.what() << endl; } } // ====================== 用户界面功能 ====================== void CreateItem() { clear(); string id; short maxStack; cout << "物品ID: "; cin >> id; if (itemDB.contains(id)) { cout << "物品已存在!" << endl; pause(); return; } cout << "最大堆叠数 (默认64): "; cin >> maxStack; if (maxStack <= 0) maxStack = 64; itemDB.add(Item(id, maxStack)); SaveItems(false); cout << "物品创建成功!" << endl; wait(1); } void DeleteItem() { clear(); auto ids = itemDB.getSortedIDs(); if (ids.empty()) { cout << "没有可删除的物品!" << endl; pause(); return; } cout << "可用物品:\n"; for (const auto& id : ids) { cout << " - " << id << "\n"; } string target; cout << "\n输入要删除的物品ID: "; cin >> target; if (!itemDB.contains(target)) { cout << "物品不存在!" << endl; pause(); return; } cout << "确认删除? (Y/N): "; char confirm; cin >> confirm; if (toupper(confirm) == 'Y') { if (itemDB.removeItem(target)) { SaveItems(false); cout << "物品已删除!" << endl; } else { cout << "删除失败!" << endl; } } else { cout << "操作取消" << endl; } wait(1); } void AddRecipeToItem() { clear(); auto ids = itemDB.getSortedIDs(); if (ids.empty()) { cout << "请先创建物品!" << endl; pause(); return; } cout << "可用物品:\n"; for (const auto& id : ids) { cout << " - " << id << "\n"; } string target; cout << "\n输入要添加配方的物品ID: "; cin >> target; Item* item = itemDB.getItem(target); if (!item) { cout << "物品不存在!" << endl; pause(); return; } // 选择合成方块 cout << "选择合成方块 (输入ID,留空使用默认): "; string blockID; cin.ignore(); getline(cin, blockID); CraftingBlock* block = nullptr; if (!blockID.empty()) { block = itemDB.getCraftingBlock(blockID); if (!block) { cout << "方块不存在,使用默认合成" << endl; wait(1); } } // 创建新合成表 ItemTable newTable; if (block) { newTable.setBlockID(block->getID()); cout << "使用方块: " << block->getName() << endl; } // 设置输入网格(支持"0"表示空槽位) cout << "\n输入3x3合成网格 (输入'0'表示空槽,格式: 物品ID 数量)\n"; for (int x = 0; x < 3; x++) { for (int y = 0; y < 3; y++) { string id; short cnt; cout << "位置 [" << x << "," << y << "]: "; cin >> id; // 处理"0"输入 if (id == "0") { newTable.setItem(x, y, "", 0); cin.ignore(numeric_limits<streamsize>::max(), '\n'); continue; } // 处理正常输入 cin >> cnt; if (!itemDB.contains(id)) { cout << "物品不存在,跳过此位置!" << endl; newTable.setItem(x, y, "", 0); continue; } newTable.setItem(x, y, id, cnt); } } // 设置每次合成产出数量 short craftCount; cout << "每次合成产出数量: "; cin >> craftCount; newTable.setCraftCount(craftCount > 0 ? craftCount : 1); // 设置输出槽数量 int outputSlots = block ? block->getOutputSlots() : 1; cout << "\n设置输出槽 (共 " << outputSlots << " 个槽位)\n"; for (int i = 0; i < outputSlots; i++) { string outID; short outCnt; cout << "输出槽 #" << (i+1) << " (物品ID 数量,留空跳过): "; cin >> outID; if (outID.empty() || outID == "0") { newTable.setOutputSlot(i, "", 0); cin.ignore(numeric_limits<streamsize>::max(), '\n'); continue; } cin >> outCnt; if (!itemDB.contains(outID)) { cout << "物品不存在,跳过此输出槽!" << endl; newTable.setOutputSlot(i, "", 0); continue; } newTable.setOutputSlot(i, outID, outCnt); } // 添加到物品或方块 if (block) { block->addRecipe(newTable); } else { item->addTable(newTable); } SaveItems(false); cout << "合成表添加成功!" << endl; wait(1); } void ViewRecipes() { clear(); auto ids = itemDB.getSortedIDs(); if (ids.empty()) { cout << "没有可查看的物品!" << endl; pause(); return; } cout << "可用物品:\n"; for (size_t i = 0; i < ids.size(); i++) { cout << setw(2) << i+1 << ". " << ids[i] << "\n"; } int choice; cout << "\n选择物品 (0返回): "; cin >> choice; if (choice <= 0 || choice > static_cast<int>(ids.size())) return; string target = ids[choice-1]; Item* item = itemDB.getItem(target); if (!item) return; clear(); cout << "物品: " << target << "\n"; cout << "最大堆叠: " << item->getMaxStack() << "\n\n"; if (item->getTables().empty()) { cout << "此物品没有合成配方!" << endl; pause(); return; } cout << "合成配方:\n"; for (size_t i = 0; i < item->getTables().size(); i++) { const auto& table = item->getTables()[i]; cout << "配方 #" << i+1 << ": " << table.getPathDescription() << "\n"; } cout << "\n输入配方编号查看详情 (0返回): "; cin >> choice; if (choice <= 0 || choice > static_cast<int>(item->getTables().size())) return; const auto& table = item->getTables()[choice-1]; clear(); cout << "配方详情: " << table.getPathDescription() << "\n"; // 显示输入网格 cout << "\n输入网格:\n"; for (int x = 0; x < 3; x++) { for (int y = 0; y < 3; y++) { const auto& slot = table.getItem(x, y); cout << "[" << (slot.first.empty() ? " " : slot.first.substr(0,2)) << (slot.second > 0 ? to_string(slot.second) : " ") << "] "; } cout << "\n"; } // 显示输出槽 cout << "\n输出槽:\n"; for (size_t i = 0; i < table.getAllOutputs().size(); i++) { const auto& slot = table.getOutputSlot(i); if (!slot.first.empty() && slot.second > 0) { cout << "槽位 #" << i+1 << ": " << slot.first << " x" << slot.second << "\n"; } } pause(); } void AddCraftingBlock() { clear(); string id, name; int inSlots, outSlots; cout << "方块ID: "; cin >> id; cout << "方块名称: "; cin.ignore(); getline(cin, name); cout << "输入槽数量: "; cin >> inSlots; cout << "输出槽数量: "; cin >> outSlots; if (inSlots <= 0 || outSlots <= 0) { cout << "槽位数量必须大于0!" << endl; pause(); return; } if (itemDB.getCraftingBlock(id)) { cout << "方块ID已存在!" << endl; pause(); return; } itemDB.addCraftingBlock(CraftingBlock(id, name, inSlots, outSlots)); SaveItems(false); cout << "合成方块添加成功!" << endl; wait(1); } void DeleteCraftingBlock() { clear(); const auto& blocks = itemDB.getAllCraftingBlocks(); if (blocks.empty()) { cout << "没有可用的合成方块!" << endl; pause(); return; } cout << "可用合成方块:\n"; for (const auto& [id, block] : blocks) { cout << " - " << id << " (" << block.getName() << ")\n"; } string target; cout << "\n输入要删除的方块ID: "; cin >> target; if (!itemDB.getCraftingBlock(target)) { cout << "方块不存在!" << endl; pause(); return; } cout << "确认删除? (Y/N): "; char confirm; cin >> confirm; if (toupper(confirm) == 'Y') { if (itemDB.removeCraftingBlock(target)) { SaveItems(false); cout << "方块已删除!" << endl; } else { cout << "删除失败!" << endl; } } else { cout << "操作取消" << endl; } wait(1); } void CalculateMaterials() { clear(); auto ids = itemDB.getSortedIDs(); if (ids.empty()) { cout << "没有可计算的物品!" << endl; pause(); return; } cout << "可用物品:\n"; for (size_t i = 0; i < ids.size(); i++) { cout << setw(2) << i+1 << ". " << ids[i] << "\n"; } int choice; cout << "\n选择物品 (0返回): "; cin >> choice; if (choice <= 0 || choice > static_cast<int>(ids.size())) return; string target = ids[choice-1]; long long count; cout << "需要数量: "; cin >> count; // 选择计算模式 cout << "\n选择计算模式:\n" << "1. 最短路径 (默认)\n" << "2. 最长路径\n" << "3. 精确匹配\n" << "选择: "; int modeChoice; cin >> modeChoice; ItemTable::PathMode pathMode = ItemTable::SHORTEST; ItemTable::BatchMode batchMode = ItemTable::EXACT_BATCH; if (modeChoice == 2) pathMode = ItemTable::LONGEST; else if (modeChoice == 3) pathMode = ItemTable::EXACT; // 计算材料 MaterialMap materials = calculator.calculateMaterials(target, count, pathMode, batchMode); // 显示结果 clear(); cout << "合成 " << count << " 个 " << target << " 需要:\n"; cout << "================================\n"; long long totalItems = 0; for (const auto& [id, cnt] : materials) { cout << setw(15) << left << id << ": " << cnt << "\n"; totalItems += cnt; } cout << "================================\n"; cout << "总计材料: " << totalItems << " 个\n"; pause(); } void StepByStepCraftingUI() { clear(); auto ids = itemDB.getSortedIDs(); if (ids.empty()) { cout << "没有可合成的物品!" << endl; pause(); return; } cout << "可用物品:\n"; for (size_t i = 0; i < ids.size(); i++) { cout << setw(2) << i+1 << ". " << ids[i] << "\n"; } int choice; cout << "\n选择物品 (0返回): "; cin >> choice; if (choice <= 0 || choice > static_cast<int>(ids.size())) return; string target = ids[choice-1]; long long count; cout << "需要数量: "; cin >> count; // 启动逐步合成 StepByStepCrafting stepper(itemDB, calculator, target, count); stepper.start(); } void SetSavePath() { clear(); cout << "当前保存路径: " << savePath << “\n\n”; cout << "输入新路径: "; string newPath; cin.ignore(); getline(cin, newPath); if (!newPath.empty()) { savePath = fs::path(newPath); cout << "路径已更新!" << endl; wait(1); } } // ====================== 主程序 ====================== int main() { LoadItems(); while (true) { clear(); cout << "===== 合成系统 =====" << endl; cout << "1. 创建物品" << endl; cout << "2. 删除物品" << endl; cout << "3. 添加合成表" << endl; cout << "4. 查看物品配方" << endl; cout << "5. 材料计算" << endl; cout << "6. 逐步合成" << endl; cout << "7. 添加合成方块" << endl; cout << "8. 删除合成方块" << endl; cout << "9. 设置保存路径" << endl; cout << "10. 保存数据" << endl; cout << "11. 退出" << endl; cout << "=====================" << endl; cout << "物品数: " << itemDB.size() << " | 方块数: " << itemDB.getAllCraftingBlocks().size() << " | 路径: " << savePath.filename() << endl; cout << "选项: "; int choice; cin >> choice; switch (choice) { case 1: CreateItem(); break; case 2: DeleteItem(); break; case 3: AddRecipeToItem(); break; case 4: ViewRecipes(); break; case 5: CalculateMaterials(); break; case 6: StepByStepCraftingUI(); break; case 7: AddCraftingBlock(); break; case 8: DeleteCraftingBlock(); break; case 9: SetSavePath(); break; case 10: SaveItems(); pause(); break; case 11: SaveItems(false); cout << "再见!" << endl; return 0; default: cout << "无效选项!" << endl; wait(1); } } }
最新发布
08-07
请你解决使用任意格数的合成方块输入合成表时依然是9格输入的问题,并且在设置了输出槽后,不应该有输出数量询问了(直接在输出槽里回答),并且,统计材料和逐步合成都是看输入框里的物品的,合成出的是输出框里的物品,此外,我们发现程序在启动时并不能找到之前的保存位置,请用一个文件来设置保存位置,另外,缺少头文件<unordered_set>。 代码: #include <iostream> #include <fstream> #include <vector> #include <map> #include <set> #include <string> #include <algorithm> #include <cctype> #include <filesystem> #include <iomanip> #include <limits> #include <sstream> #include <cmath> #include <unordered_map> #include <unordered_set> #include <functional> #include <memory> #include <variant> #include <queue> #include <stack> #include <array> #include <thread> #include <climits> #include <cctype> #include <type_traits> #include <string_view> using namespace std; namespace fs = filesystem; using namespace std::literals; // ===================== 函数预定义 ===================== void clear(), wait(int),pause(); // ====================== 类型定义 ====================== using CraftGrid = array<array<pair<string, short>, 3>, 3>; using MaterialMap = unordered_map<string, long long>; // ====================== 常量定义 ====================== constexpr short DEFAULT_MAX_STACK = 64; constexpr short MAX_RECIPES_PER_ITEM = 10; constexpr short MAX_CRAFTING_BLOCKS = 20; // ====================== 合成表类 ====================== class ItemTable { public: enum PathMode : uint8_t { SHORTEST, LONGEST, EXACT }; enum BatchMode : uint8_t { EXACT_BATCH, MERGE_BATCH }; private: CraftGrid grid; vector<pair<string, short>> outputs; // 多输出槽支持 string blockID; // 关联的合成方块ID short craftCount = 1; // 每次合成产出数量 public: ItemTable() = default; // 设置网格项 void setItem(int x, int y, const string& id, short count) noexcept { if (x >= 0 && x < 3 && y >= 0 && y < 3) { grid[x][y] = make_pair(id, count); } } // 获取网格项 const pair<string, short>& getItem(int x, int y) const noexcept { static const pair<string, short> empty = make_pair("", 0); return (x >= 0 && x < 3 && y >= 0 && y < 3) ? grid[x][y] : empty; } // 设置输出槽 void setOutputSlot(size_t slot, const string& id, short count) { if (slot >= outputs.size()) outputs.resize(slot + 1, make_pair("", 0)); outputs[slot] = make_pair(id, count); } // 获取输出槽 const pair<string, short>& getOutputSlot(size_t slot) const noexcept { static const pair<string, short> empty = make_pair("", 0); return (slot < outputs.size()) ? outputs[slot] : empty; } // 获取所有输出 const vector<pair<string, short>>& getAllOutputs() const noexcept { return outputs; } // 获取主输出 pair<string, short> getMainOutput() const noexcept { for (const auto& output : outputs) { if (!output.first.empty() && output.second > 0) { return output; } } return make_pair("", 0); } // 设置关联的合成方块 void setBlockID(const string& id) noexcept { blockID = id; } const string& getBlockID() const noexcept { return blockID; } // 设置每次合成产出数量 void setCraftCount(short count) noexcept { craftCount = max<short>(1, count); } short getCraftCount() const noexcept { return craftCount; } // 移除对特定物品的引用 void removeReferencesTo(const string& id) noexcept { // 清理输入网格 for (auto& row : grid) { for (auto& slot : row) { if (slot.first == id) { slot.first = ""; slot.second = 0; } } } // 清理输出槽 for (auto& output : outputs) { if (output.first == id) { output.first = ""; output.second = 0; } } } // 获取路径描述 string getPathDescription() const { ostringstream oss; if (!blockID.empty()) oss << "[" << blockID << "] "; const auto& mainOut = getMainOutput(); if (!mainOut.first.empty()) { oss << mainOut.first << " x" << mainOut.second; if (outputs.size() > 1) { oss << " (+" << (outputs.size() - 1) << " 其他输出)"; } } return oss.str(); } }; // ====================== 物品类 ====================== class Item { string id; short maxStack = DEFAULT_MAX_STACK; vector<ItemTable> tables; public: explicit Item(string id, short maxStack = DEFAULT_MAX_STACK) : id(move(id)), maxStack(maxStack) { tables.reserve(MAX_RECIPES_PER_ITEM); } const string& getID() const noexcept { return id; } short getMaxStack() const noexcept { return maxStack; } // 添加合成表 void addTable(ItemTable table) { if (tables.size() < MAX_RECIPES_PER_ITEM) { tables.emplace_back(move(table)); } } // 获取所有合成表 const vector<ItemTable>& getTables() const noexcept { return tables; } // 移除对特定物品的引用 void removeReferencesTo(const string& id) noexcept { for (auto& table : tables) { table.removeReferencesTo(id); } } }; // ====================== 合成方块类 ====================== class CraftingBlock { string id; string name; int inputSlots; int outputSlots; vector<ItemTable> recipes; // 关联的合成配方 public: CraftingBlock(string id, string name, int inSlots, int outSlots) : id(move(id)), name(move(name)), inputSlots(inSlots), outputSlots(outSlots) { recipes.reserve(MAX_RECIPES_PER_ITEM); } // 添加配方 void addRecipe(const ItemTable& recipe) { if (recipes.size() < MAX_RECIPES_PER_ITEM) { recipes.push_back(recipe); } } // 获取属性 const string& getID() const noexcept { return id; } const string& getName() const noexcept { return name; } int getInputSlots() const noexcept { return inputSlots; } int getOutputSlots() const noexcept { return outputSlots; } const vector<ItemTable>& getRecipes() const noexcept { return recipes; } }; // ====================== 物品集合类 ====================== class ItemCollection { unordered_map<string, Item> items; unordered_map<string, CraftingBlock> craftingBlocks; public: // 添加物品 bool add(Item item) { auto [it, inserted] = items.try_emplace(item.getID(), move(item)); return inserted; } // 获取物品 Item* getItem(const string& id) noexcept { auto it = items.find(id); return (it != items.end()) ? &it->second : nullptr; } const Item* getItem(const string& id) const noexcept { auto it = items.find(id); return (it != items.end()) ? &it->second : nullptr; } // 删除物品 bool removeItem(const string& id) { auto it = items.find(id); if (it == items.end()) return false; // 移除所有引用 for (auto& [_, item] : items) { item.removeReferencesTo(id); } // 从方块中移除引用 for (auto& [_, block] : craftingBlocks) { for (auto& recipe : const_cast<vector<ItemTable>&>(block.getRecipes())) { recipe.removeReferencesTo(id); } } items.erase(it); return true; } // 获取所有物品ID(排序后) vector<string> getSortedIDs() const { vector<string> ids; ids.reserve(items.size()); for (const auto& [id, _] : items) ids.push_back(id); sort(ids.begin(), ids.end()); return ids; } // 检查物品是否存在 bool contains(const string& id) const noexcept { return items.find(id) != items.end(); } // 物品数量 size_t size() const noexcept { return items.size(); } // 添加合成方块 bool addCraftingBlock(CraftingBlock block) { auto [it, inserted] = craftingBlocks.try_emplace(block.getID(), move(block)); return inserted; } // 获取合成方块 CraftingBlock* getCraftingBlock(const string& id) noexcept { auto it = craftingBlocks.find(id); return (it != craftingBlocks.end()) ? &it->second : nullptr; } // 获取所有合成方块 const unordered_map<string, CraftingBlock>& getAllCraftingBlocks() const noexcept { return craftingBlocks; } // 删除合成方块 bool removeCraftingBlock(const string& id) { auto it = craftingBlocks.find(id); if (it == craftingBlocks.end()) return false; // 移除所有关联的配方引用 for (auto& [_, item] : items) { auto& tables = const_cast<vector<ItemTable>&>(item.getTables()); for (auto itTable = tables.begin(); itTable != tables.end(); ) { if (itTable->getBlockID() == id) { itTable = tables.erase(itTable); } else { ++itTable; } } } craftingBlocks.erase(it); return true; } // 文件存储 void saveToFile(const fs::path& path) const { ofstream out(path, ios::binary); if (!out) throw runtime_error("无法打开文件进行写入: " + path.string()); // 保存物品 size_t itemCount = items.size(); out.write(reinterpret_cast<const char*>(&itemCount), sizeof(itemCount)); for (const auto& [id, item] : items) { // 保存ID size_t len = id.size(); out.write(reinterpret_cast<const char*>(&len), sizeof(len)); out.write(id.c_str(), len); // 保存属性 short maxStack = item.getMaxStack(); out.write(reinterpret_cast<const char*>(&maxStack), sizeof(maxStack)); // 保存合成表 size_t tableCount = item.getTables().size(); out.write(reinterpret_cast<const char*>(&tableCount), sizeof(tableCount)); for (const auto& table : item.getTables()) { // 保存输入网格 for (int x = 0; x < 3; x++) { for (int y = 0; y < 3; y++) { const auto& slot = table.getItem(x, y); len = slot.first.size(); out.write(reinterpret_cast<const char*>(&len), sizeof(len)); out.write(slot.first.c_str(), len); out.write(reinterpret_cast<const char*>(&slot.second), sizeof(slot.second)); } } // 保存输出槽 const auto& outputs = table.getAllOutputs(); size_t outputCount = outputs.size(); out.write(reinterpret_cast<const char*>(&outputCount), sizeof(outputCount)); for (const auto& output : outputs) { len = output.first.size(); out.write(reinterpret_cast<const char*>(&len), sizeof(len)); out.write(output.first.c_str(), len); out.write(reinterpret_cast<const char*>(&output.second), sizeof(output.second)); } // 保存关联方块ID const string& blockID = table.getBlockID(); len = blockID.size(); out.write(reinterpret_cast<const char*>(&len), sizeof(len)); out.write(blockID.c_str(), len); // 保存每次合成产出数量 short craftCount = table.getCraftCount(); out.write(reinterpret_cast<const char*>(&craftCount), sizeof(craftCount)); } } // 保存合成方块 size_t blockCount = craftingBlocks.size(); out.write(reinterpret_cast<const char*>(&blockCount), sizeof(blockCount)); for (const auto& [id, block] : craftingBlocks) { // 保存ID size_t len = id.size(); out.write(reinterpret_cast<const char*>(&len), sizeof(len)); out.write(id.c_str(), len); // 保存名称 len = block.getName().size(); out.write(reinterpret_cast<const char*>(&len), sizeof(len)); out.write(block.getName().c_str(), len); // 保存槽位 int slots = block.getInputSlots(); out.write(reinterpret_cast<const char*>(&slots), sizeof(slots)); slots = block.getOutputSlots(); out.write(reinterpret_cast<const char*>(&slots), sizeof(slots)); // 保存关联配方 size_t recipeCount = block.getRecipes().size(); out.write(reinterpret_cast<const char*>(&recipeCount), sizeof(recipeCount)); for (const auto& recipe : block.getRecipes()) { // 保存配方数据 for (int x = 0; x < 3; x++) { for (int y = 0; y < 3; y++) { const auto& slot = recipe.getItem(x, y); len = slot.first.size(); out.write(reinterpret_cast<const char*>(&len), sizeof(len)); out.write(slot.first.c_str(), len); out.write(reinterpret_cast<const char*>(&slot.second), sizeof(slot.second)); } } const auto& outputs = recipe.getAllOutputs(); size_t outputCount = outputs.size(); out.write(reinterpret_cast<const char*>(&outputCount), sizeof(outputCount)); for (const auto& output : outputs) { len = output.first.size(); out.write(reinterpret_cast<const char*>(&len), sizeof(len)); out.write(output.first.c_str(), len); out.write(reinterpret_cast<const char*>(&output.second), sizeof(output.second)); } const string& blockID = recipe.getBlockID(); len = blockID.size(); out.write(reinterpret_cast<const char*>(&len), sizeof(len)); out.write(blockID.c_str(), len); short craftCount = recipe.getCraftCount(); out.write(reinterpret_cast<const char*>(&craftCount), sizeof(craftCount)); } } } // 文件加载 void loadFromFile(const fs::path& path) { ifstream in(path, ios::binary); if (!in) throw runtime_error("无法打开文件进行读取: " + path.string()); items.clear(); craftingBlocks.clear(); // 加载物品 size_t itemCount; in.read(reinterpret_cast<char*>(&itemCount), sizeof(itemCount)); for (size_t i = 0; i < itemCount; i++) { // 加载ID size_t len; in.read(reinterpret_cast<char*>(&len), sizeof(len)); string id(len, ' '); in.read(id.data(), len); // 加载属性 short maxStack; in.read(reinterpret_cast<char*>(&maxStack), sizeof(maxStack)); Item item(id, maxStack); // 加载合成表 size_t tableCount; in.read(reinterpret_cast<char*>(&tableCount), sizeof(tableCount)); for (size_t j = 0; j < tableCount; j++) { ItemTable table; // 加载输入网格 for (int x = 0; x < 3; x++) { for (int y = 0; y < 3; y++) { in.read(reinterpret_cast<char*>(&len), sizeof(len)); string id(len, ' '); in.read(id.data(), len); short cnt; in.read(reinterpret_cast<char*>(&cnt), sizeof(cnt)); table.setItem(x, y, id, cnt); } } // 加载输出槽 size_t outputCount; in.read(reinterpret_cast<char*>(&outputCount), sizeof(outputCount)); for (size_t k = 0; k < outputCount; k++) { in.read(reinterpret_cast<char*>(&len), sizeof(len)); string id(len, ' '); in.read(id.data(), len); short cnt; in.read(reinterpret_cast<char*>(&cnt), sizeof(cnt)); table.setOutputSlot(k, id, cnt); } // 加载关联方块ID in.read(reinterpret_cast<char*>(&len), sizeof(len)); string blockID(len, ' '); in.read(blockID.data(), len); table.setBlockID(blockID); // 加载每次合成产出数量 short craftCount; in.read(reinterpret_cast<char*>(&craftCount), sizeof(craftCount)); table.setCraftCount(craftCount); item.addTable(move(table)); } items.emplace(id, move(item)); } // 加载合成方块 size_t blockCount; in.read(reinterpret_cast<char*>(&blockCount), sizeof(blockCount)); for (size_t i = 0; i < blockCount; i++) { // 加载ID size_t len; in.read(reinterpret_cast<char*>(&len), sizeof(len)); string id(len, ' '); in.read(id.data(), len); // 加载名称 in.read(reinterpret_cast<char*>(&len), sizeof(len)); string name(len, ' '); in.read(name.data(), len); // 加载槽位 int inSlots, outSlots; in.read(reinterpret_cast<char*>(&inSlots), sizeof(inSlots)); in.read(reinterpret_cast<char*>(&outSlots), sizeof(outSlots)); CraftingBlock block(id, name, inSlots, outSlots); // 加载关联配方 size_t recipeCount; in.read(reinterpret_cast<char*>(&recipeCount), sizeof(recipeCount)); for (size_t j = 0; j < recipeCount; j++) { ItemTable table; // 加载输入网格 for (int x = 0; x < 3; x++) { for (int y = 0; y < 3; y++) { in.read(reinterpret_cast<char*>(&len), sizeof(len)); string id(len, ' '); in.read(id.data(), len); short cnt; in.read(reinterpret_cast<char*>(&cnt), sizeof(cnt)); table.setItem(x, y, id, cnt); } } // 加载输出槽 size_t outputCount; in.read(reinterpret_cast<char*>(&outputCount), sizeof(outputCount)); for (size_t k = 0; k < outputCount; k++) { in.read(reinterpret_cast<char*>(&len), sizeof(len)); string id(len, ' '); in.read(id.data(), len); short cnt; in.read(reinterpret_cast<char*>(&cnt), sizeof(cnt)); table.setOutputSlot(k, id, cnt); } // 加载关联方块ID in.read(reinterpret_cast<char*>(&len), sizeof(len)); string blockID(len, ' '); in.read(blockID.data(), len); table.setBlockID(blockID); // 加载每次合成产出数量 short craftCount; in.read(reinterpret_cast<char*>(&craftCount), sizeof(craftCount)); table.setCraftCount(craftCount); block.addRecipe(table); } craftingBlocks.emplace(id, move(block)); } } }; // ====================== 材料计算引擎 ====================== class MaterialCalculator { const ItemCollection& itemDB; mutable unordered_map<string, int> depthCache; public: explicit MaterialCalculator(const ItemCollection& db) : itemDB(db) {} // 计算材料需求 MaterialMap calculateMaterials(const string& id, long long count, ItemTable::PathMode pathMode = ItemTable::SHORTEST, ItemTable::BatchMode batchMode = ItemTable::EXACT_BATCH) { MaterialMap materials; set<string> visited; CalcMaterialsRecursive(id, count, materials, visited, pathMode, batchMode); return materials; } private: void CalcMaterialsRecursive(const string& id, long long count, MaterialMap& materials, set<string>& visited, ItemTable::PathMode pathMode, ItemTable::BatchMode batchMode) { // 检查循环依赖 if (visited.find(id) != visited.end()) return; visited.insert(id); // 获取物品 const Item* item = itemDB.getItem(id); if (!item || item->getTables().empty()) { materials[id] += count; // 基础材料 return; } // 选择最佳合成路径 const ItemTable* bestTable = selectBestTable(id, pathMode); if (!bestTable) return; // 计算合成批次 long long craftCnt = bestTable->getCraftCount(); long long batches = (batchMode == ItemTable::EXACT_BATCH) ? (count + craftCnt - 1) / craftCnt : static_cast<long long>(ceil(static_cast<double>(count) / craftCnt)); // 处理输入材料 for (int x = 0; x < 3; x++) { for (int y = 0; y < 3; y++) { const auto& slot = bestTable->getItem(x, y); if (!slot.first.empty() && slot.second > 0) { long long totalNeeded = batches * slot.second; CalcMaterialsRecursive(slot.first, totalNeeded, materials, visited, pathMode, batchMode); } } } } const ItemTable* selectBestTable(const string& id, ItemTable::PathMode mode) { const Item* item = itemDB.getItem(id); if (!item || item->getTables().empty()) return nullptr; const ItemTable* bestTable = &item->getTables()[0]; if (mode == ItemTable::SHORTEST || mode == ItemTable::LONGEST) { int bestDepth = (mode == ItemTable::SHORTEST) ? INT_MAX : 0; for (const auto& table : item->getTables()) { int depth = getCachedPathDepth(table); if ((mode == ItemTable::SHORTEST && depth < bestDepth) || (mode == ItemTable::LONGEST && depth > bestDepth)) { bestDepth = depth; bestTable = &table; } } } return bestTable; } int getCachedPathDepth(const ItemTable& table) const { int maxDepth = 0; for (int x = 0; x < 3; x++) { for (int y = 0; y < 3; y++) { const auto& slot = table.getItem(x, y); if (!slot.first.empty() && slot.second > 0) { // 使用缓存查询 auto it = depthCache.find(slot.first); if (it != depthCache.end()) { maxDepth = max(maxDepth, it->second); } else { int depth = calculateItemDepth(slot.first); depthCache[slot.first] = depth; maxDepth = max(maxDepth, depth); } } } } return maxDepth; } int calculateItemDepth(const string& id) const { // 获取物品 const Item* item = itemDB.getItem(id); if (!item || item->getTables().empty()) { return 0; // 基础材料 } // 计算最大深度 int maxDepth = 0; for (const auto& table : item->getTables()) { for (int x = 0; x < 3; x++) { for (int y = 0; y < 3; y++) { const auto& slot = table.getItem(x, y); if (!slot.first.empty() && slot.second > 0) { int depth = calculateItemDepth(slot.first) + 1; maxDepth = max(maxDepth, depth); } } } } return maxDepth; } }; // ====================== 逐步合成状态 ====================== struct CraftingStep { string itemID; long long required; uint8_t recipeIndex; bool completed; }; class StepByStepCrafting { const ItemCollection& db; MaterialCalculator& calc; string targetID; long long targetCount; stack<CraftingStep> stepStack; unordered_set<string> synthesizedItems; MaterialMap totalMaterials; public: StepByStepCrafting(const ItemCollection& db, MaterialCalculator& calc, const string& id, long long count) : db(db), calc(calc), targetID(id), targetCount(count) {} // 开始逐步合成 void start() { // 初始化第一个步骤 stepStack.push({targetID, targetCount, 0, false}); synthesizedItems.clear(); totalMaterials.clear(); // 开始交互 interactiveCrafting(); } private: // 交互式合成过程 void interactiveCrafting() { while (!stepStack.empty()) { CraftingStep& current = stepStack.top(); // 显示当前步骤信息 clear(); displayCurrentStep(current); // 获取用户选择 int choice = getUserChoice(); // 处理用户选择 switch (choice) { case 0: handleUndo(); break; case 1: processCurrentStep(current); break; case 2: stepStack.pop(); break; // 跳过 case 3: displayMaterialSummary(); pause(); break; case 4: return; // 退出 default: cout << "无效选择!" << endl; wait(1); } } cout << "恭喜! 所有材料已准备完成!" << endl; pause(); } void handleUndo() { if (stepStack.size() > 1) { CraftingStep current = stepStack.top(); stepStack.pop(); synthesizedItems.erase(current.itemID); if (db.getItem(current.itemID) == nullptr || db.getItem(current.itemID)->getTables().empty()) { totalMaterials[current.itemID] -= current.required; } } else { cout << "已在第一步,无法返回!" << endl; wait(1); } } // 显示当前步骤信息 void displayCurrentStep(const CraftingStep& step) const { cout << "===== 当前合成步骤 =====" << endl; cout << "物品: " << step.itemID << " x " << step.required << endl; const Item* item = db.getItem(step.itemID); if (!item || item->getTables().empty()) { cout << "\n这是基础材料,无法合成!" << endl; return; } // 显示当前配方 const auto& table = item->getTables()[step.recipeIndex]; cout << "使用配方: " << table.getPathDescription() << endl; // 显示当前材料 cout << "\n所需材料:" << endl; for (int x = 0; x < 3; x++) { for (int y = 0; y < 3; y++) { const auto& slot = table.getItem(x, y); if (!slot.first.empty() && slot.second > 0) { long long totalNeeded = step.required * slot.second; cout << " - " << slot.first << " x " << totalNeeded << endl; } } } // 显示当前状态 cout << "\n当前状态: " << (step.completed ? "已完成" : "待处理") << "\n========================" << endl; } // 获取用户选择 int getUserChoice() const { cout << "\n选项:" << endl; cout << "0. 返回上一步" << endl; cout << "1. 合成此物品" << endl; cout << "2. 跳过此物品" << endl; cout << "3. 查看材料汇总" << endl; cout << "4. 退出逐步合成" << endl; cout << "选择: "; int choice; cin >> choice; return choice; } // 处理当前步骤 void processCurrentStep(CraftingStep& step) { const Item* item = db.getItem(step.itemID); if (!item || item->getTables().empty()) { // 基础材料,直接完成 totalMaterials[step.itemID] += step.required; stepStack.pop(); return; } const auto& table = item->getTables()[step.recipeIndex]; short craftCount = table.getCraftCount(); long long batches = (step.required + craftCount - 1) / craftCount; // 整数除法 // 添加子步骤 for (int x = 0; x < 3; x++) { for (int y = 0; y < 3; y++) { const auto& slot = table.getItem(x, y); // 跳过空槽位和已合成物品 if (slot.first.empty() || slot.second == 0 || synthesizedItems.find(slot.first) != synthesizedItems.end()) continue; // 创建新步骤 stepStack.push({slot.first, batches * slot.second, 0, false}); } } // 标记当前步骤为已完成 step.completed = true; synthesizedItems.insert(step.itemID); } // 显示材料汇总 void displayMaterialSummary() const { clear(); cout << "===== 材料汇总 =====" << endl; cout << "目标: " << targetID << " x " << targetCount << endl; cout << "已准备材料:" << endl; for (const auto& [id, cnt] : totalMaterials) { cout << " - " << id << ": " << cnt << endl; } cout << "=====================" << endl; } }; // ====================== 用户界面工具 ====================== void clear() { #ifdef _WIN32 system("cls"); #else system("clear"); #endif } void pause() { cout << "\n按回车键继续..."; cin.ignore(numeric_limits<streamsize>::max(), '\n'); cin.get(); } void wait(int seconds) { this_thread::sleep_for(chrono::seconds(seconds)); } // ====================== 全局数据 ====================== ItemCollection itemDB; MaterialCalculator calculator(itemDB); fs::path savePath = fs::current_path() / "items.dat"; // ====================== 文件操作 ====================== void SaveItems(bool showMessage = true) { try { if (!fs::exists(savePath.parent_path())) { fs::create_directories(savePath.parent_path()); } itemDB.saveToFile(savePath); if (showMessage) cout << "物品数据已保存!" << endl; } catch (const exception& e) { cerr << "保存错误: " << e.what() << endl; } } void LoadItems() { try { if (fs::exists(savePath)) { itemDB.loadFromFile(savePath); cout << "物品数据已加载 (" << itemDB.size() << " 物品)" << endl; } else { cout << "未找到保存文件,创建新数据库" << endl; } } catch (const exception& e) { cerr << "加载错误: " << e.what() << endl; } } // ====================== 用户界面功能 ====================== void CreateItem() { clear(); string id; short maxStack; cout << "物品ID: "; cin >> id; if (itemDB.contains(id)) { cout << "物品已存在!" << endl; pause(); return; } cout << "最大堆叠数 (默认64): "; cin >> maxStack; if (maxStack <= 0) maxStack = 64; itemDB.add(Item(id, maxStack)); SaveItems(false); cout << "物品创建成功!" << endl; wait(1); } void DeleteItem() { clear(); auto ids = itemDB.getSortedIDs(); if (ids.empty()) { cout << "没有可删除的物品!" << endl; pause(); return; } cout << "可用物品:\n"; for (const auto& id : ids) { cout << " - " << id << "\n"; } string target; cout << "\n输入要删除的物品ID: "; cin >> target; if (!itemDB.contains(target)) { cout << "物品不存在!" << endl; pause(); return; } cout << "确认删除? (Y/N): "; char confirm; cin >> confirm; if (toupper(confirm) == 'Y') { if (itemDB.removeItem(target)) { SaveItems(false); cout << "物品已删除!" << endl; } else { cout << "删除失败!" << endl; } } else { cout << "操作取消" << endl; } wait(1); } void AddRecipeToItem() { clear(); auto ids = itemDB.getSortedIDs(); if (ids.empty()) { cout << "请先创建物品!" << endl; pause(); return; } cout << "可用物品:\n"; for (const auto& id : ids) { cout << " - " << id << "\n"; } string target; cout << "\n输入要添加配方的物品ID: "; cin >> target; Item* item = itemDB.getItem(target); if (!item) { cout << "物品不存在!" << endl; pause(); return; } // 选择合成方块 cout << "选择合成方块 (输入ID,留空使用默认): "; string blockID; cin.ignore(); getline(cin, blockID); CraftingBlock* block = nullptr; if (!blockID.empty()) { block = itemDB.getCraftingBlock(blockID); if (!block) { cout << "方块不存在,使用默认合成" << endl; wait(1); } } // 创建新合成表 ItemTable newTable; if (block) { newTable.setBlockID(block->getID()); cout << "使用方块: " << block->getName() << endl; } // 设置输入网格(支持"0"表示空槽位) cout << "\n输入3x3合成网格 (输入'0'表示空槽,格式: 物品ID 数量)\n"; for (int x = 0; x < 3; x++) { for (int y = 0; y < 3; y++) { string id; short cnt; cout << "位置 [" << x << "," << y << "]: "; cin >> id; // 处理"0"输入 if (id == "0") { newTable.setItem(x, y, "", 0); cin.ignore(numeric_limits<streamsize>::max(), '\n'); continue; } // 处理正常输入 cin >> cnt; if (!itemDB.contains(id)) { cout << "物品不存在,跳过此位置!" << endl; newTable.setItem(x, y, "", 0); continue; } newTable.setItem(x, y, id, cnt); } } // 设置每次合成产出数量 short craftCount; cout << "每次合成产出数量: "; cin >> craftCount; newTable.setCraftCount(craftCount > 0 ? craftCount : 1); // 设置输出槽数量 int outputSlots = block ? block->getOutputSlots() : 1; cout << "\n设置输出槽 (共 " << outputSlots << " 个槽位)\n"; for (int i = 0; i < outputSlots; i++) { string outID; short outCnt; cout << "输出槽 #" << (i+1) << " (物品ID 数量,留空跳过): "; cin >> outID; if (outID.empty() || outID == "0") { newTable.setOutputSlot(i, "", 0); cin.ignore(numeric_limits<streamsize>::max(), '\n'); continue; } cin >> outCnt; if (!itemDB.contains(outID)) { cout << "物品不存在,跳过此输出槽!" << endl; newTable.setOutputSlot(i, "", 0); continue; } newTable.setOutputSlot(i, outID, outCnt); } // 添加到物品或方块 if (block) { block->addRecipe(newTable); } else { item->addTable(newTable); } SaveItems(false); cout << "合成表添加成功!" << endl; wait(1); } void ViewRecipes() { clear(); auto ids = itemDB.getSortedIDs(); if (ids.empty()) { cout << "没有可查看的物品!" << endl; pause(); return; } cout << "可用物品:\n"; for (size_t i = 0; i < ids.size(); i++) { cout << setw(2) << i+1 << ". " << ids[i] << "\n"; } int choice; cout << "\n选择物品 (0返回): "; cin >> choice; if (choice <= 0 || choice > static_cast<int>(ids.size())) return; string target = ids[choice-1]; Item* item = itemDB.getItem(target); if (!item) return; clear(); cout << "物品: " << target << "\n"; cout << "最大堆叠: " << item->getMaxStack() << "\n\n"; if (item->getTables().empty()) { cout << "此物品没有合成配方!" << endl; pause(); return; } cout << "合成配方:\n"; for (size_t i = 0; i < item->getTables().size(); i++) { const auto& table = item->getTables()[i]; cout << "配方 #" << i+1 << ": " << table.getPathDescription() << "\n"; } cout << "\n输入配方编号查看详情 (0返回): "; cin >> choice; if (choice <= 0 || choice > static_cast<int>(item->getTables().size())) return; const auto& table = item->getTables()[choice-1]; clear(); cout << "配方详情: " << table.getPathDescription() << "\n"; // 显示输入网格 cout << "\n输入网格:\n"; for (int x = 0; x < 3; x++) { for (int y = 0; y < 3; y++) { const auto& slot = table.getItem(x, y); cout << "[" << (slot.first.empty() ? " " : slot.first.substr(0,2)) << (slot.second > 0 ? to_string(slot.second) : " ") << "] "; } cout << "\n"; } // 显示输出槽 cout << "\n输出槽:\n"; for (size_t i = 0; i < table.getAllOutputs().size(); i++) { const auto& slot = table.getOutputSlot(i); if (!slot.first.empty() && slot.second > 0) { cout << "槽位 #" << i+1 << ": " << slot.first << " x" << slot.second << "\n"; } } pause(); } void AddCraftingBlock() { clear(); string id, name; int inSlots, outSlots; cout << "方块ID: "; cin >> id; cout << "方块名称: "; cin.ignore(); getline(cin, name); cout << "输入槽数量: "; cin >> inSlots; cout << "输出槽数量: "; cin >> outSlots; if (inSlots <= 0 || outSlots <= 0) { cout << "槽位数量必须大于0!" << endl; pause(); return; } if (itemDB.getCraftingBlock(id)) { cout << "方块ID已存在!" << endl; pause(); return; } itemDB.addCraftingBlock(CraftingBlock(id, name, inSlots, outSlots)); SaveItems(false); cout << "合成方块添加成功!" << endl; wait(1); } void DeleteCraftingBlock() { clear(); const auto& blocks = itemDB.getAllCraftingBlocks(); if (blocks.empty()) { cout << "没有可用的合成方块!" << endl; pause(); return; } cout << "可用合成方块:\n"; for (const auto& [id, block] : blocks) { cout << " - " << id << " (" << block.getName() << ")\n"; } string target; cout << "\n输入要删除的方块ID: "; cin >> target; if (!itemDB.getCraftingBlock(target)) { cout << "方块不存在!" << endl; pause(); return; } cout << "确认删除? (Y/N): "; char confirm; cin >> confirm; if (toupper(confirm) == 'Y') { if (itemDB.removeCraftingBlock(target)) { SaveItems(false); cout << "方块已删除!" << endl; } else { cout << "删除失败!" << endl; } } else { cout << "操作取消" << endl; } wait(1); } void CalculateMaterials() { clear(); auto ids = itemDB.getSortedIDs(); if (ids.empty()) { cout << "没有可计算的物品!" << endl; pause(); return; } cout << "可用物品:\n"; for (size_t i = 0; i < ids.size(); i++) { cout << setw(2) << i+1 << ". " << ids[i] << "\n"; } int choice; cout << "\n选择物品 (0返回): "; cin >> choice; if (choice <= 0 || choice > static_cast<int>(ids.size())) return; string target = ids[choice-1]; long long count; cout << "需要数量: "; cin >> count; // 选择计算模式 cout << "\n选择计算模式:\n" << "1. 最短路径 (默认)\n" << "2. 最长路径\n" << "3. 精确匹配\n" << "选择: "; int modeChoice; cin >> modeChoice; ItemTable::PathMode pathMode = ItemTable::SHORTEST; ItemTable::BatchMode batchMode = ItemTable::EXACT_BATCH; if (modeChoice == 2) pathMode = ItemTable::LONGEST; else if (modeChoice == 3) pathMode = ItemTable::EXACT; // 计算材料 MaterialMap materials = calculator.calculateMaterials(target, count, pathMode, batchMode); // 显示结果 clear(); cout << "合成 " << count << " 个 " << target << " 需要:\n"; cout << "================================\n"; long long totalItems = 0; for (const auto& [id, cnt] : materials) { cout << setw(15) << left << id << ": " << cnt << "\n"; totalItems += cnt; } cout << "================================\n"; cout << "总计材料: " << totalItems << " 个\n"; pause(); } void StepByStepCraftingUI() { clear(); auto ids = itemDB.getSortedIDs(); if (ids.empty()) { cout << "没有可合成的物品!" << endl; pause(); return; } cout << "可用物品:\n"; for (size_t i = 0; i < ids.size(); i++) { cout << setw(2) << i+1 << ". " << ids[i] << "\n"; } int choice; cout << "\n选择物品 (0返回): "; cin >> choice; if (choice <= 0 || choice > static_cast<int>(ids.size())) return; string target = ids[choice-1]; long long count; cout << "需要数量: "; cin >> count; // 启动逐步合成 StepByStepCrafting stepper(itemDB, calculator, target, count); stepper.start(); } void SetSavePath() { clear(); cout << "当前保存路径: " << savePath << "\n\n"; cout << "输入新路径: "; string newPath; cin.ignore(); getline(cin, newPath); if (!newPath.empty()) { savePath = fs::path(newPath); cout << "路径已更新!" << endl; wait(1); } } // ====================== 主程序 ====================== int main() { LoadItems(); while (true) { clear(); cout << "===== 合成系统 =====" << endl; cout << "1. 创建物品" << endl; cout << "2. 删除物品" << endl; cout << "3. 添加合成表" << endl; cout << "4. 查看物品配方" << endl; cout << "5. 材料计算" << endl; cout << "6. 逐步合成" << endl; cout << "7. 添加合成方块" << endl; cout << "8. 删除合成方块" << endl; cout << "9. 设置保存路径" << endl; cout << "10. 保存数据" << endl; cout << "11. 退出" << endl; cout << "=====================" << endl; cout << "物品数: " << itemDB.size() << " | 方块数: " << itemDB.getAllCraftingBlocks().size() << " | 路径: " << savePath.filename() << endl; cout << "选项: "; int choice; cin >> choice; switch (choice) { case 1: CreateItem(); break; case 2: DeleteItem(); break; case 3: AddRecipeToItem(); break; case 4: ViewRecipes(); break; case 5: CalculateMaterials(); break; case 6: StepByStepCraftingUI(); break; case 7: AddCraftingBlock(); break; case 8: DeleteCraftingBlock(); break; case 9: SetSavePath(); break; case 10: SaveItems(); pause(); break; case 11: SaveItems(false); cout << "再见!" << endl; return 0; default: cout << "无效选项!" << endl; wait(1); } } }
08-07
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值