craylib

GetRandomValue function in Raylib giving 0 every time


I'm trying to make a snake game in Raylib. I've gotten to the stage of writing a cell (food) to the screen, this is my code:

#include "raylib.h"

#define CELLSIZE 30
#define CELLCOUNT 25

Color green = {173, 204, 96, 255};
Color darkGreen = {43, 51, 24, 255};


int main(void){

        Vector2 foodPos = {GetRandomValue(0, CELLCOUNT - 1),GetRandomValue(0, CELLCOUNT - 1)};


        InitWindow(CELLSIZE * CELLCOUNT, CELLSIZE * CELLCOUNT, "retro snake");
        SetTargetFPS(60);
        BeginDrawing();


        while (!WindowShouldClose())
        {
                BeginDrawing();
                ClearBackground(green);

                DrawRectangle(foodPos.x, foodPos.y, CELLSIZE, CELLSIZE, darkGreen);

                EndDrawing();
        }

        CloseWindow();

        return 0;
}

When I run this code the food is always in the top left corner - it just spawns the food at 0,0 every time.

This is what it looks like.


Solution

  • In your code, you are calling GetRandomValue without first calling SetRandomSeed.

    void SetRandomSeed(unsigned int seed); // Set the seed for the random number generator
    

    As of Raylib 5, there are two possible pRNGs: C's standard rand (srand), and rprand - an implementation of xoshiro128**.

    If the standard C pRNG is in use, calling rand() without first calling srand(seed) behaves as though srand(1) was called during program startup. In this situation, it is extremely likely you would see non-zero values - but since the seed is always the same (1), they would be the same values on every execution of the program.

    If rprand is in use, calling the internal rprand_xoshiro without first calling rprand_set_seed results in a pRNG with a zero-state: all numbers generated will be zero. I would hazard a guess that this is what is occurring on your system (in effect: when you call GetRandomValue before SetRandomSeed).


    InitWindow calls

    SetRandomSeed((unsigned int)time(NULL));
    

    as the last thing it does, and is often the first Raylib library function called in an application, so you can simply reorder the code:

    InitWindow(CELLSIZE * CELLCOUNT, CELLSIZE * CELLCOUNT, "retro snake");
    SetTargetFPS(60);
    
    Vector2 foodPos = {
        GetRandomValue(0, CELLCOUNT - 1),
        GetRandomValue(0, CELLCOUNT - 1)
    };
    

    As pointed out by @pmacfarlane, your coordinates, which are in the range [0, CELLSIZE) must be multiplied by CELLSIZE for the rectangle to be drawn at the correct offset.

    Additionally note that the first BeginDrawing(); (outside the loop) is erroneous.

    A working example (press SPACE to move the rectangle to a random position):

    #include <raylib.h>
    
    #define CELLSIZE 30
    #define CELLCOUNT 25
    #define RANDOM_CELL() (GetRandomValue(0, CELLCOUNT - 1))
    
    Color green = { 173, 204, 96, 255 };
    Color darkGreen = { 43, 51, 24, 255 };
    
    int main(void)
    {
        const int dim = CELLCOUNT * CELLSIZE;
        InitWindow(dim, dim, "retro snake");
        SetTargetFPS(60);
    
        Vector2 foodPos = { RANDOM_CELL(), RANDOM_CELL() };
    
        while (!WindowShouldClose()) {
            if (IsKeyPressed(KEY_SPACE)) {
                foodPos.x = RANDOM_CELL();
                foodPos.y = RANDOM_CELL();
            }
    
            BeginDrawing();
            ClearBackground(green);
            DrawRectangle(foodPos.x * CELLSIZE, foodPos.y * CELLSIZE, CELLSIZE, CELLSIZE, darkGreen);
            EndDrawing();
        }
    
        CloseWindow();
    }
    

    proto-snake-gif