Problems with srand(), C++ - c++

I'm trying to write a program that generates a pseudorandom numbers using a seed. However, I'm running into problems.
I get this error
39 C:\Dev-Cpp\srand_prg.cpp void value not ignored as it ought to be
Using this code
#include <iostream>
#include <iomanip>
#include <sstream>
#include <limits>
#include <stdio.h>
using namespace std ;
int main(){
int rand_int;
string close ;
close == "y" ;
cout << endl << endl ;
cout << "\t ___________________________________" << endl ;
cout << "\t| |" << endl ;
cout << "\t| Pseudorandom Number Game! |" << endl ;
cout << "\t|___________________________________|" << endl ;
cout << endl << endl ;
while ( close != "y" ){
rand_int = srand(9);
cout << rand_int << endl ;
cout << " Do you wish to exit the program? [y/n] " ;
cin >> close ; }
}

srand doesn't return a random number, it just reseeds the random number generator. Call rand afterwards to actually get a number:
srand(9);
rand_int = rand();

srand() generates a seed (which is the number used to initialize the random number generator) and must be called once per process. rand() is the function you are looking for.
If you don't know what seed to pick, use the current time:
srand(static_cast<unsigned int>(time(0))); // include <ctime> to use time()

call it this way.
srand(9);
rand_int = rand();

You're using srand incorrectly, that particular function is for setting the seed for later calls to rand.
The basic idea is to call srand once with an indeterminate seed, then call rand continuously to get a sequence of numbers. Something like:
srand (time (0));
for (int i = 0; i < 10; i++)
cout << (rand() % 10);
which should give you some random numbers between 0 and 9 inclusive.
You generally don't set the seed to a specific value unless you're testing or you want an identical sequence of numbers for some other reason. You also don't set the seed each time before you call rand since you're likely to get the same number repeatedly.
So your particular while loop would be more like:
srand (9); // or use time(0) for different sequence each time.
while (close != "y") { // for 1 thru 9 inclusive.
rand_int = rand() % 9 + 1;
cout << rand_int << endl;
cout << "Do you wish to exit the program? [y/n]? ";
cin >> close;
}

srand returns void function and doesn't return a value.
Here you can see more about it. You'll just have to call srand(9) and get the value of rand() after that, like J-16 SDiZ pointed out, who will be upvoted for this :)

Related

How can I stop C++ program?

