国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 學(xué)院 > 開(kāi)發(fā)設(shè)計(jì) > 正文

用C++制作自己的游戲修改器(上)

2019-11-17 05:11:40
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

  本文旨在說(shuō)明修改游戲存檔的思路、編程方法和一點(diǎn)技巧,并無(wú)其他不良企圖。假如僅僅為了修改游戲,F(xiàn)PE、金山游俠等更為專業(yè)。

  前言

  大多數(shù)程序員都玩過(guò)游戲,也或曾想過(guò)修改游戲,筆者也不例外。我通常不希望自己受困于游戲中的經(jīng)驗(yàn)值、金錢之類的,于是采用修改游戲存檔文件的方法,自己動(dòng)手修改比起使用金山游俠等更有樂(lè)趣。究竟有時(shí)候只要享受一下游戲的情節(jié)就夠了,把大量的時(shí)間花費(fèi)在增加經(jīng)驗(yàn)值、賺錢方面太不合算了,究竟時(shí)間有限而游戲無(wú)限!方法嘛,使用老牌的UltraEdit(以下簡(jiǎn)稱UE),當(dāng)然還需要配合“計(jì)算器”進(jìn)行十進(jìn)制和十六進(jìn)制的轉(zhuǎn)換。時(shí)間長(zhǎng)了,也覺(jué)得繁瑣,何不自己動(dòng)手寫一個(gè)針對(duì)游戲存檔文件的修改器而一勞永逸?筆者比較喜歡C++,假如你有一定的C++基礎(chǔ),跟我走吧!

  筆者的電腦:AMD XP1700+,Windows2000(sp4),Borland C++ Builder 6(sp4)

  手工修改游戲存檔文件的方法

  游戲存檔文件大多使用二進(jìn)制格式,這樣對(duì)于讀取和保存數(shù)據(jù)都比較方便。可使用Windows的“計(jì)算器” 來(lái)看看10進(jìn)制和16進(jìn)制的區(qū)別:采用“科學(xué)性”模式,在10進(jìn)制模式下輸入數(shù)據(jù),然后切換到16進(jìn)制就行了。


  不過(guò)就算這樣轉(zhuǎn)換,看起來(lái)還是不很直觀,因?yàn)樵谟螒虼鏅n中并不是如此顯示的。


  那么用C++如何表達(dá)的呢?下面這個(gè)小程序演示了如何讀寫二進(jìn)制整數(shù)。

#include <iostream>
#include <fstream>
using namespace std;//標(biāo)準(zhǔn)庫(kù)所在的空間
int main()
{
 fstream BinFile("test.txt",ios::in ios::out ios::binary);//讀+寫+二進(jìn)制模式
 int i=1234;
 BinFile.write(reinterPRet_cast<const char*>(&i),sizeof(int));
 //reinterpret_cast是C++的強(qiáng)制轉(zhuǎn)換,這里把整數(shù)的地址強(qiáng)制轉(zhuǎn)換為const char*,
 //與C 的(const char*)&i 作用相同,但是reinterpret_cast更加含義明確。
 i=0;
 BinFile.seekg(0,ios::beg);//重新指向文件開(kāi)頭預(yù)備讀取
 BinFile.read(reinterpret_cast<char*>(&i),sizeof(int));
 cout<<"i="<<i<<’/n’;
}
  用UE打開(kāi)test.txt切換到二進(jìn)制模式,是這樣子的:

  在計(jì)算器中看到的是04D2,在UE 中看到的是D204,這就是筆者所謂的不直觀性。因此,假如你要在某個(gè)游戲存檔文件中間(擴(kuò)充開(kāi)來(lái)就是二進(jìn)制文件)尋找04D2這個(gè)數(shù)值,找到上圖顯示的地方就對(duì)了。筆者初期手工修改存檔也是這樣的,比較麻煩。

  下面這個(gè)小程序表明了模擬UE在二進(jìn)制文件中尋

  找整數(shù)的原理:

