15.1: Uzyskiwanie liczb losowych do zastosowania w grze

Cele lekcji

Po zakończeniu tej lekcji…

  • Będziesz potrafić generować liczby losowe w prosty i poprawny sposób.

 

Jak w wielu grach, tak i w naszej potrzebne są liczby losowe.

Za ich pomocą można określać obrażenia zadane przez potwora i rany zadane przez gracza oraz jakie przedmioty z tabeli łupów otrzymamy po zabiciu potwora.

Jednak z liczbami losowymi związana jest jedna kwestia, o której trzeba pamiętać.

Platforma .Net Framework jest wyposażona w klasę „Random” pozwalającą generować liczby losowe, jednak wartości dostarczane przez nią nie są do końca losowe. W naszej prostej grze nie jest to problemem, ale jeśli chcesz stworzyć poważną grę, to zdecydowania musisz zastosować lepszą metodę.

Problem z tą lepszą metodą jest taki, że wymaga ona złożonych obiektów i logiki do wygenerowania potrzebnych liczb, a operacje te są stanowczo zbyt skomplikowane, abym opisywał je w podręczniku dla początkujących. Ba, niektóre z nich są trudne nawet dla doświadczonych programistów.

Więc jeśli chcesz użyć lepszej metody generowania liczb losowych, to musisz uwierzyć mi na słowo, że ona działa.

Poniżej zamieszczam obydwie metody, a Ty wybierz jedną z nich.

 

Tworzenie generatora liczb losowych

 

Etap 1: Uruchom aplikację Visual Studio i otwórz swoje rozwiązanie.

 

Etap 2: Prawym przyciskiem myszy kliknij projekt Engine i dodaj nową klasę RandomNumberGenerator.cs.

 

Etap 3: Wybierz metodę i wklej poniższy kod do klasy RandomNumberGenerator.

Metoda prosta:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Engine
{
    public static class RandomNumberGenerator
    {
        private static Random _generator = new Random();

        public static int NumberBetween(int minimumValue, int maximumValue)
        {
            return _generator.Next(minimumValue, maximumValue + 1);
        }
    }
}

 

W prostej metodzie tworzymy obiekt Random (_generator) i za pomocą metody Next() uzyskujemy wartość losową w przedziale od wartości minimalnej do maksymalnej z zakresu przekazanego do parametru.

 

Metoda złożona:

using System;
using System.Security.Cryptography;

namespace Engine
{
    // This is the more complex version
    public static class RandomNumberGenerator
    {
        private static readonly RNGCryptoServiceProvider _generator = new RNGCryptoServiceProvider();

        public static int NumberBetween(int minimumValue, int maximumValue)
        {
            byte[] randomNumber = new byte[1];

            _generator.GetBytes(randomNumber);

            double asciiValueOfRandomCharacter = Convert.ToDouble(randomNumber[0]);

            // We are using Math.Max, and substracting 0.00000000001,
            // to ensure "multiplier" will always be between 0.0 and .99999999999
            // Otherwise, it's possible for it to be "1", which causes problems in our rounding.
            double multiplier = Math.Max(0, (asciiValueOfRandomCharacter / 255d) - 0.00000000001d);

            // We need to add one to the range, to allow for the rounding done with Math.Floor
            int range = maximumValue - minimumValue + 1;

            double randomValueInRange = Math.Floor(multiplier * range);

            return (int)(minimumValue + randomValueInRange);
        }
    }
}

 

W tej metodzie korzystamy z wystąpienia klasy szyfrującej (RNGCryptoServiceProvider). Za pomocą tej klasy łatwiej jest uzyskać niepowtarzające się ciągi liczb losowych, chociaż wymaga ona większej liczby obliczeń do uzyskania wartości w ramach określonego przedziału.

 

Podsumowanie

Umiesz już tworzyć liczby losowe,

które w naszej prostej grze występują w kilku miejscach. Powyższe informacje mogą być użyteczne, jeśli będziesz chcieć dodać kolejne funkcje.

 

Łącza do tej lekcji

Kod źródłowy w serwisie GitHub

Kod źródłowy w serwisie Dropbox

UWAGA: Kod zawiera obydwie wersje klasy (prostą i złożoną). Utwórz więc tylko jedną klasę RandomNumberGenerator i skopiuj do niej kod tylko jednej z wersji.

Leave a Reply

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