I made a program that prompts the user to guess numbers (which I have programmed to produce a random number)ranging from 1-10, if the user guesses the number successfully which is the same as the random number generated it prints "congratulation", else it prompts the user to try again. but I want to stop the user from answering after a certain amount of time(like Game Over). But the prompt keeps coming, I tried using the break in my while loop but it doesn't work, I also tried using the exit function, which actually stopped the program from running but it stopped it after answering 2 times which is not what I want.
#include <iostream>
#include <cmath>
#include <cstdlib>
#include <ctime>
using namespace std;
int main() {
int a,b,c,d,e,f;
// generate a random number, prompt the user for any number if the users guess is in line with the random number generated the user wins else try again
//generate a random number between 1 - 10 store it in a variable
cout << "Random Number Generator \n \n";
srand(time(0));
for(int i = 1; i == 1; i++){
a = 1+(rand() % 10);
cout << a << endl;
}
//prompt the user for numbers ranging from 1 - 10
cout << "type in a number from (1 - 10)\n";
cin >> b;
c++;
//check if the number is the same as the random number
//this checks to see if the user gets the question, else it continues running till he gets it
while(a != b){
cout << "You're incorrect!\n";
cout << "type in a number from (1 - 10)\n";
cin >> b;
while(b <= 3){
exit(3);
}
}
//print result
if(a == b){
cout << "congratulations";
}
return 0;
}
how can I make this work?
You could count the number of times the user answers and stop when it has executed for the number of times you want.
//prompt the user for numbers ranging from 1 - 10
cout << "type in a number from (1 - 10)\n";
cin >> b;
int answer_count = 1; // variable to count answers (there is already 1 answer here)
const int max_attempts = 10; // number of attempts the user has
//check if the number is the same has the random number
//this checks to see if the user gets the question, else it continues running till he gets it
while(a != b){
cout << "You're incorrect!\n";
cout << "type in a number from (1 - 10)\n";
cin >> b;
answer_count++; // count this new answer
if (answer_count >= max_attempts){ // check if the count reached the "certain amount of time"
break; // exit from this loop
}
}
Alternatively, you could also give the user a certain amount of time to guess. For example, 10 seconds. This can easily be achieved using the C++ chrono library:
#include <chrono>
#include <iostream>
#include <random>
int main(int argc, char **argv)
{
const int max_time = 10; // seconds
const int min_secret = 1;
const int max_secret = 10;
// This generates a random number between min_secret and max_secret using the STL random library
std::random_device r;
std::default_random_engine e(r());
std::uniform_int_distribution<int> uniform_dist(min_secret, max_secret);
int secret = uniform_dist(e);
auto start = std::chrono::system_clock::now();
int guess;
do {
std::cout << "Type a number from (1 - 10)\n";
std::cin >> guess;
if (guess == secret)
break;
std::cout << "Your guess is incorrect!\n";
// See if the time elapsed since the start is within max_time
auto now = std::chrono::system_clock::now();
auto elapsed_time = std::chrono::duration_cast<std::chrono::seconds>(now - start);
if (elapsed_time.count() > max_time) {
std::cout << "You ran out of time.\n";
exit(0);
} else {
std::cout << "You still have " << max_time - elapsed_time.count() << " seconds left\n";
}
} while (guess != secret);
std::cout << "Your guess was correct, congratulations!";
}
Note that the time check is only performed after the user tried to guess, so if the time limit is 10 seconds and the user waits 30 to type, it will still allow. To kill the program entirely with a timer in C++, you could use the thread library to spawn a second thread that handles the elapsed time, or even use an interruption based scheme (see https://stackoverflow.com/a/4001261/15284149 for an example of timer).
Also, note that the user input is not sanitized, and if the user writes anything other than a number your program has undefined behavior.
You need to fix up several things in your code:
The variable c is kept uninitialized and incremented later to use nowhere. Remove this. Note that d, e, f are unused as well.
In the loop:
for(int i = 1; i == 1; i++) {
a = 1 + (rand() % 10);
cout << a << endl;
}
You have told the compiler to iterate until i == 1, increment it by one, it is only done once – and that you might not want to do but i < 10.
Also, You are not using an array to store those 10 random numbers, but the last one. You need to make an array of 10 rooms and assign it to each of them:
int a[10];
// Since the array index begins at zero
for (int i = 0; i < 10; i++) {
a[i] = (rand() % 10) + 1;
cout << a[i] << endl;
}
After the successful assignment, it's time to introduce a randomly chosen index as the right answer (it should be put before the while loop):
// To choose the random index
int shuffle = a[rand() % 10];
Also, replace the congratulating statement:
// It was a == b previously
if (shuffle == b)
cout << "congratulations";
Lastly, to quit after three incorrect attempts, replace the while loop:
int count = 0;
while (shuffle != b) {
count++;
cout << "You're incorrect!\n";
cout << "type in a number from (1 - 10)\n";
cin >> b;
if (count == 2) {
cout << "Game Over" << endl;
exit(0);
}
}

Issues with rand and srand

I'm making a program to get the average number of dice rolls to get a 6, but there seems to be an issue with the RNG. I suspect it's the seed, as while the number is different each time I compile and run the code, it doesn't change in each individual attempt, so the average doesn't change. Heres my code:
#include <iostream>
#include <cstdlib> // random numbers header file//
#include <ctime> // used to get date and time information
using namespace std;
int main()
{
int roll = 0; //declare a variable to keep store the random number
int i = 0;
int counter = 0;
int resume = 1;
int average = 0;
int totalrolls = 0;
srand(time(0)); //initialise random num generator using time
while (resume != 0) {
while (roll != 6) {
roll = rand() % 6 + 1; // generate a random number between 1 and 6
i++;
}
counter++;
totalrolls += i;
average = totalrolls / counter;
cout << "the average number of rolls to get a 6 is " << average << ", based on " << counter << " sixes." << endl;
cout << "do you wish to keep rolling? ";
cin >> resume;
cout << endl;
}
return 0;
}
Anyone got any idea what's going on?
Notice that roll only gets updated inside this loop:
while (roll != 6) {
...
}
This means that after that loop finishes running with roll set to 6, it will never run again, even if the outer loop executes another time.
To fix this, you could either
change this to be a do ... while loop so that it always executes at least once; or
manually reset roll to a value other than 6 on each iteration through the outer while loop; or
change where roll is defined so that it's local to the outer while loop and so you get a fresh copy of it per outer loop iteration, which is basically a better version of option (2).

c++ srand(time(0)) doesn't work in guessing game

I need to make a guessing game in C++, and everything works except that srand(time(0)) doesn't reset the number after the user wants to play again. I also can't use std libraries.
Nothing I have done has worked so far. Am I doing the while loops wrong?
#include <iostream>
#include <ctime>
using namespace std;
int main()
{
//Initialize variables
int input = 0;
int playing = 1;
char yninput[2];
int count = 1;
//While the player is playing the game
while (playing == 1) {
srand(time(0));
int num = rand() % 101;
//While the player hasn't guessed the number
while (input != num) {
//Prompt the player
cout << "Enter your guess" << endl;
cout << num << endl;
cin >> input;
//If the guess is greater than the number
if (input > num) {
cout << " Your guess is too high!" << endl;
count++;
}
//If the guess is less than the number
else if (input < num) {
cout << " Your guess is too low!" << endl;
count++;
}
//If the player guesses the correct number
else {
cout << " You have guessed the number! It took you " << count << "
guess(es)! Would you like to play again?" << endl;
//Ask the play if they want to play again
cin >> yninput[2];
//If the player doesn't want to play again quit the program
if (yninput[2] == 'n') {
playing = 0;
input = num;
}
//If the player wants to play again restart the program and
randomize the number
else if (yninput[2] == 'y') {
input = 0;
count = 1;
}
}
}
}
}
As #user4581301 has pointed out, you shouldn't call srand(time(0)) more than once, as it will reset the random seed according to the current system time. If srand(time(0)) is called in rapid succession, the very big number that it will take as a seed (which I believe is the current epoch time) will be sufficiently close to the previous call that you might not observe significant difference in your RNG.
Simply moving the srand(time(0)); line out of the while loop should do the trick.
How do I get it so that when the user presses 'y' and the game resets that the random number also changes?
You get the next number in the pseudo random sequence by calling rand without calling srand in between. If you set the random sequence to start from the current timestamp on every iteration, then you get the same number which changes once a second.
I also can't use std libraries.
srand, rand, time, cout and cin are all from the standard library.
I think #Mathis has already pointed out the solution.
I am just sharing some insight as to how srand and rand are related. Consider the below code snippet:
#include <iostream>
#include <ctime>
int main()
{
int i = 0;
// Uncomment below line to generate new set of random numbers
// on every execution.
// srand(time(0));
while (i < 5)
{
std::cout<< rand() % 10 <<std::endl;
}
}
Let's say the program generates numbers - 5, 7, 3, 0 and 4 on 1st run. If you run the program again, you will see the same set of numbers, i.e, 5, 7, 3, 0 and 4. So, although they are random (pseudo random to be precise), but on every program execution, the order of numbers will be same.
This is the reason we use srand to specify some seed value. Seed is any value which is different on each execution. When we use time(0) as parameter to srand, we make sure that on every program execution, we are providing a new and unique seed. This will make sure that we get truly random set of numbers.

PRNG program failure. Cannot enter random amount of choices and will always answer with 2 from the PRNG

So as the title describes I'm trying to learn PRNG but it hasn't gone too well thusfar. I am writing a program that takes an entered number of choices, rolls a dice and makes the choice for you. I do this using rand() and an array of strings with a length that is dependant on a variable read in before the declaration of the array.
The two problems showing up are that if I try to choose between for example 12 choices, the program will crash. As I read in the length of the array before I declare it I don't understand how this could happen. Also the PRNG will always return the number 2 which is not the desired function of a function that should return a random number between min and max. I will share my code below:
#include <iostream>
#include <cstdlib> // for rand() and srand()
#include <ctime> // for time()
#include <string>
using namespace std;
int callPRNG(int min, int max)
{
srand(static_cast<unsigned int>(time(0))); // set initial seed value to system clock
static const double fraction = 1.0 / (static_cast<double>(RAND_MAX) + 1.0); // static used for efficiency, so we only calculate this value once
// evenly distribute the random number across our range
return static_cast<int>(rand() * fraction * (max - min + 1) + min);
}
int main()
{
int max=1;
int min=0;
cout << "Please enter the amount of choices you want to choose from: ";
cin >> max;
string choices[max-1];
int choiceMade=0;
{
int i=0;
while(i<=max-1)
{
cout << "Please enter choice " << i+1 << ": ";
cin >> choices[i];
i++;
}
choiceMade=callPRNG(min, max-1);
cout << "I have decided: " << choices[choiceMade-1];
}
return 0;
}
As extra information, I'm using code::blocks with C++11 enabled on a windows 10 OS. I hope someone can help me with this as I don't quite understand arrays and PRNG well enough to find the error by myself. Thanks :)
edit: It seems, as I can now use higher values for max without crashing the program, that the answer scales with the value of max.
The problem with crashing is because you're not allocating enough space for the array of choices (you need the size to be max, not max - 1). You're using a G++ extension to C++ — namely variable length arrays — which are part of standard C but not standard C++. You should use a vector of strings.
The non-random random behaviour is more a reflection on the quality of the rand() PRNG — it is often not very good. I was getting similar behaviour on macOS Sierra 10.12.2 with G++ 6.3.0. I worked around it by avoiding the use of floating point arithmetic and using modulus operations.
The use of choiceMade-1 was suspect too; given a choice of 0, it tries to access non-existent element -1 of the array of choices.
These changes yield the following code, which still has debug code in place:
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <string>
#include <vector>
using namespace std;
int callPRNG(int min, int max)
{
cout << __func__ << ": " << min << " .. " << max << "\n";
unsigned int seed = static_cast < unsigned int > (time(0));
cout << __func__ << ": " << seed << "\n";
srand(seed);
int range = max - min + 1;
int max_valid = RAND_MAX - RAND_MAX % range;
int rand_val;
while ((rand_val = rand()) > max_valid)
;
int rv = rand_val % range;
cout << __func__ << ", rand_val = " << rand_val << ", ret_val = " << rv << "\n";
return rv;
}
int main()
{
int max = 1;
int min = 0;
cout << "Please enter the amount of choices you want to choose from: ";
cin >> max;
vector < string > choices(max);
int choiceMade = 0;
int i = 0;
while (i <= max - 1)
{
cout << "Please enter choice " << i + 1 << ": ";
cin >> choices[i];
i++;
}
choiceMade = callPRNG(min, max - 1);
cout << "I have decided: " << choices[choiceMade] << endl;
return 0;
}
Sample outputs:
Please enter the amount of choices you want to choose from: 12
Please enter choice 1: a
Please enter choice 2: b
Please enter choice 3: c
Please enter choice 4: d
Please enter choice 5: e
Please enter choice 6: f
Please enter choice 7: g
Please enter choice 8: h
Please enter choice 9: i
Please enter choice 10: j
Please enter choice 11: k
Please enter choice 12: l
callPRNG: 0 .. 11
callPRNG: 1483236759
callPRNG, rand_val = 770034137, ret_val = 5
I have decided: f
Over a series of runs, with filtering out all except the 'I have decided' lines, I got outputs:
I have decided: g
I have decided: i
I have decided: d
I have decided: f
I have decided: a
I have decided: c
I have decided: l
I have decided: f
I have decided: a
I have decided: f
I have decided: h
Jonathan Leffler's answer was complete and correct. But I thought you might also be interested in a shorter program that uses <random>:
#include <vector>
#include <iostream>
#include <string>
#include <random>
size_t callRNG(size_t min, size_t max)
{
std::random_device r{};
std::uniform_int_distribution<size_t> ud{min,max};
return ud(r);
}
int main()
{
const auto min{0};
std::vector<std::string> choices{};
std::string line{};
while(std::cout << "Please enter choice: ", std::getline(std::cin, line) && !line.empty()) {
choices.push_back(line);
}
const auto max{choices.size() - 1};
if(!choices.empty()) {
std::cout << "I have decided: " << choices[callRNG(min, max)] << '\n';
}
}

