creating multiple objects with array of structures having unique random numbers - c++

I am trying to create different objects, each with an array of structures of numbers with random values. After compiling I am getting the same sequence of number inside the arrays of every object.
Is there a way to create different objects with unique sequences of numbers inside the arrays?
#include <iostream>
#include <time.h>
#include <stdlib.h>
using namespace std;
struct storeTwoValue
{
int x;
int y;
};
class practice{
public:
storeTwoValue storageArray[10];
void valueGenerator()
{ srand(time(NULL));
for (int i = 0; i< 10; i++)
{
storageArray[i].x = rand()%10 +1;
storageArray[i].y = rand()%7 + 1;
}
}
void print()
{
cout<<"x"<<" "<<"y"<<endl;
for (int i = 0; i< 10; i++)
{
cout<<storageArray[i].x <<" ";
cout<< storageArray[i].y << endl;
}
cout<<endl;
}
};
int main()
{
for(int i=0; i<3; i++)
{ practice A;
A.valueGenerator();
A.print();
}
return 0;
}

Move the srand() call into main, i.e. execute it only once.
The way you are using it, it gets called in too short order for each object, at least if you create/initialise them all at start. I.e. they get all initialised while time(0) gives identical seeds, which means that the pseudo random number generator is basically reset (starting same sequence from same initial value).
To verify this, you can (before moving the srand call) extend your loop. If it takes enough time, so that time(0) reliably has different values, you will see groups of objects with same values within the groups, but different across groups.
Calling srand() should be done exactly once, calling it more often does not improve randomness.

Related

Trying to stick randomly generated numbers into an array

I'm working on a project currently that involves taking randomly generated numbers, putting them into an array, then using that array throughout the entire program. It's basically supposed to be a number version of wordle. What I'm stuck on right now it trying to make the function to array connection work, and I don't know what I'm doing wrong.
I'm in a beginner course for programming, so I'm probably making a lot of dumb mistakes. The purpose of the function is to generate 5 random numbers between 0 and 9. The I'm supposed to take those numbers and stick then into an array. Then the array needs to be saved so it can be used for a game.
#include <iostream>
#include <random>
#include <chrono>
#include <array>
using namespace std;
//using std::array;
int getRandomDigit() {
std::random_device randomSource;
unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
std::default_random_engine engine(seed);
std::uniform_int_distribution<int> uniformDist(0,9);
//for (int i = 0; i < 5; i++) {
int digits[5] = {getRandomDigit(),getRandomDigit(),getRandomDigit(),getRandomDigit(),getRandomDigit()};
return digits[5];
}
//for (int i = 0; i < 5; i++) {
//int randArray[5] = {getRandomDigit(),getRandomDigit(),getRandomDigit(),getRandomDigit(),getRandomDigit()};
int main()
{
//for (int i = 0; i < 5; i++) {
//int randArray[5] = {getRandomDigit(),getRandomDigit(),getRandomDigit(),getRandomDigit(),getRandomDigit()};
//}
cout << digits[1] <<endl;
return 0;
}
This is what I have so far. I compile it, and it gives me an error of "'digits' was not declared in this scope". I'm honestly very lost on how to make this work. The random number generator was given to us by our instructor
Your compilation error "'digits' was not declared in this scope" is because you are using digits in your main function without declaring it first. You only have it declared in getRandomDigit(). Declare your array in main() instead and set it to values that are returned from getRandomDigit(). Additionally, you can not return an array in C++ directly. Focus on returning a single int from the getRandomDigit() function and populating your array in main().

Adding together two arrays and print into third array

Before I start I must notice that I am a begginer in C++.
I have a code (see below), In this code I have two arrays with 10 random numbers but In tab_A numbers are the same like in tab_B - I don't know how to solve this. Also I don't know how to merge/add/sum these two arrays in new array tab_C and print result.
#include <iostream>
#include <cstdio>
#include <time.h>
#include <cstdlib>
using namespace std;
int gen() {
return rand() % 11;
}
int main()
{
int tab_A[10];
cout<<"TABLICA A DEBUG"<<endl;
srand (time(NULL));
for (int i=0; i<10; i++)
{
tab_A[i] = gen();
cout<<tab_A[i]<<endl;
}
int tab_B[10];
cout<<"TABLICA B DEBUG"<<endl;
srand (time(NULL));
for (int i=0; i<10; i++)
{
tab_B[i] = gen();
cout<<tab_B[i]<<endl;
}
int tab_C[10];
cout<<"TABLICA C DEBUG"<<endl;
int sumAB=0;
sumAB=tab_A[10]+tab_B[10];
tab_C[10]=sumAB;
cout<<tab_C[10]<<endl;
return 0;
}
In the code, you have called srand twice with the same seed. Hence, the numbers that will be randomly generated will be the same. If you want to generate random numbers it is advisable to set seed only once.
Also, there seems to be an issue in the code. C++ has 0-indexing. Hence, the lines
sumAB=tab_A[10]+tab_B[10];
tab_C[10]=sumAB;
cout<<tab_C[10]<<endl;
will give errors.
As the size of tab_C is 10 so the index of the last element would be 9.

