ゲーム用に作成した乱数ジェネレーターで問題が発生しています。高速な疑似ランダム フィールド ジェネレーターが必要です。暗号的に安全である必要はありません。ベクトルとシードを取り込んで、人間による簡単な検査を欺くのに十分なランダムなハッシュ値を与えるだけで済みます。
ただし、このコードは、2 次元ベクトルを指定して結果を 2 で変更すると、「疑似乱数」出力を生成できません。ほぼチェッカーボード パターンが生成されます。
理由はわかりませんが、正直なところ、それがわかればうれしいのですが、それがわからなくても気にすることはありません。ほとんどの場合、乱数を生成するこの方法はひどすぎると思ったので、この問題にアプローチする別の方法を知りたいと思いました。つまり、「何が間違っているのか」と尋ねるのではなく、この方法で乱数を生成するための優れた代替方法についてのリソースまたはポインターを本当に探していました。
基本的に、同じ入力を入力すると、元に戻すことができる「無限」の 2D ノイズ フィールド (ホワイト ノイズと考えてください) を生成しようとしています。
私が書いたコードは次のとおりです (これは fnv ハッシュであるはずです。テンプレートのことをお許しください。これをコードから取り出しただけです。後でクリーンアップします)。
//Static random number generator, will generate a random number based off of a seed and a coordinate
template<typename T, typename... TL>
uint32_t static_random_u32(T const& d, TL const&... rest) {
return fnv_hash32(d, rest..., 2938728349u); //I'm a 32-bit prime!
}
template<typename T, typename... TL>
uint32_t fnv_hash32(T const& v, TL const&... rest) {
uint32_t hash;
fnv_hash32_init(hash);
fnv_hash32_types(hash, v, rest...);
return hash;
}
inline void fnv_hash32_init(uint32_t& hash) {
hash = 2166136279u; //another 32-bit prime
}
// Should produce predictable values regardless of endianness of architecture
template<typename T, typename... TL>
void fnv_hash32_types(uint32_t& hash, T const& v, TL const&... rest) {
#if LITTLE_ENDIAN
fnv_hash32_bytes(hash, (char*)&v, sizeof(v), true);
#else
fnv_hash32_bytes(hash, (char*)&v, sizeof(v), false);
#endif
fnv_hash32_types(hash, rest...);
}
inline void fnv_hash32_types(uint32_t& hash) {}
inline void fnv_hash32_bytes(uint32_t& hash, char const* bytes, size_t len, bool swapOrder = false) {
if (swapOrder) {
for (size_t i = len; i > 0; --i)
fnv_hash32_next(hash, bytes[i - 1]);
} else {
for (size_t i = 0; i < len; ++i)
fnv_hash32_next(hash, bytes[i]);
}
}
inline void fnv_hash32_next(uint32_t& hash, char byte) {
hash ^= byte;
hash *= 16777619u;
}