获取外部来源的种子

Obtain a seed for an outside source

本文关键字:种子 外部 获取      更新时间:2023-10-16

我不确定是否有人熟悉怪物牧场主游戏,但我想实现一个像他们这样的系统。

它的工作方式是,他们使用外部来源为RNG获得种子,然后创建一个怪物,并根据结果进行统计。他们使用CD,一款新的ds游戏使用声音。

我在想,从编程的意义上讲,我该如何从外部媒体获得种子,比如cd。就我所见,种子只是一个数字,所以使用C++,我如何从电脑上的东西中获得数字?我在想我可以使用插入USB端口的东西,会有点有趣吗?

编辑:我不是在研究如何获得一个随机的种子,我想知道如何读取类似的CD,以产生一个可以用作种子的数字。CD将始终产生相同的种子值,而不同的CD将产生不同的种子值。

是的,我记得那场比赛。简单的解决方案。使用类似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';
}

没有可移植的方法。在大多数Unix系统上,您可以读取/dev/random/dev/urandom

在Windows上,尝试CryptGenRandom

(对于这种应用,加密强伪随机数和"真"随机数一样好。证明我错了,你可以从世界上任何一所大学获得博士学位。)

[编辑]

对不起,我以为你在寻找一个不错的方式来滚动一个随机的角色。如果你每次都试图使用相同的数字,只需将种子存储在一个文件中,并使用任何旧的伪随机数生成器。

在unix上,只有

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

或者从代码中以二进制模式打开/dev/sr0。在Windows上,请参阅此片段(来自本页)。它支持Win98/2k等。示例使用A:,但您也可以指定用于原始读取的物理驱动器为CCD_ 5或CCD_。。。etc

// 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;
}
std::string tohash;
std::cin >> tohash;
boost::hash<std::string> string_hash;
std::size_t theRandomNumber = string_hash(tohash); 

将std::cin替换为从cd或文件系统读取的文件名、文件的内容等等。