Roll 2 dice 1000 times

My professor asked us to write a program that:
uses a loop to simulate the rolling of a pair of dice one thousand times(Here I think a for loop would be useful).
With each iteration, the loop needs to count the number of times each value from 2 to 12(Here I am thinking if/else statements would apply)
When the loop ends, must display the number of times each value(from 2 to 12) occurred.
He has the assignment structured like so:
He wants us to use a function that goes into the 1000-time for loop, that calls ANOTHER function TWO TIMES per function call(to simulate two dice being thrown).
Let me explain what I have managed to put down
//
// main.cpp
// RollingDice
#include <iostream>
#include <ctime>
using namespace std;
int roll();
int rollDice();
int main(int argc, const char * argv[])
{
for (int i = 1; i < 1000; i++)
{
rollDice(); //This is the function that is supposed to call the roll();
//function two times. This makes sense to me that TWO DICE
//are being rolled 1000 times.
}
int result; //These two statements was where I was just hoping for something
//to work. I put these variable statements outside of the for
//loop because I was thinking that the int rollDice(); function
//definition(below) wouldn't know how to use it otherwise. I
//know that doesn't make sense, but I just can't explain why.
result = rollDice();
}
int roll()
{ //This function was provided to us by my professor.
static bool randomInitialized = false;
int points;
if (!randomInitialized)
{
srand((unsigned int) time(NULL));
randomInitialized = true;
}
points = (rand() % 6) + 1;
return points;
}
int rollDice()
{ //This I wrote myself. I'm imagining this is how you call a function twice.
//The return statement in this function was my attempt of returning the sum
//of the values of the two dice.
roll();
roll();
return result;
}
Besides this part of the program not working, the other issue I still have is determining a way to have a counter for each value that occurs(however, I am imagining that that part of the program belongs in the for loop. that's about all I know though.). I have thinking deeply about this program since yesterday. I came back to it today hoping a fresh mind would solve it, but I'm still struggling. Any and all help is greatly appreciated.
The expression roll() evaluates to a number. To add numbers, we use +. To return a value, we use return.
Putting that together, we get a simple function to sum two rolls
int rollDice() { return roll() + roll(); }
If you have a numbered sequence of things, and the numbers are both close together and start near 0, one of the standard library's SequenceContainers is an appropriate holder for the whole sequence.
Here the things are counts for a particular throw. We know up front exactly the available values (2 - 12 inclusive), so std::array is appropriate. Any integral value that can hold at least 1000 is appropriate for a count. I choose std::size_t here.
#include <array>
#include <iostream>
int main()
{
std::array<std::size_t, 13> counts {};
This will give us 13 0s, starting at position 0
for (std::size_t i = 0; i < 1000; ++i)
{
++counts[rollDice()];
We choose which number with rollDice, and use it to select a count to increment
}
for (std::size_t i = 2; i < 13; ++i)
{
We can now loop over our results, displaying the counts
std::cout << "The count for " << i << " is " << counts[i] << std::endl;
}
}
1- Using maps to count how many times each number from 2 to 12: ( most practical)
int sumOfDice;
map <int,int> diceOccurances;
for (int i=0; i < 1000; i++)
{
sumOfDice=rollDice();
diceOccurances[sumOfDice];
// Here you are storing how many times each of the dice values occured. Here's
// how you access the map;
}
for (auto const& x : socks)
{
cout <<" Dice Total Number: " << x.first ;
cout <<" Dice Number of Occurances: "<< x.second<<endl;
}
int rollDice()
{ //This I wrote myself. I'm imagining this is how you call a function twice.
//The return statement in this function was my attempt of returning the sum
//of the values of the two dice.
int die1,die2;
die1= roll();
die2= roll();
result = die1+die2;
return result;
}
2- Using if/else ( or switch );
int two, three, four, five, six, seven, eight, nine, ten ,eleven ,twelve;
two=three=four=five=six=seven=eight=nine=ten=eleven=twelve=0;
for (int i=0; i < 1000; i++)
{
if ( rollDice()==2) two++;
if (rollDice()==3) three++;
if (rollDice()==4) four++;
// and so forth until twelve++;
}
int rollDice()
{ //This I wrote myself. I'm imagining this is how you call a function twice.
//The return statement in this function was my attempt of returning the sum
//of the values of the two dice.
int die1,die2;
die1= roll();
die2= roll();
result = die1+die2;
return result;
}
you could do something like this(needs some alteration to fit into the rest of your Proff's code)
int rollDice()
int main(int argc, const char * argv[])
{
srand(time(0));// randomly seed every time you run the code
int dice1;
int dice2;
int storageData[11];//stores the number of times the values from 2 to 12 appears;
for(int i=0; i<1000; i++)
{
dice1=rollDice();
dice2=rollDice();
int sum=dice1+dice2;
storageData[sum-2]+=1; // updates the number of times the sum has appeared.
}
cout << "the value x has appeared "<< storageData[x-2] <<" times"<< endl; // change the value of x depending on which sum number you want.
}
int rollDice()
{
int x=rand()%6+1;// rand()%6 produces a no. from 0-5. rand()%6+1 produces a number from 1-6.
return x;
}
NOTE in the above code we subtract (-2) for every element cos the sum starts from 2 and not 0.

Issue with Random Number Generator in a Class [duplicate]

This question already has answers here:
srand() — why call it only once?
(7 answers)
Closed 9 years ago.
First off this could be complete rubbish as I am new to C++ classes and have never used a random number generator before. But this is my attempt. It generates a random number between the values that I want, thats fine. but when outputting them via an array, all the random values are the same.
RandomNumberGenerator.h
#pragma once
#include <iostream>
#include <cstdlib>
#include <ctime>
class RandomNumber
{
public:
void randomNumber();
int actualRandomNumber;
};
RandomNumberGenerator.cpp
#include "RandomNumberGenerator.h"
void RandomNumber::randomNumber()
{
srand (time(NULL));
actualRandomNumber = rand() % 66 + 1;
}
Game.h
#include "RandomNumberGenerator.h"
class Game
{
private:
int myNumbers[6];
public:
void createGame();
};
Game.cpp
#include "Game.h"
void Game::createGame()
{
RandomNumber create;
std::cout << "Welcome to your game!" << std::endl;
for (int i = 0; i < 6; i++)
{
create.randomNumber();
myNumbers[i] = create.actualRandomNumber;
}
for (int i = 0; i < 6; i++)
{
std::cout << myNumbers[i] << std::endl;
}
}
main
#include "Game.h"
#include "RandomNumberGenerator.h"
int main()
{
Game play;
play.createGame();
system("pause");
return 0;
}
Thanks in advance for anyones time.
Everytime you call srand(time(NULL)), you set the starting point of your sequence depending on a value that only changes once a second, thus your number only changes once a second (independend from number of calls).
So only calling srand() once will fix your code.
Notice, that both rand() and your actualRandomNumber = rand() % 66 + 1; are really bad regarding their "randomness" (why).
Use the C++ STL instead, consider the example on the bottom of the page (you want the uniform int distribution).
Edit: Typo and link to OneC++ Talk
The pseudo random number generator starts with a certain number and then generates a sequence based on the first number.
When the first number is the same the output sequence will be the same.
To generate different sequences each time you launch your program, the idea is to use the starting time of your program relatively to a specific date in miliseconds.
So the Error in your code is that you placed the srand(time(NULL)) in the function randomnumber() and it's being called in the loop. Because the CPU is so fast the time(NULL) (the first number in the sequence) will return the same value in miliseconds. Thus your having the same sequence.
To solve this place srand(time(NULL)) in main()

C++ Program Functions

I am having trouble with my functions. When I use a function to manipulate an array, and print it and move on to the next manipulation function, it uses the array that was previously manipulated instead of the original array. For example, when my function converts every negative number to a positive, I call the next function which zeros out all even numbers, and my array prints out all zeros, instead of using the array from the original.
#include <iostream>
#include <fstream>
#include <cstdlib>
using namespace std;
#define NUMS_PER_LINE 10 // maximum numbers to be printed on each line.
int numbers[100]; // array to hold upto 100 integer numbers.
int numcnt; // actual count (<=100) of numbers in above array.
// reads file content into array
void read_array_from_file (const char filename[])
{
ifstream inpfile(filename);
if (!inpfile.is_open())
{
cout << "Can't open file : " << filename << endl;
exit(1);
}
numcnt=0; // Initialise count of read numbers
// Read numbers from the file into array.
inpfile >> numbers[numcnt];
while (!inpfile.eof()) // Read until EOF is reached.
{
numcnt++; // Got one more number from input file.
inpfile >> numbers[numcnt];
}
inpfile.close();
return;
}
// Print out all the values in the array
void print_array_content (int numsinaline)
{
int i;
for (i=0; i<numcnt+1; i++)
{
if ((i % numsinaline) == 0)
cout << endl;
cout << numbers[i] << " ";
}
cout << endl << endl;
return;
}
// calculate average
double calculate_average ()
{
int i;
float sum=0;
for (i=0; i<(numcnt-1); i++)
{
sum += numbers[i];
}
return (sum/(numcnt-1));
}
// Find numbers larger and smaller than the average.
void find_numbers_smaller_and_larger_than_average (int &larger, int &smaller, int average)
{
int i;
for (i=0; i<(numcnt-1); i++)
{
if (numbers[i] < average)
smaller++;
else if (numbers[i] > average)
larger++;
}
return;
}
// Convert negative numbers to positive in the array 'numbers'.
void convert_negative_to_positive ()
{
int i;
for (i=0; i<(numcnt-1); i++)
{
if (numbers[i] < 0)
numbers[i] *= -1;
}
return;
}
// Convert all even numbers into zero.
void zero ()
{
int i;
for (i=0; i<numcnt; i++)
{
if (numbers[i] > 0)
numbers[i] *= 0;
}
return;
}
First of all, you are using a global variable for your array, so you are never passing it to your function. When you change a global variable in the function, it changes the data in the array. You should be passing that data into the function and NOT using global variables.
Second, while(!inpFile.eof()) is bad! Don't do it.
For file streams:
std::vector<int> numbers;
std::ifstream fin("myfile");
std::copy(std::istream_iterator<int>(fin), std::istream_iterator(), std::back_inserter<vector<int> >(numbers));
Those 3 lines will read the entire file into the vector "numbers".
Third, when declaring your functions, pass the array:
void myFunction(const std::vector<int>& vec); // if you aren't going to change the vector
or
void myFunction(std::vector& vec); // if you are going to change it
and you would call it by simply:
myFunction(numbers);
" it uses the array that was previously manipulated instead of the original array."
Obviously because you have your array declared globally
int numbers[100];
Outside all functions.
When you perform one operation on this array, the element get modified and the new values will be used for next functions.
Instead of this, save of copy of your original array and then use this copy whenever you wish to work on original array
All your operations act on a single global variable, numbers. If you modify it in any of your functions its values will also change in every other occurrence.
Instead, provide a way to tell your functions which array you want to use, how many elements it contains and use several arrays. This also enables you to get rid of the global variable.
Example:
#include <iostream>
using namespace std;
typedef unsigned int array_size_t;
void print_array(int array[], array_size_t size){
for(array_size_t i = 0; i < size; ++i){
cout << array[i] << endl;
}
}
int main(){
int a1[] = {1,2,3,4};
int a2[] = {1,3,3,7,0,0,0,0};
print_array(a1,4);
print_array(a2,8);
}
Remark
If you're allowed use standard containers such as std::vector instead. The solution above is more C than C++-like.
You are using global variable. All your operation on numbers whatever index will change your certain position's value.
Another potential risk is if your input file contains more than 100 integers, you will do
inpfile >> numbers[100];
or some index number greater than 100.
which will cause a segmentation fault.
You should be very careful when using global variables
You are directly manipulating your array inside of your functions since it is defined globally, instead of passing in a copy as a parameter.
void modify(int[] array) {
//Modify copied array here
}
int main() {
int numbers[100];
int copyNumbers[100];
//Copy numbers
memcpy(copyNumbers, numbers, sizeof(numbers));
modify(copyNumbers);
//Use modified array
memcpy(copyNumbers, numbers, sizeof(numbers)); //Set back to original
modify(copyNumbers); //Modify copy again as original
}