2011-06-24 110 views
3

我不確定是否有人熟悉怪物牧場主遊戲,但我想實現像他們的系統。獲得外部來源的種子

它的工作方式是使用外部來源爲RNG獲取種子,然後創建一個怪物並基於結果統計。他們使用CD,新的遊戲使用聲音。

我想知道如何從編程意義上的外部中間這樣的CD獲得種子。據我看到種子只是一個數字,所以使用C++我怎樣才能從附加到我的電腦的東西獲得數字?我想我可以使用插入USB端口的東西,會有趣嗎?

編輯:我不看如何得到一個隨機種子,我想知道我如何可以讀取類似的東西的CD來產生一個我可以用作種子的數字。 CD總是會產生相同的種子值,不同的CD會產生不同的種子值。

+1

在* nix上,'/ dev/random'將完成這項工作。 –

+0

@Cicada我不明白你的意思 – Skeith

+0

你使用Linux嗎?如果是,我可以在答案中詳細說明。 –

回答

0

沒有便攜的方式。在大多數Unix系統上,您可以閱讀/dev/random/dev/urandom

在Windows上,嘗試CryptGenRandom

(對於這種應用,加密性強的僞隨機數與「真」隨機數一樣好。證明我錯了,你可以從世界上任何一所大學獲得博士學位。)

對不起,我以爲你是在尋找一個像樣的方式來隨機發送一個字符。如果每次嘗試使用相同的數字,只需將種子存儲在一個文件中,並使用任何舊的僞隨機數字生成器。

3

是的,我記得那場比賽。解決方案簡單使用類似boost.filesystem的文件獲取驅動器上的文件列表。

然後決定一些基於這些文件生成種子的方案。它可以像按字母順序讀取第一個文件那樣簡單,然後以二進制讀取文件,並將前四個字節作爲32位字。但是,這可能不會像您想的那樣產生獨特的價值。更好的做法可能是做一些涉及多個文件的散列。

下面是一個簡單的例子。它發現K驅動器上的第一個文件的大小大於sizeof(unsigned int),從中檢索到很多字節,並將其存儲在一個值中。顯然這不是很複雜,但它應該讓你開始。

#include <iostream> 
#include <fstream> 
#include <boost/filesystem.hpp> 

int main() 
{ 
    namespace fs = boost::filesystem; 

    unsigned int seed = 0; 
    fs::recursive_directory_iterator begin("K:/"), end; 
    while (begin != end) 
    { 
     if (fs::is_regular_file(*begin) 
      && fs::file_size(*begin) >= sizeof(seed)) 
     { 
      std::ifstream fin(begin->path().string(), std::ios::binary); 
      fin.read((char*)&seed, sizeof(seed)); 
      break; 
     } 

     ++begin; 
    } 

    std::cout << "Seed = " << seed << '\n'; 
} 
+0

「類似boost.filesystem」的這一點非常詳細,是問題的關鍵lol,謹慎詳細說明? – Skeith

+0

那麼,一種方法是抓住'dir/s/b'的輸出並在其上運行散列算法。 – Brian

+0

@Skeith:看我的更新。這有幫助嗎? –

0

在Unix,只是

dd if=/dev/sr0 bs=512 count=32 

或在從代碼二進制模式打開/ dev/SR0。在Windows上,請參閱此片段(from this page)。它支持WIN98/2K等示例使用A:但是你也可以指定 爲原始讀數爲"\\\\.\\PhysicalDrive0""\\\\.\\PhysicalDrive1"物理驅動器...等

// All msdos data structures must be packed on a 1 byte boundary 
#pragma pack (1) 
struct 
{ 
    DWORD StartingSector ; 
    WORD NumberOfSectors ; 
    DWORD pBuffer; 
}ControlBlock; 
#pragma pack() 

#pragma pack (1) 
typedef struct _DIOC_REGISTERS 
{ 
    DWORD reg_EBX; 
    DWORD reg_EDX; 
    DWORD reg_ECX; 
    DWORD reg_EAX; 
    DWORD reg_EDI; 
    DWORD reg_ESI; 
    DWORD reg_Flags; 
} DIOC_REGISTERS ; 
#pragma pack() 

char * ReadSectors(int drive, DWORD startinglogicalsector, int numberofsectors) 
{ 

    char* buffer = (char*)malloc (512*numberofsectors); 
    HANDLE hDevice ; 
    DIOC_REGISTERS reg ; 
    BOOL fResult ; 
    DWORD cb ; 

    // Creating handle to vwin32.vxd (win 9x) 
    hDevice = CreateFile ("\\\\.\\vwin32", 
      0, 
      0, 
      NULL, 
      0, 
      FILE_FLAG_DELETE_ON_CLOSE, 
      NULL); 

    if (hDevice == INVALID_HANDLE_VALUE) 
    { 
     // win NT/2K/XP code 
     HANDLE hDevice; 
     DWORD bytesread; 

     char _devicename[] = "\\\\.\\A:"; 
     _devicename[4] += drive; 

     // Creating a handle to disk drive using CreateFile() function .. 
     hDevice = CreateFile(_devicename, 
       GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 
       NULL, OPEN_EXISTING, 0, NULL); 

     if (hDevice == INVALID_HANDLE_VALUE) 
      return NULL; 

     // Setting the pointer to point to the start of the sector we want to read .. 
     SetFilePointer (hDevice, (startinglogicalsector*512), NULL, FILE_BEGIN); 

     if (!ReadFile (hDevice, buffer, 512*numberofsectors, &bytesread, NULL)) 
      return NULL; 
    } 
    else 
    { 
     // code for win 95/98 
     ControlBlock.StartingSector = (DWORD)startinglogicalsector; 
     ControlBlock.NumberOfSectors = (DWORD)numberofsectors ; 
     ControlBlock.pBuffer = (DWORD)buffer ; 

     //----------------------------------------------------------- 
     // SI contains read/write mode flags 
     // SI=0h for read and SI=1h for write 
     // CX must be equal to ffffh for 
     // int 21h's 7305h extention 
     // DS:BX -> base addr of the 
     // control block structure 
     // DL must contain the drive number 
     // (01h=A:, 02h=B: etc) 
     //----------------------------------------------------------- 

     reg.reg_ESI = 0x00 ; 
     reg.reg_ECX = -1 ; 
     reg.reg_EBX = (DWORD)(&ControlBlock); 
     reg.reg_EDX = drive+1; 
     reg.reg_EAX = 0x7305 ; 

     // 6 == VWIN32_DIOC_DOS_DRIVEINFO 
     fResult = DeviceIoControl (hDevice, 
       6, 
       &(reg), 
       sizeof (reg), 
       &(reg), 
       sizeof (reg), 
       &cb, 
       0); 

     if (!fResult || (reg.reg_Flags & 0x0001)) return NULL;  
    } 

    CloseHandle(hDevice); 
    return buffer; 
} 
0
std::string tohash; 
std::cin >> tohash; 
boost::hash<std::string> string_hash; 
std::size_t theRandomNumber = string_hash(tohash); 

與替換的std :: CIN從cd或文件系統讀取的文件名,文件的內容等等。

+0

你的代碼下的句子就是我所要求的。只是去做這不是一個非常有用的答案。 – Skeith