#include <iostream>
#include <fstream>
using namespace std;
int main()
{
 fstream BinFile("test.txt",ios::in ios::out ios::binary);//讀+寫+二進(jìn)制模式
 const int i=87654;
 BinFile.write(reinterpret_cast<const char*>(&i),
 sizeof(int));//強(qiáng)制轉(zhuǎn)換,把i用二進(jìn)制方式寫入文件
 BinFile.seekg(0,ios::beg);
 //重新指向文件開(kāi)頭,預(yù)備讀取

 char ch;
 while(BinFile.read(&ch,sizeof(char)))//讀取所有字符
  cout<<static_cast<int>(ch)<<"/t";//顯示
  //static_cast是C++的靜態(tài)轉(zhuǎn)換,與C的(int)ch作用相
  //同,但是static_cast意思表達(dá)更清楚。
  cout<<’/n’;
  //下面把i的地址轉(zhuǎn)換為字符串地址,并用char方式依次讀取,主要是比較兩者讀取的結(jié)果是否相同.
 const char* P=reinterpret_cast<const char*>(&i);
 for(int i=0;i<sizeof(int);++i)
  cout<<static_cast<int>(P[i])<<"/t";
} 更多文章 更多內(nèi)容請(qǐng)看C/C++技術(shù)專題  網(wǎng)絡(luò)游戲攻略  游戲策劃專題,或

自動(dòng)檢查游戲存檔中的數(shù)值

  手工在存檔文件中使用UE中來(lái)查找某個(gè)數(shù)值的時(shí)候,可能找到好多地方,靠一個(gè)一個(gè)查找然后記錄下地址可真費(fèi)眼神。寫個(gè)程序來(lái)自動(dòng)尋找指定的數(shù)值,并且記錄下地址吧!本文所述的地址都是從0開(kāi)始的,而且都以十進(jìn)制方式輸入輸出。

template<class T>
class CheckBinaryFile
{
 public:
  typedef fstream::off_type AddressType;
  CheckBinaryFile();
  void Run();
 private:
  static const int MaxByte=sizeof(T);
  const int CharSize;
  EInputStream CIN;//我自己寫的一個(gè)加強(qiáng)輸入流
  string FileName;
  T OldData;
  int ByteNumber;
  mutable bool InputIsOk;
  mutable ifstream BinaryFile;
  mutable list<AddressType> AddressList;
  void Input();
  int Check() const;
  void SaveAddressToFile(ostream&) const;
  void AutoModifySave(const T&) const;
};
template<class T>
const int CheckBinaryFile<T>::MaxByte;//定義靜態(tài)整型常量
  這是自己定義的一個(gè)類,下面逐一解釋:

template<class T>
  T代表要尋找的數(shù)據(jù)的類型。當(dāng)然,這個(gè)程序只是尋找整數(shù)(經(jīng)驗(yàn)值、金錢都是整數(shù)!),但我不排除以后要查找其他類型的數(shù)據(jù)。為了可擴(kuò)充性,使用了模板

typedef fstream::off_type AddressType;
  我要找到數(shù)據(jù)在文件中總有地址,這個(gè)地址是什么類型呢? int還是long,或者是其他類型?fstream有一個(gè)類型叫off_type,應(yīng)該是偏移類型的含義,在這里我把這個(gè)類型叫做AddressType。

static const int MaxByte=sizeof(T);
  這是一個(gè)靜態(tài)整型常量,表示T的大小(最多有多少字節(jié)),比如在我的機(jī)器上,sizeof(int)=4。T的大小在編譯的時(shí)候就確定,而且它不能被修改(const),對(duì)于所有查找類型相同的CheckBinaryFile,這個(gè)數(shù)值是唯一的,共享的(static)。

  構(gòu)造函數(shù):

template<class T>
CheckBinaryFile<T>::CheckBinaryFile():CharSize(sizeof (char)),CIN(cin)
{ InputIsOk=true; Input(); }
  CharSize 為sizeof(char),把cin 綁定到CIN。由于CharSize是常量,必須在構(gòu)造函數(shù)的初始化列表中設(shè)定。

  預(yù)設(shè)輸入狀態(tài),調(diào)用輸入函數(shù):

