Lesson 15.1 – Getting random numbers for the game

Lesson Objectives

At the end of this lesson, you will know…

  • How to create random numbers – the easy way, and the good way

 

This game, like many games, needs to get random numbers.

We’ll use random numbers to determine how much damage a player does to a monster, how much damage the monster does to the player, and which items from the monster loot table the player will receive after defeating a monster.

However, there is something important that you need to consider when using random numbers.

The .Net framework has a built-in random number generating class, called “Random”. Unfortunately, it doesn’t produce numbers that are really random. In a simple game like this, that’s not a big problem. But if you were serious about building a good game, you’d want to use a better technique.

The problem with better technique is that it uses some complex objects and logic to generate the random numbers. These are way more complex than I can describe in a tutorial for beginners. In fact, some of the things in it are difficult for advanced programmers to understand.

So, if you want to use the better version, you’ll just have to take my word that it works.

I have both versions below. You can select either one to use in your version of the game.

 

Creating a random number generator

Step 1: Start Visual Studio Express 2013 for Desktop, and open the solution.

Step 2: Right-click on the Engine project and add a new class named RandomNumberGenerator.cs.

Step 3: Decide which method you want to use, and paste the code below into the RandomNumberGenerator class.

The code for the easy way:

In the simple version, we create a Random object (_generator) and use its Next() method to get a random value between the minimum and maximum values passed in as parameter.

 

The code for the more random way:

In this version, we use an instance of an encryption class (RNGCryptoServiceProvider). This class is better at not following a pattern when it creates random numbers. But we need to do some more math to get a value between the passed in parameters.

 

Summary

Now you can create random numbers in the game.

We only use random numbers in a few places, in this simple version of the game. However, if you want to add more features, you may find this useful.

 

Source code for this lesson

Get it from GitHub: https://gist.github.com/ScottLilly/e05a5f971c1fce7ea5fe

or DropBox: Lesson 15.1 – https://www.dropbox.com/sh/kyedp4e80scafg4/AACSq2Zr1_PVJHvaGpW-KY3Ua?dl=0

NOTE: This has the code for both versions of the class, the simple one and the complex one. Only create one RandomNumberGenerator class and copy the code from the one version that you want to use.

 

Next lesson: Lesson 16.1 – Writing the function to move the player

Previous lesson: Lesson 14.3 – Foreach loops

All lessons: Learn C# by Building a Simple RPG Index

16 thoughts on “Lesson 15.1 – Getting random numbers for the game

  1. Sanity Check!

    In the first “easy way” example, is it not true that the parameter of “maximumValue”  for the NumberBetween function will never actually return that maximum value?( this is what I have found)

    IE… if you wanted a number between 1-10, your input parameters should be 1-11, or the return value function call should be…
    return _generator.Next(minimumValue, maximumValue+1);

    If this is True, does this also apply to the “more random way”?
           

    1. Aaaarrgh! You’re right about the “easy” one. That was missing a “+ 1”. The “complex” one has the “+ 1” on line 25, to take care of that problem. I always use the complex one, and that’s the one I’ve tested. I’ve corrected the code.

      Thanks for catching that one.

  2. Not sure where to post this question, but its related to the RNG so i’ll just post it here.

    I am trying to create a spawn chance for monsters and include more than one monster at a location. An example would be I have a location: Castle Field, that has 2 monsters: Bear and Wolf. The wolf has a 60% chance to spawn (rng < 60 = spawn) and the bear has a 40% chance to spawn (rng < 40 = spawn). But I only want one monster to spawn at a time and I would like the random spawn to continue after a monster is killed (so I wouldn’t keep getting bear’s). Any help? I already have a property set up in the monster class called spawnRate.

    From my own thoughts on the subject I would place this random spawn thingy in two places (im thinking its just gonna be an if statement, however if you think there is a better way please share). Those two places are in the creation of the location in the world class or in the moveto function in the superadventure class.

     

    Thanks for all the help!

    1. I started work on this feature in a larger version of this game – which I will get back to working on next month.

      Look at the Location class here: https://github.com/ScottLilly/ScottsOpenSourceRPG/blob/master/Engine/Entities/Location.cs
      You can add potential monsters to a location, with their chance of appearance, with the AddPotentialMonster() function. This saves them to a RandomDistributionList variable – a custom class I wrote to easily manage getting a random item from a weighted/percentage list.

      If you use this method, you would also need to include the RandomDistributionList class (https://github.com/ScottLilly/ScottsOpenSourceRPG/blob/master/Engine/Collections/RandomDistributionList.cs) in your Engine project (and change its namespace from “Engine.Collections” to “Engine”)

      Let me know if that makes sense, and if you have any trouble adapting your project to use this technique (or if you try some other way).

  3. What is about the performance?

    I use the seed to bring a little bit more “random” to the value…

    private static Random _generator = new Random((int)DateTime.Now.ToBinary());

    1. In this situation, the difference in performance is not noticeable.

      Sometimes, you have several ways to do something and need to consider which one is best for the program. For this program, we don’t need to worry about performance, because it is a turn-based, single-player game. We also don’t need to have a powerful random number generator, like you would if you wrote an online casino program where people gambled with real money. So, you can use several different options, including using a datetime seed.

    1. Hello Bandi,

      We did not really need to do this as a static method. I just didn’t want to instantiate a new object every time the game needed a random number. With a static method, you do not need to instantiate an object, to use the method. This is similar to getting the current date by calling “DateTime.Now”, without needing to instantiate a DateTime object. Because the NumberBetween method is static, all class-level variables it uses (_generator) also need to be static.

      If this was not static, the code to get a random number would look like this:
      RandomNumberGenerator randomGenerator = new RandomNumberGenerator();
      int randomValue = randomGenerator.NumberBetween(1, 2);

      Because it is static, we can get a random number with one line:
      int randomValue = RandomNumberGenerator.NumberBetween(1, 2);

      If this was a bigger program, or had many users, the static method would also help improve the performance (instantiating objects is relatively slow).

      Please tell me if that did not answer your question.

      1. Hello Scott,

        Thanks a lot for your answer, I understand it all now, it helped me a lot to understand the working of ‘static’.

  4. I’ve already posted a comment talking about this on the index, yet i’ll ask here as i’m really curious.

    Why did you make a class just to hold one method? You could’ve placed the method inside the “World” class. Is there a reason for that?

    1. Normally, a class with one method is not good. However, I put this method in its own class for a few reasons.

      1. There is something called the “Single Responsibility Principle” – where each class should be responsible for one thing. Even with a larger class, such as the Player class, its “single responsibility” is to maintain the player’s “state” (information/status).
      2. A game will need random numbers in several different places (classes). I don’t want to duplicate this method in each class. Now, every other part of the program can use this single class/method, to generate random numbers.
      3. This is also a method I might need in other programs. Because it is in its own class, I can easily copy it to another program, and use it there. If I had the function in a larger class, I would need to remember which “using” statements need to be copied, if I ever copied the method to another project.

      Does that make it clearer?

Leave a Reply

Your email address will not be published. Required fields are marked *