Random Numbers and programming logic

I'm having trouble with the assignment below.
"Write a program that generates a random integer between 1-100 and then asks the user to guess what the number is. If the user's guess is higher than the random number, the program should display “Too high, try again.” If the user’s guess is lower than the random number, the program should display “Too low, try again.” The program should use a loop that repeats until the user correctly guesses the random number."
How do I make the random numbers work, and is there a better/more efficient way to write any parts? I'm still learning C++
Here's my code
#include <iostream>
#include <ctime>
#include <cstdlib>
using namespace std;
int main()
{
// declare variables
int rightAnswer, userAnswer;
// determine rightAnswer
srand (time(NULL));
rightAnswer = (rand() % 100) + 1;
// begin the game
cout << "I'm thinking of a number between 1-100!" << endl;
do{
// collect data
cout << "Guess: ";
cin >> userAnswer;
// if else statements to determine correctness
if (userAnswer < 1 || userAnswer > 100)
cout << "The number is in the range 1-100. Try again!" << endl;
else if (userAnswer > rightAnswer)
cout << "Too high! Try again!" << endl;
else if (userAnswer < rightAnswer)
cout << "Too low! Try again!" << endl;
else
cout << "That's it! Good job!" << endl << ":)";
} while (userAnswer != rightAnswer);
return 0;
}
In c++11 you can generate random number more uniformly in given range using correct choice of Random number distributions. One example of uniform distribution usage is shown below:
#include <random>
...
std::random_device rd; // obtain a random number
std::mt19937 engine(rd());
std::uniform_int_distribution<> distribution(1, 100); // define the range
const int rightanswer = distribution(engine);