template<class T>
void CheckBinaryFile<T>::Input()
{
 cout<<"Binary file name:/t";
 CIN>>FileName;
 BinaryFile.open(FileName.c_str(),ios::in ios::binary);
 if(!BinaryFile){
  InputIsOk=false;
  cerr<<"Open file failed./n";
  return;
 }
 cout<<"The integer you want to search:/t";
 CIN>>OldData;
 cout<<"Byte number(1--"<<CheckBinaryFile<T>::MaxByte<<"):/t";
 CIN>>ByteNumber;
 if(ByteNumber<1 ByteNumber>CheckBinaryFile<T>::MaxByte) {
  //字節(jié)數(shù)錯(cuò)誤,調(diào)整為最大值
  ByteNumber=CheckBinaryFile<T>::MaxByte;
  cout<<"Byte number was amended to " << CheckBinaryFile<T>::ByteNumber<<’/n’;
 }
}
  提示用戶輸入二進(jìn)制存檔文件,用只讀+二進(jìn)制模式開(kāi)啟。假如失敗,設(shè)置輸入狀態(tài)為false,直接退出。然后提示用戶輸入要查找的整數(shù)(OldData)以及多少個(gè)字節(jié)(ByteNumber)。假如字節(jié)數(shù)錯(cuò)誤,調(diào)整為最大值。由于計(jì)算機(jī)系統(tǒng)的不同以及char,short,int,long之間存在
轉(zhuǎn)換關(guān)系,對(duì)于某些整型的字節(jié)數(shù)是不可確定的。比如100,可以用char表示,那么只需要sizeof(char)個(gè)字節(jié)表示就夠了,當(dāng)然也可以用字節(jié)數(shù)更多的類型,比如int,來(lái)表示100。

template<class T>
int CheckBinaryFile<T>::Check() const{
 const char* P=reinterpret_cast<const char*>(&OldData);
 char Range[CheckBinaryFile<T>::MaxByte];
 int Occurs=0;
 AddressType Addr=0;
 //填充0
 memset(Range,0,CheckBinaryFile<T>::MaxByte*CharSize);
 BinaryFile.read(Range,CharSize*ByteNumber);//填滿Range
 while(BinaryFile){
  if(memcmp(P,Range,CharSize*ByteNumber)==0){//匹配成功
   AddressList.push_back(Addr);
   ++Occurs;
  }
  //刪除一個(gè)最舊的
  memcpy(Range,&Range[1],CharSize*(ByteNumber-1));
  //讀入一個(gè)新的
  BinaryFile.read(&Range[ByteNumber-1],CharSize);
  ++Addr;
 }
 return Occurs;
}

  檢查輸入的二進(jìn)制文件中有多少個(gè)OldData,并保存地址,用模擬二進(jìn)制方式比較OldData。Range 是一個(gè)比較區(qū)域,這里不打算輸出這個(gè)字符串,也不考慮用strcpy來(lái)拷貝內(nèi)容,所以不必預(yù)留一個(gè)空間來(lái)保存結(jié)尾符號(hào)’/0’。填滿Range 后,開(kāi)始一個(gè)一個(gè)字符比較了:

  當(dāng)Range和OldData完全相同就表示匹配成功(memcmp返回0 表示成功),一旦成功,就把該地址保存下來(lái)(AddressList)。不管是否成功,把Range去掉一個(gè)最早讀取的,然后讀入一個(gè)新的,繼續(xù)匹配。函數(shù)返回匹配的個(gè)數(shù)。 更多文章 更多內(nèi)容請(qǐng)看C/C++技術(shù)專題  網(wǎng)絡(luò)游戲攻略  游戲策劃專題,或


  list是標(biāo)準(zhǔn)C++的一個(gè)容器,類似雙向鏈表,在添加/刪除節(jié)點(diǎn)方面表現(xiàn)優(yōu)秀。我不打算使用排序,因?yàn)閺念^到尾遍歷文件時(shí)保存下來(lái)的地址肯定是有序的;我也不需要隨機(jī)讀取這些地址,所以排除了vector以及deque這兩種容器。至于沒(méi)有采用內(nèi)建的數(shù)組,咳,我不
