Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Serializing java.util.Random

Tags:

java

random

I'm working on a small, simple game (mostly to learn what's new in Java 8 and JavaFX). One of the features I have is the ability to seed the game's random number generator so you can play roughly the same game as a friend on a different system (think Minecraft Maps or The Binding of Isaac games).

I would like to add the ability to save the game to be resumed at a later time. After looking over the documentation for the java.util.Random class, I can't find a way to get the current seed of the random number generator. The only ways I have come up with to restore the random number generator after saving the game is to either access the seed via reflection at save time and use that, or to seed the initial seed at load time and just call nextInt() over and over again until we've rolled forward the random number generator enough to be where it was before the game was saved.

like image 514
nlowe Avatar asked Apr 10 '15 01:04

nlowe


1 Answers

First of all, as @user2357112 points out, Random implements Serializable, and does so by writing the seed field (along with the nextNextGaussian and haveNextNextGaussian fields). Have you tried simply serializing it? That should 'just work'™. Other serializers, like Gson, also work. gson.fromJson(gson.toJson(r), Random.class); returns an identical object.

You don't necessarily need the same Random instance, just a consistent one. You could simply call nextLong() and write that value to your save file as random_seed or whatever. Then just initialize a Random instance with that seed, and now all runs loaded from that file will behave the same. If you wanted, you could even reset the Random instance in your currently running game to the same seed too.

On the other hand if you're generating maps or other seemingly-constant content randomly and want it to persist between loads, I'd think you'd do better to simply seed your Random at the start, and save that value like you describe. To save on computation you could do this in chunks smaller than a whole level. For example, split each level into 10ths, and use (and save) a different seed for each 10th. Then you just have to generate the portion the user's on now, and not the parts they've already crossed. If you were to only save the current state like you propose, the user couldn't go backwards in the map (which might not be a problem for your game in particular, but wouldn't be a great practice in general).


UX caveat: saving your game's randomness seems potentially over-engineered. As a user, I don't generally expect a save file to persist randomness. In fact, sometimes players take advantage of that, for instance if they die in a random encounter right after saving, reloading the game doesn't immediately drop them back into the same encounter. I would consider just leaving your game's Random unseeded and let each game be slightly unique.

like image 160
dimo414 Avatar answered Sep 28 '22 11:09

dimo414