C++独立游戏存档模块设计 VERSION_1.7
TANXL_DATABASE VERSION_1_7
实践是检验真理的唯一标准,在实际使用此模块进行游戏存档功能设计时发现了几处极不合理的地方。首先,此模块采用十六进制数对数据索引编号,但是却仅仅只使用了五位。在无符号数中没有专门的五位无符号数,只有UINT16(四位)和UINT32(八位),采用五位即意味着剩下三位的空间被浪费掉了。其次,程序函数应该保证通用性,在上一版的设计中添加储存信息需要根据零是否合法而对相同数据输入截然不同的值(零合法时需要输入六位数据,第六位标记数据插入位置)。此版本主要修改内容如下。
修改图解
首先是设置物品结构体的操作统一,并将UINT32的空间用满(设置0xF为非法值)
重置结构体函数(其实改了效果是一样的,主要明确各位长度关系)
计算已设置位个数的函数
移除源文件中定义的类
根据以上修改对默认数据函数重写(其中展示了零合法与不合法的数据添加方式)
TANXL_DATABASE.H VERSION_1_7
//_VERSION_1_7_ UPDATE LOG
// LAST_UPDATE 2022-08-26 20:20#pragma once#ifndef IOSTREAM
#define IOSTREAM
#include<iostream>
#endif#ifndef FSTREAM
#define FSTREAM
#include<fstream>
#endif#ifndef STRING
#define STRING
#include<string>
#endif#ifndef SSTREAM
#define SSTREAM
#include<sstream>
#endif#ifndef VECTOR
#define VECTOR
#include<vector>
#endifenum ESort_Mode//为SortDataBase函数提供的功能枚举
{SORT_LOCALF = 0,SORT_MEMORY = 2,
};enum EDivid_Mode//为Divid_Char函数提供的功能枚举
{GET_STATUS_DAT = 0,GET_STORAG_DAT = 1,GET_STATUS_TAG = 2,GET_STATUS_STR = 3,GET_OLDSTY_DAT = 4
};enum ESet_Specified
{SET_TYPE_STATUS = 0,SET_EXAC_STATUS = 1,SET_OTH1_STATUS = 2,SET_OTH2_STATUS = 3,SET_OTH3_STATUS = 4,
};struct Data_Vector//短数据表(Vector)
{explicit Data_Vector(int I_A = 0, std::string D_A = NULL, int I_B = 0, std::string D_B = NULL, int I_C = 0, std::string D_C = NULL) :Id_1(I_A), Id_2(I_B), Id_3(I_C), Sd_1(D_A), Sd_2(D_B), Sd_3(D_C) {}int Id_1, Id_2, Id_3;std::string Sd_1, Sd_2, Sd_3;
};struct Id_Vector//短类型表(Vector)
{explicit Id_Vector(int Type, int Exac, std::string Code = "NULL", std::string Name = "NULL") :Type(Type), Exac(Exac), StrA(Code), StrB(Name), exac(new std::vector<Data_Vector*>) {}int Type, Exac;std::string StrA, StrB;std::vector<Data_Vector*>* exac;//用于支持折半查找
};class TANXL_DataBase
{private:struct{unsigned Item_Status{ 0 };unsigned Status_1{}; std::string Code;unsigned Status_2{}; std::string Name;unsigned Status_3{}; std::string Oth1;unsigned Status_4{}; std::string Oth2;unsigned Status_5{}; std::string Oth3;}Item_Instance;std::vector<Id_Vector*>* IC_Vector;int Current_Location;bool Is_Instance_Data;//用来判断Item_Instance中是否有数据bool Is_Chain_Empty;//用来判断链表是否为空bool Is_Zero_Legal;//值为true时0成为合法值 可在输出中显示/使用inline void Set_Code(std::string set, unsigned status);inline void Set_Name(std::string set, unsigned status);inline void Set_Oth1(std::string set, unsigned status);inline void Set_Oth2(std::string set, unsigned status);inline void Set_Oth3(std::string set, unsigned status);Id_Vector* Id_Chain_Locate(int Type, int Exac);//时间复杂度为logN的Id_Chain快速定位函数 Type Exac 指Id_Chain的同名变量Data_Vector* Data_Chain_Locate(int Type, int Exac, int Depth);//借由Id_Chain_Locate函数对不同深度的Data_Chain定位void Replace_Chain(int OldType, int OldExac, int OldDepth, int Type, int Exac);//转移Data_Chain到另一个Id_Chain下void Append_Chain(Data_Vector& New_Data, Id_Vector& New_Id);//链表添加内容V3 添加到Vector中void Get_Item_Status();//获取物品数值 并加载到结构中void Clear_Chain();//清理链表void ResetInstance();//重置Item结构的内容inline void OstreamSpace(std::ostream& os, int Before = 0, int After = 0);//根据级别输出空格 Before用于执行前对级别数值进行修改 After用于执行后inline void Combine_Status();//组合Status各物品级别并合并到Item_Instance中
public:TANXL_DataBase(bool Zero_Legal = false);//构造函数bool Get_LocalData(std::string File_Name);//获取本地数据 并新建一个链表 支持打开任意格式的文件(.usd .sd)//↓编辑实例 0x12030405 1代表Code位 2代表Name位 03代表Oth1位 依此类推//↓在1.7版本中考虑到零合法的操作一致性 最大值已被作为不可选标志即 Code/Name位的F 或Oth位的FFvoid Set_Instance(unsigned Num, std::string Set);void Get_Specified(int Type, int Exac, int Nums);//读取指定Type(A)_Exac(B)级别的物品 并载入到单例结构中 Nums表示链表中的第几个(从0开始)//↓修改指定Type(A)_Exac(B)级别的物品 Nums表示链表中的第几个(从0开始) level取值范围为1~5 用于选定Type Exac Oth1 ...//↓修改OTH1 OTH2 OTH3的时候直接更改相关内容 修改TYPE-EXAC时 会转移当前Data_Chain到新的符合修改后的TYPE-EXAC的Id_Chain下void Set_Specified(int Type, int Exac, int Nums, int level, int Id, std::string Data);void Remove_Chain(int Type, int Exac);//删除某一节点与其下所有内容//↓输出当前内存中的链表的所有内容 仅支持输出Id_Vector和Data_Vector中的内容 当前内存为空时会抛出错误void Print_Data();void AppendItem(bool To_File = true, std::string File_Name = "Tanxl_DataBase.usd");//向本地文件中(.usd)添加Item物品 此函数会导致Item单例重置//↓使本地(.usd)文件的内容合理化 In_File_Name为输入文件名 Out_File_Name为输出文件名 现在具有保存链表修改功能//↓Mode为true时从文件中读取数据 需要提供In/Out_File_Name 执行后清空内存中的链表 Mode为false时直接对当前内存中的链表进行整理 可以使现有链表改为升序 执行后不清空void SortDataBase(int Mode = SORT_LOCALF, std::string Out_File_Name = "Tanxl_Data", std::string In_File_Name = "Tanxl_DataBase");friend std::ostream& operator<<(std::ostream& fot, TANXL_DataBase& s);//用于直接输出当前Item单例内的信息
};std::string Combine_Char(std::string data, int Start, int End);//拆分char数组获取指定内容,Start为开始位置End为结束位置(结束位置不保留)std::string Divid_Char(std::string data, int Mode = GET_STATUS_DAT);//拆分单行内容获取信息void Reset_Chain(TANXL_DataBase TDB, int Type, int Exac, int Nums);//重置链表某一单元 Nums表示A,B level下的第几个(从0开始)void Data(bool Mode = true, bool Zero = true);//测试用默认数据 为true时每次添加的同时还会在屏幕上打印 Zero用于选择添加模式 为True时添加的为0合法的数据void Combine_File(std::string FileA, std::string FileB);//将FileA和FileB的内容整合到FileA中 仅限USD格式文件使用
2022/08/26 20:20 WILD_CHICKEN_PROGRAMING VERSION_1_7
#pragma once#include "Tanxl_DataBase.h"std::string Combine_Char(std::string data, int Start, int End)
{if (End < Start){throw "错误 : Combine_Char 的输入值Start大于End的值";return "";}std::string New_data{};for (int i = Start, j = 0; i < End; i++, j++){if (data[i] == '\t' || data[i] == '<'){End++; j--;continue;}if (j < 0)j = 0;New_data = New_data + data[i];}return New_data;
}std::string Divid_Char(std::string data, int Mode)
{int Lock{ -1 }, Last{ -1 };char Left, Right;switch (Mode){case GET_STATUS_DAT://获取单例数据0~15Left = '/'; Right = '>';break;case GET_STORAG_DAT://获取储存的信息Left = '>'; Right = '<';break;case GET_STATUS_TAG://信息条目Left = '<'; Right = ':';break;case GET_STATUS_STR://V3链表主副键StringLeft = ':'; Right = '/';break;case GET_OLDSTY_DAT:Left = ':'; Right = '>';break;default:throw "错误 : Divid_Char 没有此条目的功能(0~3 为合法内容,而你输入了" + std::to_string(Mode) + ")";return "";}for (int i = 0; i < data.length(); i++)//获取内容{if ((data[i] == Left && Lock == -1) || (data[i] == Right && Lock != -1)){if (Lock == -1){Lock = i + 1;continue;}elseLast = i;}if (Lock != -1 && Last != -1)return Combine_Char(data, Lock, Last);}throw "失败 : Divid_Char 读取错误 不存在满足条件的内容";return "";
}void Reset_Chain(TANXL_DataBase TDB, int A, int B, int Nums)
{TDB.Set_Specified(A, B, Nums, 3, -1, "NULL");TDB.Set_Specified(A, B, Nums, 4, -1, "NULL");TDB.Set_Specified(A, B, Nums, 5, -1, "NULL");
}void Data(bool Mode, bool Zero)
{TANXL_DataBase TDB_Instance(Zero);for (unsigned Content = 0x11111f55; Content < 0x11112111; Content++){TDB_Instance.Set_Instance(0x10000000 | 0x0fffffff, "手枪");TDB_Instance.Set_Instance(Content & 0x0f000000 | 0xf0ffffff, "地下水");TDB_Instance.Set_Instance(Content & 0x00ff0000 | 0xff00ffff, std::to_string(rand() % 100));TDB_Instance.Set_Instance(Content & 0x0000ff00 | 0xffff00ff, std::to_string(rand() % 100));TDB_Instance.Set_Instance(Content & 0x000000ff | 0xffffff00, std::to_string(rand() % 100));if (Mode)std::cout << TDB_Instance;TDB_Instance.AppendItem();}for (unsigned Content = 0x22221f55; Content < 0x22222111; Content++){TDB_Instance.Set_Instance(0x20000000 | 0x0fffffff, "步枪");TDB_Instance.Set_Instance(Content & 0x0f000000 | 0xf0ffffff, "M4A1-S");TDB_Instance.Set_Instance(Content & 0x00ff0000 | 0xff00ffff, std::to_string(rand() % 100));TDB_Instance.Set_Instance(Content & 0x0000ff00 | 0xffff00ff, std::to_string(rand() % 100));TDB_Instance.Set_Instance(Content & 0x000000ff | 0xffffff00, std::to_string(rand() % 100));if (Mode)std::cout << TDB_Instance;TDB_Instance.AppendItem();}for (unsigned Content = 0x33331f55; Content < 0x33332111; Content++){TDB_Instance.Set_Instance(0x30000000 | 0x0fffffff, "重型武器");TDB_Instance.Set_Instance(Content & 0x0f000000 | 0xf0ffffff, "Nova");TDB_Instance.Set_Instance(Content & 0x00ff0000 | 0xff00ffff, std::to_string(rand() % 100));TDB_Instance.Set_Instance(Content & 0x0000ff00 | 0xffff00ff, std::to_string(rand() % 100));TDB_Instance.Set_Instance(Content & 0x000000ff | 0xffffff00, std::to_string(rand() % 100));if (Mode)std::cout << TDB_Instance;TDB_Instance.AppendItem();}for (unsigned Content = 0x44441f55; Content < 0x44442111; Content++){TDB_Instance.Set_Instance(0x40000000 | 0x0fffffff, "微型冲锋枪");TDB_Instance.Set_Instance(Content & 0x0f000000 | 0xf0ffffff, "MP9");TDB_Instance.Set_Instance(Content & 0x00ff0000 | 0xff00ffff, std::to_string(rand() % 100));TDB_Instance.Set_Instance(Content & 0x0000ff00 | 0xffff00ff, std::to_string(rand() % 100));TDB_Instance.Set_Instance(Content & 0x000000ff | 0xffffff00, std::to_string(rand() % 100));if (Mode)std::cout << TDB_Instance;TDB_Instance.AppendItem();}
}void Combine_File(std::string FileA, std::string FileB)
{std::string Line{};std::fstream in(FileB + ".usd", std::ios::in);if (!in.is_open())std::fstream in(FileB + ".sd", std::ios::in);std::fstream out(FileA + ".sd", std::ios::app);if (in.is_open() && out.is_open()){out << std::endl;while (std::getline(in, Line))out << Line << std::endl;}elsethrow "失败 : Combine_File 无法打开的指定文件";
}std::ostream& operator<<(std::ostream& fot, TANXL_DataBase& s)
{if ((s.Item_Instance.Status_1 + s.Item_Instance.Status_2 + s.Item_Instance.Status_3 + s.Item_Instance.Status_4 + s.Item_Instance.Status_5) || s.Is_Zero_Legal){s.Get_Item_Status();fot << "<Type_Status : " << s.Item_Instance.Code << " / " << s.Item_Instance.Status_1 << ">" << std::endl;s.OstreamSpace(fot, 1); fot << "<Exac_Status : " << s.Item_Instance.Name << " / " << s.Item_Instance.Status_2 << ">" << std::endl;s.OstreamSpace(fot, 1, 1); fot << "<TDBS_Item>" << std::endl;if (s.Item_Instance.Status_3 || s.Is_Zero_Legal) {s.OstreamSpace(fot);fot << "<Oth1: " << s.Item_Instance.Status_3 << ">" << s.Item_Instance.Oth1 << "</Oth1>" << std::endl;}if (s.Item_Instance.Status_4 || s.Is_Zero_Legal) {s.OstreamSpace(fot);fot << "<Oth2: " << s.Item_Instance.Status_4 << ">" << s.Item_Instance.Oth2 << "</Oth2>" << std::endl;}if (s.Item_Instance.Status_5 || s.Is_Zero_Legal) {s.OstreamSpace(fot);fot << "<Oth3: " << s.Item_Instance.Status_5 << ">" << s.Item_Instance.Oth3 << "</Oth3>" << std::endl;}s.OstreamSpace(fot, -1); fot << "</TDBS_Item>" << std::endl;s.OstreamSpace(fot, -1); fot << "</Exac_Status>" << std::endl;s.OstreamSpace(fot, -1); fot << "</Type_Status>" << std::endl;}return fot;
}inline void TANXL_DataBase::Set_Code(std::string set, unsigned status){ Item_Instance.Code = set; Item_Instance.Status_1 = status; Combine_Status(); }
inline void TANXL_DataBase::Set_Name(std::string set, unsigned status){ Item_Instance.Name = set; Item_Instance.Status_2 = status; Combine_Status(); }
inline void TANXL_DataBase::Set_Oth1(std::string set, unsigned status){ Item_Instance.Oth1 = set; Item_Instance.Status_3 = status; Combine_Status(); }
inline void TANXL_DataBase::Set_Oth2(std::string set, unsigned status){ Item_Instance.Oth2 = set; Item_Instance.Status_4 = status; Combine_Status(); }
inline void TANXL_DataBase::Set_Oth3(std::string set, unsigned status){ Item_Instance.Oth3 = set; Item_Instance.Status_5 = status; Combine_Status(); }TANXL_DataBase::TANXL_DataBase(bool Zero_Legal) :Is_Instance_Data(false), Is_Chain_Empty(true), Is_Zero_Legal(Zero_Legal),IC_Vector(new std::vector<Id_Vector*>),Current_Location(0) {}inline void TANXL_DataBase::OstreamSpace(std::ostream& os, int Before, int After)
{static int TDB_Status = 0;//级别数值 用于记录当前行的Tab数量TDB_Status += Before;for (int i = 0; i < TDB_Status; i++)os << "\t";TDB_Status += After;
}inline void TANXL_DataBase::Combine_Status()
{Item_Instance.Item_Status = (Item_Instance.Status_1 << 28)+ (Item_Instance.Status_2 << 24)+ (Item_Instance.Status_3 << 16)+ (Item_Instance.Status_4 << 8 )+ Item_Instance.Status_5;
}void TANXL_DataBase::ResetInstance()
{Item_Instance.Status_1 = 0x0;Item_Instance.Status_2 = 0x0;Item_Instance.Status_3 = 0x00;Item_Instance.Status_4 = 0x00;Item_Instance.Status_5 = 0x00;Combine_Status();Is_Instance_Data = false;
}void TANXL_DataBase::Set_Instance(unsigned Num, std::string Set)
{int SetTimes{ 0 };if (0 <= ((Num & 0xf0000000) >> 28) && ((Num & 0xf0000000) >> 28) < 15) {Set_Code(Set, ((Num & 0xf00000000) >> 28)); SetTimes++;}if (0 <= ((Num & 0x0f000000) >> 24) && ((Num & 0x0f000000) >> 24) < 15) {Set_Name(Set, ((Num & 0x0f000000) >> 24)); SetTimes++;}if (0 <= ((Num & 0x00ff0000) >> 16) && ((Num & 0x00ff0000) >> 16) < 255) {Set_Oth1(Set, ((Num & 0x00ff0000) >> 16)); SetTimes++;}if (0 <= ((Num & 0x0000ff00) >> 8) && ((Num & 0x0000ff00) >> 8) < 255) {Set_Oth2(Set, ((Num & 0x0000ff00) >> 8)); SetTimes++;}if (0 <= (Num & 0x000000ff) && (Num & 0x000000ff) < 255) {Set_Oth3(Set, (Num & 0x000000ff)); SetTimes++;}if (SetTimes)Is_Instance_Data = true;
}void TANXL_DataBase::AppendItem(bool To_File, std::string File_Name)
{if (!Is_Instance_Data){throw "添加失败! 结构内容为空";return;}else if (To_File){Is_Instance_Data = true;std::fstream out(File_Name, std::ios::app);if (out.is_open()){out << *this;this->ResetInstance();out.close();}}else{Data_Vector* DTemp = new Data_Vector(Item_Instance.Status_3, Item_Instance.Oth1,Item_Instance.Status_4, Item_Instance.Oth2,Item_Instance.Status_5, Item_Instance.Oth3);Id_Vector* ITemp = new Id_Vector(Item_Instance.Status_1, Item_Instance.Status_2,Item_Instance.Code, Item_Instance.Name);if (DTemp && ITemp)//判断是否申请空间成功Append_Chain(*DTemp, *ITemp);elsethrow "添加失败! 申请内存空间失败";}
}void TANXL_DataBase::SortDataBase(int Mode, std::string Out_File_Name, std::string In_File_Name)
{if (Mode == SORT_LOCALF)if (!Get_LocalData(In_File_Name)){throw "SortDataBase() Failed ! : 未能成功匹配文件";return;}if (Is_Chain_Empty){throw "SortDataBase() Failed ! : 获取到的数据为空";return;}std::fstream out(Out_File_Name + ".sd", std::ios::out | std::ios::trunc);Id_Vector* PIC{ this->IC_Vector->at(0)};out << "<Tanxl_DataBase Information>" << std::endl;std::vector<Id_Vector*>::iterator IOIE{ IC_Vector->end()};std::vector<Id_Vector*>::iterator IOIB{ IC_Vector->begin() };do{std::vector<Data_Vector*>::iterator IODE{ (*IOIB)->exac->end() };std::vector<Data_Vector*>::iterator IODB{ (*IOIB)->exac->begin() };std::cout << "\t<Type_Status : " << (*IOIB)->StrA << " / " << (*IOIB)->Type << ">" << std::endl;std::cout << "\t\t<Exac_Status : " << (*IOIB)->StrB << " / " << (*IOIB)->Exac << ">" << std::endl;out << "\t<Type_Status : " << (*IOIB)->StrA << " / " << (*IOIB)->Type << ">" << std::endl;out << "\t\t<Exac_Status : " << (*IOIB)->StrB << " / " << (*IOIB)->Exac << ">" << std::endl;do{if ((*IODB)->Id_1 + (*IODB)->Id_2 + (*IODB)->Id_3 == -3)continue;out << "\t\t\t<TDB_Item>" << std::endl;if ((*IODB)->Id_1 || Is_Zero_Legal)out << "\t\t\t\t<Oth1: " << (*IODB)->Id_1 << ">" << (*IODB)->Sd_1 << "</Oth1>" << std::endl;if ((*IODB)->Id_2 || Is_Zero_Legal)out << "\t\t\t\t<Oth2: " << (*IODB)->Id_2 << ">" << (*IODB)->Sd_2 << "</Oth2>" << std::endl;if ((*IODB)->Id_3 || Is_Zero_Legal)out << "\t\t\t\t<Oth3: " << (*IODB)->Id_3 << ">" << (*IODB)->Sd_3 << "</Oth3>" << std::endl;out << "\t\t\t</TDB_Item>" << std::endl;IODB++;} while (IODB != IODE);out << "\t\t</Exac_Status>" << std::endl;out << "\t</Type_Status>" << std::endl;IOIB++;} while (IOIB != IOIE);out << "</Tanxl_DataBase Information>" << std::endl;out.close();Clear_Chain();if (Mode == SORT_LOCALF){std::string s = In_File_Name + ".usd";remove(s.c_str());}
}void TANXL_DataBase::Append_Chain(Data_Vector& New_Data, Id_Vector& New_Id)
{if (Is_Chain_Empty){IC_Vector->push_back(&New_Id);IC_Vector->at(0)->exac->push_back(&New_Data);Is_Chain_Empty = false;return;}int Left{ 0 }, Value{ New_Id.Type * 16 + New_Id.Exac },Right{ static_cast<int>(IC_Vector->size()) - 1 <= 0 ? 0 : static_cast<int>(IC_Vector->size()) - 1 };while (true){int Mid{ (Left + Right) / 2 };Id_Vector* PIC = IC_Vector->at(Mid);int PIC_Value{ PIC->Type * 16 + PIC->Exac };if (PIC_Value == Value)//Type B匹配时{PIC->exac->push_back(&New_Data);Is_Chain_Empty = false;return;}else if (Left == Right && PIC_Value != Value)//Type B不匹配 但已经是最接近的值时{if (PIC_Value < Value)Left += 1;this->IC_Vector->insert(IC_Vector->begin() + Left, &New_Id);IC_Vector->at(Left)->exac->push_back(&New_Data);Is_Chain_Empty = false;return;}else if (PIC_Value < Value)Left = Mid;else if (PIC_Value > Value)Right = Mid;if (Left + 1 == Right){if (PIC_Value < Value)Left = Right;else Right = Left;}}throw "Append() Failed ! : 未知原因";return;
}bool TANXL_DataBase::Get_LocalData(std::string File_Name)
{std::fstream in(File_Name + ".usd", std::ios::in);if (!in.is_open())std::fstream in(File_Name + ".sd", std::ios::in);if (in.is_open()){std::string Type_Data{}, Exac_Data{};//需要使用时再定义int Type_Stat{}, Exac_Stat{};int IData[3]{ 0 }, Target{ -1 };std::string SData[3]{};std::string Line{};while (std::getline(in, Line)){std::string Tag{ Combine_Char(Line, 1, 5) };if (Tag == "Type"){Type_Stat = std::stoi(Divid_Char(Line, GET_STATUS_DAT));Type_Data = Divid_Char(Line, GET_STATUS_STR);std::getline(in, Line);Exac_Stat = std::stoi(Divid_Char(Line, GET_STATUS_DAT));Exac_Data = Divid_Char(Line, GET_STATUS_STR);while (std::getline(in, Line)){Tag = Combine_Char(Line, 1, 5);if (Tag == "Type"){Type_Stat = std::stoi(Divid_Char(Line, GET_STATUS_DAT));Type_Data = Divid_Char(Line, GET_STATUS_STR);}else if (Tag == "Exac"){Exac_Stat = std::stoi(Divid_Char(Line, GET_STATUS_DAT));Exac_Data = Divid_Char(Line, GET_STATUS_STR);}else if (Tag == "/TDB"){Data_Vector* Data_Temp = new Data_Vector(IData[0], SData[0], IData[1], SData[1], IData[2], SData[2]);Id_Vector* Id_Temp = new Id_Vector(Type_Stat, Exac_Stat, Type_Data, Exac_Data);IData[0] = 0; IData[1] = 0; IData[2] = 0; SData[0] = ""; SData[1] = ""; SData[2] = "";if (Data_Temp && Id_Temp)Append_Chain(*Data_Temp, *Id_Temp);elsethrow "添加失败! 申请内存空间失败";continue;}else if (Tag == "Oth1")Target = 0;else if (Tag == "Oth2")Target = 1;else if (Tag == "Oth3")Target = 2;if (Target == -1)continue;IData[Target] = std::stoi(Divid_Char(Line, GET_OLDSTY_DAT));SData[Target] = Divid_Char(Line, GET_STORAG_DAT);Target = -1;}}}in.close();return true;}elsereturn false;
}void TANXL_DataBase::Clear_Chain()
{for (int i = 0; i < IC_Vector->size(); i++)Remove_Chain(IC_Vector->at(i)->Type, IC_Vector->at(i)->Exac);Is_Chain_Empty = true;
}void TANXL_DataBase::Get_Specified(int Type, int Exac, int Nums)
{if (Data_Vector * PDC{ Data_Chain_Locate(Type, Exac, Nums) }){Id_Vector* PIC = { Id_Chain_Locate(Type, Exac) };Item_Instance.Status_1 = PIC->Type; Item_Instance.Code = PIC->StrA;Item_Instance.Status_2 = PIC->Exac; Item_Instance.Name = PIC->StrB;Item_Instance.Status_3 = PDC->Id_1; Item_Instance.Oth1 = PDC->Sd_1;Item_Instance.Status_4 = PDC->Id_2; Item_Instance.Oth2 = PDC->Sd_2;Item_Instance.Status_5 = PDC->Id_3; Item_Instance.Oth3 = PDC->Sd_3;Combine_Status();return;}throw "Get_Specified() Failed ! : 未能成功匹配相同值";
}void TANXL_DataBase::Get_Item_Status()//此处存在BUG 位的取值未进行对应的修改 会导致输出的数据各编号错误
{Item_Instance.Status_1 = ((Item_Instance.Item_Status & 0xf0000) >> 16);Item_Instance.Status_2 = ((Item_Instance.Item_Status & 0x0f000) >> 12);Item_Instance.Status_3 = ((Item_Instance.Item_Status & 0x00f00) >> 8 );Item_Instance.Status_4 = ((Item_Instance.Item_Status & 0x000f0) >> 4 );Item_Instance.Status_5 = ( Item_Instance.Item_Status & 0x0000f );
}//V0.1B41稳定更新中已修复void TANXL_DataBase::Print_Data()//输出当前链表中的所有内容 V3 Updated
{if (!Is_Chain_Empty){Id_Vector* PIC{};Data_Vector* PDC{};int PIC_Count{ 0 };std::vector<Id_Vector*>::iterator IOI = IC_Vector->end() - 1;do{int PDC_Count{ 0 };PIC = this->IC_Vector->at(PIC_Count++);std::vector<Data_Vector*>::iterator IOD = PIC->exac->end() - 1;std::cout << "Id_Vector :" << PIC->Type << " - " << PIC->StrA << " - " << PIC->Exac << " - " << PIC->StrB << std::endl;do{PDC = PIC->exac->at(PDC_Count++);std::cout << "\tData_Vector :" << PDC->Id_1 << "-" << PDC->Id_2 << "-" << PDC->Id_3 << std::endl;} while (PDC != *IOD);} while (PIC != *IOI);return;}throw "Print_Data() Failed ! : 链表内容为空";
}void TANXL_DataBase::Set_Specified(int Type, int Exac, int Nums, int level, int Id, std::string Data) //V3 Updated
{if (Data_Vector * PDC{ Data_Chain_Locate(Type, Exac, Nums) })switch (level){case SET_TYPE_STATUS:Replace_Chain(Type, Exac, Nums, Id, Exac);return;case SET_EXAC_STATUS:Replace_Chain(Type, Exac, Nums, Type, Id);return;case SET_OTH1_STATUS:PDC->Id_1 = Id;PDC->Sd_1 = Data;return;case SET_OTH2_STATUS:PDC->Id_2 = Id;PDC->Sd_2 = Data;return;case SET_OTH3_STATUS:PDC->Id_3 = Id;PDC->Sd_3 = Data;return;}throw "Set_Specified() Failed ! : 查找相关内容不成功或链表内容为空";
}void TANXL_DataBase::Remove_Chain(int Type, int Exac)
{if (Id_Vector * PIC{ Id_Chain_Locate(Type, Exac) }){for (int i{ 0 }; i < PIC->exac->size(); i++)delete PIC->exac->at(i);//释放 Data_VectorPIC->exac->clear();delete PIC;//释放 Id_VectorIC_Vector->erase(IC_Vector->begin() + Current_Location);}
}Id_Vector* TANXL_DataBase::Id_Chain_Locate(int Type, int Exac)
{int Left{ 0 },Value{ Type * 16 + Exac },Right{ static_cast<int>(IC_Vector->size()) - 1 >= 0 ? static_cast<int>(IC_Vector->size()) - 1 : 0 };;if (Left == Right){if (Value == IC_Vector->at(0)->Type * 16 + IC_Vector->at(0)->Exac){Current_Location = 0;return IC_Vector->at(0);}throw "Id_Chain_Locate Failed ! : 未能成功匹配相同值";return NULL;}else{while (Left != Right){int Mid{ (Left + Right) / 2 };int Mid_Value{ IC_Vector->at(Mid)->Type * 16 + IC_Vector->at(Mid)->Exac };if (Mid_Value == Value){Current_Location = Mid;return IC_Vector->at(Mid);}else if (Mid_Value > Value)Right = Mid;else if (Mid_Value < Value)Left = Mid;if (Left == Right){throw "Id_Chain_Locate Failed ! : 未能成功匹配相同值";return NULL;}}}throw "Id_Chain_Locate Failed ! : 未知原因";return NULL;
}Data_Vector* TANXL_DataBase::Data_Chain_Locate(int Type, int Exac, int Depth)
{Id_Vector* PIC{ Id_Chain_Locate(Type, Exac) };if (PIC->exac->size() < Depth){throw "Data_Chain_Locate Failed ! : 超出当前容器最大深度";return NULL;}else if (Depth < 0 && Depth + static_cast<int>(PIC->exac->size()) >= 0)return PIC->exac->at(Depth + PIC->exac->size());while (Depth + static_cast<int>(PIC->exac->size() < 0))Depth += static_cast<int>(PIC->exac->size());return PIC->exac->at(Depth);
}void TANXL_DataBase::Replace_Chain(int OldType, int OldExac, int OldDepth, int Type, int Exac)
{Id_Vector* PIC{ Id_Chain_Locate(OldType, OldExac) };Append_Chain(*PIC->exac->at(OldDepth), *new Id_Vector(Type, Exac));if (PIC->exac->size() > OldDepth && OldDepth >= 0)PIC->exac->erase(PIC->exac->begin() + OldDepth);else if (PIC->exac->size() + OldDepth >= 0 && PIC->exac->size() + OldDepth < PIC->exac->size())PIC->exac->erase(PIC->exac->begin() + PIC->exac->size() + OldDepth);
}
使用范例
#include <iomanip>TANXL_DataBase NData(true);int n = 0x10101010, i = 5;while (i--){std::cout << "Updating : " << std::setbase(16) << n << std::endl;NData.Set_Instance(n++, "Updating" + std::to_string(n));std::cout << NData;NData.AppendItem(false);}NData.Print_Data();
此示例会生成一组数据并在控制台中输出,更多详情请参见接口介绍。
FROM_TANXL_ENGINE_VERSION_0_1_BUILD_33
C++独立游戏存档模块设计 VERSION_1.7相关推荐
- 游戏设计与开发_独立游戏开发:怎样设计游戏新手教学?
教你画像素画原创出品 塞尔达荒野之息 1.游戏新手教学需要考虑的4个问题 1.玩家怎么玩? 2.玩家怎么完成游戏目标? 3.为什么玩家要这么做? 4.玩家何时会采取行动? 动作类游戏,玩家的操作会即时 ...
- 开发笔记:掉落系统模块设计思路
本文所讨论的掉落系统是一个游戏中的通用模块,不仅局限于打怪时掉落物品,包括抽卡.开宝箱.任务奖励.活动奖励等功能都可以使用.抽象地说,掉落系统是由给定参数按照特定的算法生成一系列可附加在玩家身上的东西 ...
- 开发笔记:游戏逻辑模块组织及数据同步
一个游戏根据功能可以划分为多个不同的模块,如金钱.背包.装备.技能.任务.成就等.按照软件工程的思想,我们希望分而治之单独实现不同的模块,再将这些模块组合在一起成为一份完整的游戏.但现实是残酷的,不同 ...
- 使用Unity引擎打造赛博朋克之城!CIGA Game Jam 2019 48小时独立游戏开发挑战
一年一度的CIGA Game Jam 48小时极限开发挑战赛结束了,作为开发独立游戏的爱好者和玩家的我们在这次活动中纷纷展现出了自己独特的才华.同样作为开发者中的一员,我们团队参与了这次比赛,而这次, ...
- 模块设计之“模块”与“模块化”
模块设计之"模块"与"模块化" 模块泛指软件系统的功能部件.在软件的体系结构设计完成之际,我们就已经确定了所有模块的功能,并且把模块安放在体系结构的恰当位置上. ...
- python3.7魔塔游戏_基于Funcode平台的“火锅版魔塔”游戏开发与设计
2019 年第 2 期 信息与电脑 China Computer & Communication 软件开发与应用 基于 Funcode 平台的"火锅版魔塔"游戏开发与设计 ...
- springboot基于JAVA游戏周边商城设计与实现毕业设计源码261622
Springboot游戏周边商城的开发 摘 要 现今人们的生活方式逐渐丰富,电脑和网络已经融入了人们生活中的滴滴点点,无时不刻的影响着我们的日常生活,网络游戏已经进入到了大多数人的生活之中.在游戏的世 ...
- 手机rpg游戏存档在哪_在免费RPG日尝试新游戏
手机rpg游戏存档在哪 您是否曾经考虑过尝试<龙与地下城>,但不知道如何开始? 您是否在年轻时玩过Traveler,并一直在考虑重返业余爱好? 您是否对角色扮演游戏(RPG)感到好奇,但不 ...
- 游戏服务器架构设计的一些整理
一.前言 没有最好的架构,只有最适合自身业务的架构. 首先我们应该确定的是大的架构方向:分布式 / 单应用+负载均衡,这两种架构设计直接影响后续的网络层.缓存层.数据层.业务层的设计.笔者这两种架构的 ...
- 百万用户级游戏服务器架构设计
百万用户级游戏服务器架构设计 服务器结构探讨 -- 最简单的结构 所谓服务器结构,也就是如何将服务器各部分合理地安排,以实现最初的功能需求.所以,结构本无所谓正确与错误:当然,优秀的结构更有助于系统的 ...
最新文章
- flask_模拟请求post,get
- gdb调试fork+exec创建的子进程的方法
- Linux内核探讨-- 第五章
- ModuleNotFoundError: No module named ‘mmcv._ext‘
- 85.路由器和电脑的设置
- Oracle运行set autotrace on报错SP2-0618、SP2-0611
- c++对象回收问题_从垃圾回收解开Golang内存管理的面纱之三垃圾回收
- 程序员发展职业规划_大厂程序员总结:程序员30岁前,该如何规划自己的职业发展?...
- Java解码aac,Android MediaCodec解码AAC,AudioTrack播放PCM音频
- 采用qt技术,开发OFD电子文档阅读器
- linux实用技巧:ubuntu18.04安装samba服务器实现局域网文件共享
- SMILES 与 SELFIES 的转换代码
- gRPC 使用自定义的 NameResolver
- 如何通俗易懂地讲解牛顿迭代法?
- 计算机计算的应用,计算器计算
- 线程同步的几种实现方法
- 从全备中恢复单库或单表,小心有坑!
- 企业如何建立商业生态系统
- ESP8266 Arduino Hard resetting via RTS pin...
- Adobe安装程序无法初始化的解决方案