知道能找到多少地址,或許一個(gè)都沒(méi)有,或許成千上萬(wàn)。

  list有一個(gè)size()函數(shù),望文生義就是大小的意思,的確如此。不過(guò)由于list是一種鏈表,不像數(shù)組那樣只要把頭尾指針相減就能得到大小,取得size的辦法只有從頭到尾走一遍,速度比較慢。既然這個(gè)函數(shù)很清楚取得了多少個(gè)地址,那就直接返回這個(gè)數(shù)目吧!

template<class T>
void CheckBinaryFile<T>::Run()
{
 if(InputIsOk==false) return;
 const int Occurs=Check();
 cout<<Occurs<<" different addresses were found./n";
 if(Occurs==0) return;
 cout<<"Save address info to files(y/n)?/t";
 char YN;
 CIN>>YN;
 if(YN==’y’ YN==’Y’){
  cout<<"Address file name:/t";
  string AddressFileName;
  CIN>>AddressFileName;
  ofstream Save(AddressFileName.c_str(),ios::out);
  if(!Save)
  { cerr<<"Create "<<AddressFileName<<" failed./n";}
  else
  { SaveAddressToFile(Save);
  Save.close();
 }
}
cout<<"Modify binary file automatically(y/n)?/t";
CIN>>YN;
 if(YN==’y’ YN==’Y’){
  cout<<"New value:/t";
  T NewValue;
  CIN>>NewValue;
  system("dir > @tmp");
  system("del @*/q");
  AutoModifySave(NewValue);
 }
}
  假如輸入錯(cuò)誤,則直接退出。顯示匹配的個(gè)數(shù)并詢問(wèn)是否保存這些地址至文件。再詢問(wèn)是否自動(dòng)修改。比如找到了10個(gè)地址,自動(dòng)修改將產(chǎn)生10個(gè)新文件,每個(gè)文件與原文件相比都只修改了一個(gè)地址的數(shù)值。輸入新的數(shù)值,將產(chǎn)生若干個(gè)新文件。新文件的格式是@+地址的十進(jìn)制表示。產(chǎn)生新文件前先把舊的以@開(kāi)頭的文件刪除。假如不存在@開(kāi)頭的文件,system("del @*/q");會(huì)說(shuō)找不到文件,不大舒適,那我先制造一個(gè)@tmp(system("dir > @tmp");),這里使用了DOS的輸出重定向,把原本顯示到屏幕的內(nèi)容輸入到@tmp中。

template<class T>
void CheckBinaryFile<T>::SaveAddressToFile(ostream& os)
const
{
 copy(AddressList.begin(),AddressList.end(),
 ostream_iterator<T>(os,"/t"));
}
  把AddressList的內(nèi)容保存下來(lái)。copy是C++的函數(shù),把一個(gè)區(qū)間的內(nèi)容拷貝到另一個(gè)地方。

