Random Numbers and programming logic - c++

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);

Related

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';
}
}

Is this C++ Guessing Game syntactically correct?

#include <iostream>
#include <cstdlib>
using namespace std;
int main(){
int min = 1;
int max = 100;
int count = 0;
int randomint = min + (rand() % (int)(max - min + 1));
bool isCorrect = true;
while(!isCorrect){
int guess = 0;
cout << "What is your guess? " << endl;
cin >> guess;
if(guess < randomint){
cout << "Too low!" << endl;
count++;
} else if (guess > randomint){
cout << "Too high!" << endl;
count++;
} else{
cout << "Correct!" << endl;
cout << "Number of Guesses: " << count << endl;
isCorrect = true;
}
}
}
New C++ Programming. I couldn't get this to compile one IDEOne because it doesn't have the input system I need to work this program. I have to submit this for a class shortly, but given that my larger disk (where all my software was stored) was corrupted last night.
I apologize for the silliness of this question.
Yes, it is syntactically correct, but not logically, due to
bool isCorrect = true;
which prevents loop from starting, it should be
bool isCorrect = false;
and works like a charm (but it would be reasonable to initialize the random number generator by for example running srand(time(NULL));)
There are two things logically wrong in your program:
The game won't run at all, since isCorrect is initially true.
The random number generator doesn't get a seed, so rand() will return the same value on every run and randomint is always the same. You should call srand( seed ) beforehand, where seed is a unsigned (for example time(0)).*
*actually, your game will still run if you don't do this, but it's easy to beat after the first try

C++ Guess Number game crashing on other computers and infinite loop fix

// Guess my number
// My first text based game
// Created by USDlades
// http://www.USDgamedev.zxq.net
#include <cstdlib>
#include <ctime>
#include <string>
#include <iostream>
using namespace std;
int main()
{
srand(static_cast<unsigned int>(time(0))); // seed the random number generator
int guess;
int secret = rand() % 100 + 1; // Generates a Random number between 1 and 100
int tries =0;
cout << "I am thinking of a number between 1 and 100, Can you figure it out?\n";
do
{
cout << "Enter a number between 1 and 100: ";
cin >> guess;
cout << endl;
tries++;
if (guess > secret)
{
cout << "Too High!\n\n ";
}
else if (guess < secret)
{
cout << "Too Low!\n\n ";
}
else
{
cout << "Congrats! you figured out the magic number in " <<
tries << " tries!\n";
}
} while (guess != secret);
cin.ignore();
cin.get();
return 0;
}
My code runs fine on my computer but when a friend of mine tries to run it, The program crashes. Does this have to do with my coding? Also I found that when I enter a letter for a guess, my game goes into an infinite loop. How can I go about fixing this issue?
The "crash" is probably related to missing runtime libraries, which would result in an error message similar to
The application failed to initialize
properly [...]
...requiring your friend to install the missing runtime libraries, e.g.
http://www.microsoft.com/downloads/en/details.aspx?familyid=a5c84275-3b97-4ab7-a40d-3802b2af5fc2&displaylang=en
http://www.microsoft.com/downloads/en/details.aspx?FamilyID=a7b7a05e-6de6-4d3a-a423-37bf0912db84
Choose the version that matches whatever version of Visual Studio you used to develop your application, as well as the target platform.
As for your application entering an infinite loop: after entering a letter, the input stream will be in an error state and thus unusable. Code similar to the following will prevent that:
#include <limits>
...
...
...
std::cout << "Enter a number between 1 and 100: ";
std::cin >> guess;
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
Basically, the code clears the error bits and removes any remaining input from the input buffer, leaving the stream in an usable state again.

Problems with srand(), 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 :)