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

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.

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

Exiting Loop using Enter(Return Key) C++

First of all thanks for answering and helping out...
Now i was making a program to let the user enter any number... and then use the program to point out the total number of 4's in the the number entered and i have now encountered a problem..
This is my first post here so please excuse me if i make any mistakes..
The Code
int main()
{
int T,i,j,l;
char N,p[10];
cin>>T;
while(T--) //The number of times a user can enter a new number
{
cout<<"\nEnter Numbers\n";
l=0;i=0;
do
{
N=getch(); //getch is used so that the enter key need not be pressed and the
//number looks like a whole and also so the each number is
//individually stored
p[i]=N; //here the number entered is stored in p
cout<<N; //to display the number obviously
l++;i++;
}while(N!=' '); //Now here between '' something has to be present so that the loop
//terminates as soon as the enter key is pressed right now as soon
//as the spacebar is hit the loop will terminate.
cout<<"\n";
j=0;
for(i=0;i<l;i++) //using l so that the loop runs accordingly
{
if(p[i]=='4')
{
j++; //for couting the number of 4's
}
cout<<p[i]<<"\n"; //wont be needing in the final program but here cout is just
// to check the output
}
cout<<"\n THERE ARE "<<j<<" FOURS\n";
}
}
Please not that i already have a solution for my program so please DO NOT provide a different code using some different logic... i really need this very same program to work.i know that this program can be made to work using string length but here i want the loop to terminate after the enter key is pressed.
Well if you want to stop getting input when the user presses enter instead of space you need to test against '\r', '\n' or '\r\n' depending on what OS you are using. That said you really should be using standard C++ if you are going to use C++. You could easily make your code like:
#include <iostream>
#include <string>
#include <algorithm>
int main()
{
int loops;
std::cout << "How many numbers to check: ";
std::cin >> loops;
std::cin.get(); // eat newline
for (int i = 0; i < loops; i++)
{
std::string numbers;
std::cout << "Enter numbers and press enter: ";
std::getline(std::cin, numbers);
auto numberOf4s = std::count(numbers.begin(), numbers.end(), '4');
std::cout << "Number of 4's entered: " << numberOf4s << std::endl;
}
return 0;
}
Live Example
You can to see check if N is equal to '\r'. So your while loop looks like
do
{
N=getch(); //getch is used so that the enter key need not be pressed and the
//number looks like a whole and also so the each number is
//individually stored
p[i]=N; //here the number entered is stored in p
cout<<N; //to display the number obviously
l++;i++;
}while(N!='\r');

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

stuck in a infinite do while loop

I am trying to make a simple guess my number game in c++ but the computer need to guess my number. But the problem is that I am stuck in this infinite loop. I am just a beginner so it's a really basic program.
This is my code:
int secretNumber = rand() %100 + 1; // random number between 1-100
int tries=0;
int input;
cout <<"typ your number\n";
cin >> input;
do
{
cout <<secretNumber <<endl;
++tries;
if (secretNumber > input)
{
cout <<"To high i guess?\n";
}
else if (secretNumber < input)
{
cout <<"To low I guess?\n";
}
else
{
cout <<"Yes, i got it in " <<tries <<" tries!";
}
}while (input != secretNumber);
return 0;
}
place cin >> input into loop body
I think you should move the random number generation inside the loop.
The value of the variable input is never changed in the loop, so the terminating condition input != secretNumber is never met.
You should take the input inside the loop. So write cin >> input at the beginning of the loop.
Edit:
If the computer should guess, then still the value of input needs to be changed in the loop, which is not present in your code. The loop runs with the same value in input every time.
To make you computer make a guess, you should follow some scheme. The computer may draw the numbers at random - which you can get through moving secretNumber = rand()%100 + 1 inside the loop. But this approach may not perform good, the loop may still run for a very long time. This is shown in #Kaii's answer.
A more efficient approach is the Binary Search. In this case you should keep track of the guesses the computer makes. Keep two variables high and low which should store the guesses higher and lower than input respectively. Whenever a guess in higher than the number, store it in high, and store any guess lower than input in low. Then the computer should try its new guess between high and low. A random guess should be secretNumber = low + rand() % (high - low). In worst case it will take as much as 100 iterations. For the best results, each guess should be (high + low) / 2. According to the conditions, one of high and low will be updated in each iteration. This approach will ensure that the computer will guess the correct number within 7 guesses.
In your code it should be like this:
int secretNumber = rand() % 100 + 1; // random number between 1-100
int tries=0;
int input;
int low = 1, high = 100;
cout <<"typ your number\n";
cin >> input;
do
{
secretNumber = (high + low) / 2;
cout << secretNumber <<endl;
++tries;
if (secretNumber > input)
{
cout << "Too high I guess?\n";
high = secretNumber;
}
else if (secretNumber < input)
{
cout << "Too low I guess?\n";
low = secretNumber;
}
else
{
cout << "Yes, i got it in " << tries << " tries!";
}
} while (input != secretNumber);
return 0;
the computer is only guessing (by random) once when the program starts, but should guess each time the loop is iterated. you should move the random number generation inside the loop:
int secretNumber = 0;
int tries=0;
int input;
cout <<"typ your number\n";
cin >> input;
do
{
/* the fix is here */
secretNumber = rand() %100 + 1; // random number between 1-100
cout <<secretNumber <<endl;
++tries;
if (secretNumber > input)
{
cout <<"To high i guess?\n";
}
else if (secretNumber < input)
{
cout <<"To low I guess?\n";
}
else
{
cout <<"Yes, i got it in " <<tries <<" tries!";
}
}while (input != secretNumber);
return 0;
You have to do the input within the loop. Right now you prompt for a value BEFORE you start looping, then never ask the user for another number. If the guess can't be changed, the loop can never exit.
changing to
do {
cin >> input;
will solve the infinite loop.
infinite loop in your code because the argument for while always true until you get the true number.
you need to add another argument. example you want set maximal tries to 5 times. then it will be like this
do{
//do your stuff here
}while((input != secretNumber)&&(tries<=5))
when you input wrong number for 5 times, the application will finish