How to save the state of a Random generator in C#?

前端 未结 6 662
爱一瞬间的悲伤
爱一瞬间的悲伤 2020-11-30 10:29

For testing purposes I\'m creating random numbers with a given seed (i.e. not based on the current time).

Thus the whole program is deterministic.

If someth

6条回答
  •  难免孤独
    2020-11-30 10:49

    I'm aware this question has already been answered, however, I wanted to provide my own implementation, which is currently in use for a game that I am creating. Essentially, I created my own Random class, using the code of .NET's Random.cs. Not only did I add more functionality, but I also added a way to save and load the current generator state into and from an array of just 59 indices. It is better to do it this way instead of how some other comments suggest to "Iterate x number of times to restore the state manually. This is a bad idea because in RNG heavy games your Random generator state could theoretically get into the billions of calls, meaning you would—according to them—need to iterate a billion times to restore the state of the last play session during each startup. Granted, this may still only take a second, tops, but it's still too dirty in my opinion, especially when you could simply extract the current state of the Random Generator and reload it when required, and only taking up 1 array (59 indices of memory).

    This is just an idea, so take from my code what you will.

    Here is the full source, which is much too large to post here:

    GrimoireRandom.cs

    And for anyone who just wants the implementation for the question, I will post it here.

            public int[] GetState()
            {
                int[] state = new int[59];
                state[0] = _seed;
                state[1] = _inext;
                state[2] = _inextp;
                for (int i = 3; i < this._seedArray.Length; i++)
                {
                    state[i] = _seedArray[i - 3];
                }
                return state;
            }
    
            public void LoadState(int[] saveState)
            {
                if (saveState.Length != 59)
                {
                    throw new Exception("GrimoireRandom state was corrupted!");
                }
                _seed = saveState[0];
                _inext = saveState[1];
                _inextp = saveState[2];
                _seedArray = new int[59];
                for (int i = 3; i < this._seedArray.Length; i++)
                {
                    _seedArray[i - 3] = saveState[i];
                }
            }
    

    My code is completely stand-alone, besides the DiceType enumeration, and the OpenTK Vector3 struct. Both of those functions can just be deleted and it will work for you.

提交回复
热议问题