template<class T>
void CheckBinaryFile<T>::AutoModifySave(const T& NewValue)
const
{
 list<AddressType>::const_iterator Beg=AddressList.
 begin(),End=AddressList.end();
 const char* P=reinterpret_cast<const char*>(&NewValue);
 for(;Beg!=End;++Beg){
  BinaryFile.clear();//清除錯(cuò)誤狀態(tài)
  BinaryFile.seekg(0,ios::beg);//指向文件開(kāi)頭,預(yù)備讀 AddressType Addr=0;
  char ch;
  stringstream NewFile;
  NewFile<<"@"<<*Beg;
  string NewFileName(NewFile.str());
  ofstream Write(NewFileName.c_str(),ios::out ios:: binary);
  if(!Write){
   cerr<<NewFileName<<" ... unsUCcessfully./n";
   continue;
  }
  while(Addr < *Beg && BinaryFile){
   //小于指定地址的內(nèi)容
   BinaryFile.read(&ch,CharSize);
   Write.write(&ch,CharSize);
   ++Addr;
  }
  for(int k=0;k<ByteNumber;++k){//忽略源文件
   BinaryFile.read(&ch,CharSize);
  }
  Write.write(P,CharSize*ByteNumber); //寫入新值
  while(BinaryFile){//源文件剩余的內(nèi)容拷貝到新文件
   BinaryFile.read(&ch,CharSize);
   Write.write(&ch,CharSize);
  }
  Write.close();
  cout<<NewFileName<<" ... successfully./n";
 }//for
}
  根據(jù)AddressList的大小遍歷若干遍源文件。新的文件用@+地址格式。先把小于指定地址的內(nèi)容拷貝到新文件,到了指定地址后把新值寫入新文件,再把源文件剩余的內(nèi)容拷貝到新文件。const_iterator是常量迭代器,表明不修改AddressList 的內(nèi)容。begin 函數(shù)得到 AddressList的開(kāi)頭,end函數(shù)得到AddressList的最后一個(gè)元素的下一個(gè)地址,++表示迭代器前進(jìn)一格。把源文件剩余的內(nèi)容拷貝到新文件后,會(huì)導(dǎo)致源文件BinaryFile 的狀態(tài)為bad,在bad狀態(tài)下要執(zhí)行比如讀寫、重新指向文件某個(gè)位置等操作必須先調(diào)用clear清除這個(gè)狀態(tài)。

  mutable是C++新近的要害字,大體意思是表明該內(nèi)容可以在const成員函數(shù)中修改。比如在這個(gè)類中間,比如mutable bool InputIsOk;InputIsOk只是表明用戶輸入數(shù)據(jù)的正確性,并不影響自身的狀態(tài); mutable list<AddressType> AddressList;也沒(méi)有改動(dòng)源文件的各個(gè)屬性,只是保存了信息。

  好了,這個(gè)類基本寫完了。他的功能是:

  輸入一個(gè)二進(jìn)制文件名以及要查找的整數(shù)和字節(jié)數(shù)。

  告訴你找到了多少個(gè)地址(可保存地址信息到文件),假如你愿意,可以分別把這些地址上的數(shù)據(jù)修改為新的數(shù)值后產(chǎn)生新文件。

  你可以在仙劍2上做實(shí)驗(yàn)。仙劍2的存檔地址不是固定的。記錄下當(dāng)前的經(jīng)驗(yàn)值和金錢(都是4字節(jié)),存檔后切換到Windows,對(duì)存檔的文件開(kāi)刀,假如報(bào)告找到的地址只有四五個(gè),可以自動(dòng)產(chǎn)生新文件。把新文件覆蓋原存檔,切換到游戲后讀取剛剛修改的文件試試看。大
不了直接退出游戲。仙劍2 可以直接切換到Windows,這對(duì)于修改存檔比較方便。我以前老老實(shí)實(shí)玩到底才32級(jí),現(xiàn)在可以一下子飆升到七八十級(jí)(最高似乎是99),我以前不知道蘇媚還有“狐舞動(dòng)天”的特技,嗬嗬! 更多文章 更多內(nèi)容請(qǐng)看C/C++技術(shù)專題  網(wǎng)絡(luò)游戲攻略  游戲策劃專題,或 改進(jìn)1 :對(duì)地址文件取得交集

  應(yīng)該說(shuō)有些游戲的存檔還是很老實(shí)的——地址不變。


  對(duì)于這種類型的存檔,我們可以用對(duì)集合取交集的方法來(lái)縮小范圍。比如經(jīng)驗(yàn)值為4的時(shí)候存檔為A,經(jīng)驗(yàn)值為7 的時(shí)候存檔為B。對(duì)A用上面的工具查找4,保存地址信息為4.txt;對(duì)B用上面的工具查找7,保存地址信息為7.txt。把4.txt和7.txt的內(nèi)容看作兩個(gè)集合,假如地
