0

So I got a c++ assignment in which you as a player move through randomly generated locations. The total number of locations is 27 and the movement is performed with a throw of a dice (for example you are at the location 2 and you get 6 on a dice, you move to location 8). And there would be three types of locations randomly assigned to a spot at the start of the game (location 1 - type 1, location 2 - type 3, and so on...). And at the initialization, you need to get exactly 14 locations of type 1, 5 locations of type 2, and the rest are type 3. here is what I came up with so far:

#include <string>
#include <iostream>
#include <stdio.h>      
#include <stdlib.h>     
#include <time.h> 
using namespace std;

// movement and display

string field[28][28];
int moveVal;
int count2;
int count1;

// *** C L A S S E S ***

class location {

};

class monster {
public:
    int health;
};

class player
{
public:
    int playerPosition = 0;
};


// *** F U N C T I O N S ***

void gameInit(player &Knight)
{
    int loc1 = 0;
    int loc2 = 0;
    int loc3 = 0;
    int maxVal = 3;
    int minVal = 1;

    Knight.playerPosition = 0;


    string locStringVal;


    for (int a = 0; a < 28; a++)
    {

        int locVal = 0;

        locVal = minVal + rand() % maxVal;

        cout << locVal << endl;

        if (locVal == 1)
        {
            loc1 += 1;
        }

        if (locVal == 3)
        {
            loc2 += 1;
        }

        if (locVal == 2)
        {
            loc3 += 1;
        }

        if (loc1 > 14)
        {
            minVal = 2;
        }
        if (loc2 > 5)
        {
            maxVal = 2;
        }

    }

}


// Generates random number to move the player and stores the position of the player
void randNum(player &Knight)
{

    srand(time(NULL));

    moveVal = rand() % 6 + 1;

    Knight.playerPosition += moveVal;


}

void display(player &Knight,int &count2, int &count1)
{

    for (count2 = 0; count2 < 28; count2++)
    {
        field[0][count2] = "*";


    }

    field[0][27] = "B";
    if (Knight.playerPosition > 27)
    {
        Knight.playerPosition = 27;
    }
    field[0][Knight.playerPosition] = "P";


    for (count1 = 0; count1 < 28; count1++)
    {
        cout << field[0][count1] << " ";
    }

}



void gameLoop(player &Knight)
{
    char hui;
    bool pidaras = true;

    gameInit(Knight);

    while(pidaras == true)
    {

        randNum(Knight);

        display(Knight, count1, count2);

        cin >> hui;
    }
}


int main()
//1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
{
    srand(time(NULL));
    player Knight;

    gameLoop(Knight);

}

The script that I came up with works, but sometimes it generates too many "2s" and messes up the whole code. If you run it you can see the numbers generated.

Pete Fordham
  • 2,278
  • 16
  • 25
  • 4
    Make an array with 14 1s, 5 2s and N 3s. Then [`std::shuffle`](https://en.cppreference.com/w/cpp/algorithm/random_shuffle) the array. – user4581301 Feb 07 '20 at 00:33
  • Thank you for your answer. Is it possible to shuffle only one row in a 2d array? – Nikelangelo Feb 07 '20 at 01:19
  • Do you really need all that explanation to ask why your (pseudo-)random number distribution is not what you desire? Could you be more specific/concrete as to what constitutes "too many `2s`"? – JaMiT Feb 07 '20 at 02:23
  • 1
    Sure you can shuffle a single row. Just use ptrs to the first element and one past the last element of the row you want to shuffle instead of the usual `begin()` and `end()` Better yet, use `std::array` and the usual conventions for collections. – doug Feb 07 '20 at 05:52

1 Answers1

0

I believe the fundamental problem here is that you are calling srand every time you want to create a random number.

srand set your random series, while rand pick one number of that series. The classic rand implementation is not the best, but should generate a balanced enough series.

The problem is your are not picking numbers of this kind of balanced series, you are picking the first number again and again of different series. This way you have no guarantees of balanced distribution.

Use srand() once, rand() many.

May I also suggest a C++11 approach.

#include <rand>

Fist, you can create a random number generator whit a seed.

std::mt19937 rand_gen(time(0));

Then now you create a given distribution.

std::uniform_int_distribution<uint32_t> series_1_6(1,6);

And then you can finally get your number.

std::cout << series_1_6(rand_gen) << std::endl;

Here you have some good links:

Random number generation in C++11: how to generate, how does it work?

How to generate a random number in C++?

Giuliano
  • 1
  • 2