在项目开发中,有时需要用到随机数生成器。用Win自带的接口或项目所依赖的底层模块(如:cocos2d-x引擎中的CC_RANDOM_0_1之类的)的确也能生成相应的随机数。但它们有一定的局限性。Win自带的API不支持跨平台,cocos2d-x引擎支持的随机数服务端就“没办法用”(其实用是可以用,但一般我们不会这么用。原因就好比:你开发一个手游项目时,让客户端引入boost库一个道理)。所以最好是能够有一个随机数生成算法,不但能生成随机数,还能支持跨平台,并且库不能太大,效率要能跟的上。还有最最重要的一点:必需要能够“重现”(所库能重现,是指相同的初始化输入需要能够得到相同的结果输出)。这点非常重要,因为在有些项目中,特别如游戏项目中,对于战斗是经常需要重放的。如果不能保证这点,则录像就完法使用随机数,进而导致战斗与录像必不一致。下面是个符合上述限制要求的一个不错的随机数生成器库可供参考使用:
1 class mtrandom { 2 public: 3 mtrandom() : 4 left(1) { 5 init(); 6 } 7 explicit mtrandom(unsigned int seed) : 8 left(1) { 9 init(seed); 10 } 11 mtrandom(unsigned int* init_key, int key_length) : 12 left(1) { 13 int i = 1, j = 0; 14 int k = N > key_length ? N : key_length; 15 init(); 16 for (; k; --k) { 17 state[i] = (state[i] ^ ((state[i - 1] ^ (state[i - 1] >> 30)) 18 * 1664525UL)) + init_key[j] + j; // non linear 19 state[i] &= 4294967295UL; 20 ++i; 21 ++j; 22 if (i >= N) { 23 state[0] = state[N - 1]; 24 i = 1; 25 } 26 if (j >= key_length) 27 j = 0; 28 } 29 for (k = N - 1; k; --k) { 30 state[i] = (state[i] ^ ((state[i - 1] ^ (state[i - 1] >> 30)) 31 * 1566083941UL)) - i; 32 state[i] &= 4294967295UL; 33 ++i; 34 if (i >= N) { 35 state[0] = state[N - 1]; 36 i = 1; 37 } 38 } 39 state[0] = 2147483648UL; 40 } 41 void reset(unsigned int rs) { 42 init(rs); 43 next_state(); 44 } 45 unsigned int rand() { 46 unsigned int y; 47 if (0 == --left) 48 next_state(); 49 y = *next++; 50 y ^= (y >> 11); 51 y ^= (y << 7) & 0x9d2c5680UL; 52 y ^= (y << 15) & 0xefc60000UL; 53 y ^= (y >> 18); 54 return y; 55 } 56 int getRandInt(int min, int max) 57 { 58 if (min == max) 59 return min; 60 if (min > max) 61 return rand() % (min - max + 1) + max; 62 else 63 return rand() % (max - min + 1) + min; 64 } 65 double real() { 66 return (double) rand() / 0xffffffffUL; 67 } 68 double res53() { 69 unsigned int a = rand() >> 5, b = rand() >> 6; 70 return (a * 67108864.0 + b) / 9007199254740992.0; 71 } 72 void init(unsigned int seed = 19650218UL) { 73 state[0] = seed & 4294967295UL; 74 for (int j = 1; j < N; ++j) { 75 state[j] = (1812433253UL * (state[j - 1] ^ (state[j - 1] >> 30)) 76 + j); 77 state[j] &= 4294967295UL; // for >32 bit machines 78 } 79 } 80 private: 81 void next_state() { 82 unsigned int* p = state; 83 int i; 84 for (i = N - M + 1; --i; ++p) 85 *p = (p[M] ^ twist(p[0], p[1])); 86 for (i = M; --i; ++p) 87 *p = (p[M - N] ^ twist(p[0], p[1])); 88 *p = p[M - N] ^ twist(p[0], state[0]); 89 left = N; 90 next = state; 91 } 92 unsigned int mixbits(unsigned int u, unsigned int v) const { 93 return (u & 2147483648UL) | (v & 2147483647UL); 94 } 95 unsigned int twist(unsigned int u, unsigned int v) const { 96 return ((mixbits(u, v) >> 1) ^ (v & 1UL ? 2567483615UL : 0UL)); 97 } 98 static const int N = 624, M = 397; 99 unsigned int state[N]; 100 unsigned int left; 101 unsigned int* next; 102 };
下面是先前的一个框架中对其使用的封装:
1 /****************************************************************************** 2 3 === I'm jacc.kim === 4 5 创建日期: 2016年1月14日 8时51分 6 文件名称: GFRandomCreator.h 7 说 明: 随机数生成器 8 9 当前版本: 1.00 10 作 者: jacc.kim 11 概 述: 12 13 ******************************************************************************/ 14 #pragma once 15 16 #include "Framework/Foundation/GFHeader.h" 17 #include "Framework/ThirdParty/random/mtrandom.h" 18 19 NSGF_BEGIN 20 21 /****************************************************************************** 22 * create : (jacc.kim) [1-14-2016] 23 * summary : class GFRandomCreator.随机数生成器 24 ******************************************************************************/ 25 class GFRandomCreator 26 { 27 public: 28 // 设置种子 29 void setSeed(const GFuint32 unSeed); 30 31 // 随机生成一个数. 32 const GFuint32 rand(); 33 34 // 生成一个值在某个范围内的随机数. 35 const GFint32 randRange(const GFint32 nMinValue, const GFint32 nMaxValue); 36 37 public: 38 GFRandomCreator(); 39 ~GFRandomCreator(); 40 41 protected: 42 GFRandomCreator(const GFRandomCreator&) DELETE_METHOD; 43 GFRandomCreator& operator=(const GFRandomCreator&) DELETE_METHOD; 44 45 private: 46 mtrandom m_RandInstance; 47 48 };//class GFRandomCreator 49 50 NSGF_END
1 #include "Framework/Foundation/GFRandomCreator.h" 2 3 NSGF_BEGIN 4 5 /////////////////////////////////////////////////////////////////////////////// 6 // class GFRandomCreator 7 GFRandomCreator::GFRandomCreator() { 8 9 } 10 11 GFRandomCreator::~GFRandomCreator() { 12 13 } 14 15 void GFRandomCreator::setSeed(const GFuint32 unSeed) { 16 m_RandInstance.reset(unSeed); 17 } 18 19 const GFuint32 GFRandomCreator::rand() { 20 return m_RandInstance.rand(); 21 } 22 23 const GFint32 GFRandomCreator::randRange(const GFint32 nMinValue, const GFint32 nMaxValue) { 24 return m_RandInstance.getRandInt(nMinValue, nMaxValue); 25 } 26 27 NSGF_END