址不變,那么取得兩者的交集就能大大縮小查找范圍。

  嗯,仙劍2 不行,仙劍1 和3倒是可以的。

  對(duì)于集合的個(gè)數(shù),至少兩個(gè),可以對(duì)多個(gè)集合取交集。C++提供了set_intersection函數(shù),可以對(duì)兩個(gè)有序區(qū)間進(jìn)行交集運(yùn)算,我們只需要不斷重復(fù)這個(gè)過(guò)程,就能對(duì)多個(gè)集合執(zhí)行交集運(yùn)算了。

  約定:輸入若干個(gè)集合文件進(jìn)行交集元算,當(dāng)輸入一個(gè)不存在的文件表示結(jié)束輸入。當(dāng)程序發(fā)現(xiàn)取得空集的時(shí)候就自動(dòng)結(jié)束。

template<class T>
void GetIntersection()
{
 EInputStream CIN(cin);
 cout<<"Input some text filenames for reading,end
 with a nonexistent one./n";
 string fn;
 CIN>>fn;
 ifstream Read(fn.c_str());
 if(!Read){
  cerr<<"Open "<<fn<<" failed./n";
  return;
 }
 vector<T> V1;
 copy(istream_iterator<T>(Read),istream_iterator<T> (),back_inserter(V1));//保存file1的內(nèi)容到V1
 CIN>>fn;
 Read.clear();
 Read.close();
 Read.open(fn.c_str());
 if(!Read){
  cerr<<"Open "<<fn<<" failed./n";
  return;
 }
 vector<T> V2,V3;
 copy(istream_iterator<T>(Read),istream_iterator<T> (),back_inserter(V2));//保存file2的內(nèi)容到V2
 sort(V1.begin(),V1.end());//排序
 //刪除重復(fù)的數(shù)據(jù)
 V1.erase(unique(V1.begin(),V1.end()),V1.end());
 sort(V2.begin(),V2.end());
 V2.erase(unique(V2.begin(),V2.end()),V2.end());
 set_intersection(V1.begin(),V1.end(),V2.begin(),
 V2.end(),back_inserter(V3));//V3=V1和V2的交集
 while(V3.empty()==false){
  //假如是空集就可以退出了
  CIN>>fn;
  Read.clear();
  Read.close();
  Read.open(fn.c_str());
  if(!Read) break;
  vector<T>().swap(V1);//清除V1
  copy(istream_iterator<T>(Read),
  istream_iterator<T>(),back_inserter(V1));
  sort(V1.begin(),V1.end());
  V1.erase(unique(V1.begin(),V1.end()),V1.end());
  V2.swap(V3);//V2和V3交換
  vector<T>().swap(V3);//清除V3
  set_intersection(V1.begin(),V1.end(),
  V2.begin(),V2.end(),back_inserter(V3));
 }
 if(V3.empty()){
  cout<<"An empty aggregate was found after reading " <<fn<<"./n";
  return;
 }
 cout<<V3.size()<<" value were enumerated./n";
 cout<<"Input save filename:/t";
 CIN>>fn;
 ofstream Dest(fn.c_str());
 if(!Dest){
  cerr<<"Create "<<fn<<" failed./n";
 }
 else{
  copy(V3.begin(),V3.end(),ostream_iterator<T>(Dest,"/t"));
  Dest.close();
 }
}
  下面逐一解釋:

template<class T>

  和上一例含義一樣,在此代表集合元素的類別。我可以對(duì)整數(shù)集合進(jìn)行交集元算,對(duì)小數(shù)、字符串組成的集合也能進(jìn)行交集元算。當(dāng)然我現(xiàn)在只用到了整數(shù)集合。

  CIN是我自己的一個(gè)加強(qiáng)類,你可以看作cin。

  首先打開(kāi)兩個(gè)指定的文件(做交集運(yùn)算至少要兩個(gè)集合),假如有一個(gè)失敗就退出。
把這兩個(gè)文件的內(nèi)容分別放入V1 和V2。然后對(duì)V1 和V2 排序(sort),剔除重復(fù)內(nèi)容(unique和erase)。對(duì)調(diào)整過(guò)的V1 和V2 執(zhí)行交集,結(jié)果保存到V3。

  當(dāng)V3不為空集的時(shí)候開(kāi)始循環(huán):讀取下一個(gè)等待輸入的文件。清空V1,把新的文件內(nèi)容放入V1,把V3的內(nèi)容拷貝到V2,清空V3,把V1 和V2 的交集放入V3。

  上述“把V3的內(nèi)容拷貝到V2”只是表達(dá)一個(gè)意思,實(shí)際上只是把V3 和V2 做交換而已,因?yàn)閂3我需要清空,并不需要真正的拷貝。把某個(gè)集合清空,只是和臨時(shí)的空集做交換而已。

  這里我使用vector容器,set也是可以的。使用set的好處是可以自動(dòng)排序和剔除重復(fù)內(nèi)容,當(dāng)然自動(dòng)排序和保持元素的唯一性是需要代價(jià)的。使用vector的好處是等到所有輸入完畢后,執(zhí)行某些函數(shù)(比如sort,unique,erase)來(lái)完成上述功能,一次性達(dá)到目的,而不像set那樣任何時(shí)刻都保持元素的有序性和唯一性。

  當(dāng)數(shù)據(jù)量比較大的時(shí)候,vector或許要高效一些。當(dāng)然,主觀臆斷不是科學(xué)精神,實(shí)踐是最好的檢驗(yàn)手段。我在這里只是隨便選取了vector。一旦選擇了vector,那么“清除所有內(nèi)容”最好使用“與空的臨時(shí)vector交換”,采用這種方法后,vector的容量也會(huì)變得盡可能的小;而假如采用clear 的方法,容量保持不變。因?yàn)関ector內(nèi)部也采用數(shù)組,數(shù)組就意味著一塊連續(xù)的內(nèi)存,一旦需求超出了容量會(huì)導(dǎo)致重新分配,所以vector會(huì)采用預(yù)留一部分空間的策略,避免每次增加元素都要重新分配。而set不一樣,底層采用二叉樹(shù)(sgi采用更嚴(yán)格的
紅黑樹(shù)),不需要預(yù)留空間,要多少分配多少,對(duì)它進(jìn)行清空操作只需要簡(jiǎn)單的執(zhí)行clear即可,當(dāng)然,和空的臨時(shí)集合作交換也很好。臨時(shí)變量一旦離開(kāi)自己的生存期就會(huì)釋放自身的資源。

  拿仙劍3舉例,比如有24文錢的時(shí)候存檔為pal01.arc。有60文錢時(shí)存檔為pal02.arc。退出游戲(假如你有兩臺(tái)電腦組成網(wǎng),可以不退出游戲在另外一臺(tái)電腦上修改),把pal01.arc,pal02.arc和這個(gè)程序放在一起,對(duì)pal01.arc查找4 字節(jié)的24,保存地址為24.txt;對(duì) pal02.arc 查找4 字節(jié)的60,保存地址為60.txt。然后對(duì)24.txt和60.txt做交集。仙劍3的金錢存檔有兩個(gè),一個(gè)是表象,方便讀取存檔,另一個(gè)才是真正的存放金錢的地址。所以交集結(jié)果應(yīng)該為2個(gè)。知道了真正的地址,對(duì)于自動(dòng)產(chǎn)生的文件就可以有的放矢的選擇了。
(未完待續(xù)) 更多文章 更多內(nèi)容請(qǐng)看C/C++技術(shù)專題  網(wǎng)絡(luò)游戲攻略  游戲策劃專題,或

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 来凤县| 米易县| 道真| 临安市| 庆城县| 兴安县| 中阳县| 沈阳市| 邻水| 米易县| 特克斯县| 精河县| 广饶县| 西贡区| 扎赉特旗| 增城市| 迁安市| 内丘县| 常山县| 修武县| 陆良县| 阳山县| 兴文县| 全州县| 九台市| 伊宁县| 隆昌县| 蓬莱市| 灵台县| 三穗县| 云和县| 元谋县| 东乌珠穆沁旗| 九寨沟县| 鄢陵县| 惠安县| 九江县| 廊坊市| 乌鲁木齐市| 永宁县| 精河县|