I am writing a simple dice game where two players play against each other. The winner is the one who gets the largest number when the dice is rolled. However, when I press enter to make a random number get generated for the first player, I just get new empty lines. Here is the code:
#include <iostream>
#include <ctime>
#include <cstdlib>
#include <string>
using namespace std;
int main()
{
srand(time(0));
int p1 = (rand() % 6) + 1;
cout << "Player 1: Press enter to roll your dice" << endl;
cin >> p1;
int p2 = (rand() % 6) + 1;
cout<<"Player 2: Press enter to roll your dice" << endl;
cin >> p2;
if(p1 == p2)
{
cout<<"You tied! \n";
}
else if(p1 > p2)
{
cout<<"You won! \n";
}
else
{
cout<<"You lost! \n";
}
}
You're trying to prompt the user for discardable action, but in-fact actually requesting they provide integer input to the console (which, inconveniently, will overwrite the random draws you just pulled).
When the stream is in a good state:
cin >> p1;
will attempt to read a formatted integer off the stream. During this attempt, whitespace (including newline) will be ignored. Therefore, until such time as you (a) enter a valid integer, (b) enter any non-whitespace that will fail to be parsed as an integer, or (c) the stream is already in EOF state so any further pulls without clearing are going to fail, so you're just left staring at an input prompt.
What you seem to really want is to just ignore data on the input stream until such time as a newline is entered (or EOF is encountered). One way to do that is to use the stream ignore member. For example:
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
will pull all input from std::cin and discard it until such time as a newline is entered, or the stream reaches and error or eof state. Using that, what you probably really want is this:
#include <iostream>
#include <limits>
#include <cstdlib>
#include <ctime>
using namespace std;
int main()
{
srand(static_cast<unsigned>(time(0)));
int p1, p2;
cout << "Player 1: Press enter to roll your dice" << endl;
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
p1 = (rand() % 6) + 1;
cout << "Player 2: Press enter to roll your dice" << endl;
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
p2 = (rand() % 6) + 1;
cout << "Player 1: " << p1 << '\n';
cout << "Player 2: " << p2 << '\n';
if (p1 == p2)
{
cout << "You tied! \n";
}
else if (p1 > p2)
{
cout << "Player 1 won! \n";
}
else
{
cout << "Player 2 won! \n";
}
}
I'd use <random> for the actual draw, but that is unrelated to the root problems in your posted code.
To get an Enter key press you need to read the newline. In C++ that’s the rather wordy:
#include <iostream>
#include <limits>
std::cin.ignore( std::numeric_limits <std::streamsize> ::max(), '\n' );
Note that your program really does not need user input as it is written — everything that happens is independent of the user’s action.
RNG and the Pigeonhole Principle
Whatever RAND_MAX is on your system, if it isn’t 32767 it is probably a number of the form 2n-1. This doesn’t divide nicely by 6. So you are more likely to get a random number of 0 than 2 or 5, for example.
The way to fix this is to ignore numbers past some multiple of 6.
int multiples = RAND_MAX / 6;
int new_rand_max = multiples * 6;
If the value from rand() is not strictly less than new_rand_max then you can just throw it away.
while ((x = rand()) >= new_rand_max) ;
Now you can get the remainder and return that:
return x % 6;
Put all that in a function, making 6 an argument value, and you are good to go!
int random( int n )
{
int max = (RAND_MAX / n) * n;
int result;
while ((result = rand()) >= max) ;
return result % n;
}
And to use it:
int p1 = random( 6 ) + 1;
Related
i new to programming and we are required to create a program that dont exit when the user inputs the wrong input, but i only learned the basics so far.. i already solved when the number is above and below 100 but when the user accidentally inserted a non integer it will go into a error loop. btw this is an average calculator.
#include <iostream>
using namespace std;
int main()
{
int num[100];
int n;
double sum, average;
cout << "how many numbers will you input?: ";
cin >> n;
while ( n > 100 || n <= 0 )
{
cout << "Error! number should in range of (1 to 100) only." << endl;
cout << "Enter the number again: ";
cin >> n;
}
for ( int i = 0; i < n; ++i )
{
cout << i + 1 << ". Enter number: ";
cin >> num[i];
sum += num[i];
}
average = sum / n;
cout << "Average = " << average;
}
If std::istream::operator >> fails, it will set failbit. Therefore, you should check failbit (for example by calling std::cin.fail()) to see whether the conversion was successful, before using the result of the conversion.
If the conversion fails due to bad input, then the next call to std::istream::operator >> will automatically fail due to failbit being set. That is why you are getting stuck in an infinite loop. If you want to attempt input again after a conversion failure, you will first have to clear failbit, by using the function std::cin.clear().
Also, you will have to discard the bad input that caused the conversion to fail, because otherwise, the next time you call std::istream::operator >>, the conversion will fail again for the same reason. In order to clear the bad input, you can use std::cin.ignore(), like this:
std::cin.ignore( std::numeric_limits<std::streamsize>::max(), '\n' );
In order to use std::numeric_limits, you will have to #include <limits>.
After performing these fixes on your code, it should look like this:
#include <iostream>
#include <limits>
using namespace std;
int main()
{
int num[100];
int n;
double sum, average;
bool input_ok;
//repeat until input is valid
do
{
cout << "How many numbers will you input? ";
cin >> n;
if ( cin.fail() )
{
cout << "Error: Conversion to integer failed!\n";
input_ok = false;
}
else if ( n > 100 || n <= 0 )
{
cout << "Error: Number should in range of (1 to 100) only!\n";
input_ok = false;
}
else
{
input_ok = true;
}
//clear failbit
cin.clear();
//discard remainder of line
cin.ignore( numeric_limits<streamsize>::max(), '\n' );
} while ( !input_ok );
for ( int i = 0; i < n; ++i )
{
do
{
cout << i + 1 << ". Enter number: ";
cin >> num[i];
if ( cin.fail() )
{
cout << "Error: Conversion to integer failed!\n";
input_ok = false;
}
else
{
input_ok = true;
}
//clear failbit
cin.clear();
//discard remainder of line
cin.ignore( numeric_limits<streamsize>::max(), '\n' );
} while ( !input_ok );
sum += num[i];
}
average = sum / n;
cout << "Average = " << average;
}
This program has the following behavior:
How many numbers will you input? 200
Error: Number should in range of (1 to 100) only!
How many numbers will you input? -31
Error: Number should in range of (1 to 100) only!
How many numbers will you input? test
Error: Conversion to integer failed!
How many numbers will you input? 4abc
1. Enter number: 1
2. Enter number: 2
3. Enter number: 3
4. Enter number: 4
Average = 2.5
As you can see, the program now works in that it can now handle bad input such as test. It rejects that input and reprompts the user for new input.
However, one problem with this program is that it accepts 4abc as valid input for the number 4. It would probably be appropriate to reject such input instead. One way to fix this would be to inspect the remainder of the line, instead of simply discarding it.
Another issue is that this solution contains a lot of code duplication. Apart from the range check, both do...while loops are nearly identical. Therefore, it would be better to put this loop into a function, which can be called from several places in your code.
However, I generally don't recommend that you use std::istream::operator >>, because its behavior is not always intuitive. For example, as already pointed out above:
It does not always read a whole line of input, so that you must explicitly discard the remainder of the line.
It accepts 4abc as valid input for the number 4.
In my experience, if you want proper input validation of integer input, it is usually better to write your own function that reads a whole line of input using std::getline and converts it with std::stoi. If the input is invalid, then the function should automatically reprompt the user.
In my example below, I am calling this function get_int_from_user.
If you want to additionally ensure that the input is in a certain range, then you can call the function get_int_from_user in an infinite loop, and break out of that loop once you determine that the input is valid.
#include <iostream>
#include <string>
#include <sstream>
#include <cctype>
int get_int_from_user( const std::string& prompt );
int main()
{
int nums[100];
int n;
double sum;
//repeat loop forever, until input is good
for (;;) //equivalent to while(true)
{
n = get_int_from_user( "How many numbers will you input? " );
if ( 1 <= n && n <= 100 )
//input is good
break;
std::cout << "Error! Number should in range of (1 to 100) only.\n";
}
//read one number per loop iteration
for( int i = 0; i < n; i++ )
{
std::ostringstream prompt;
prompt << "Enter number #" << i + 1 << ": ";
nums[i] = get_int_from_user( prompt.str() );
sum += nums[i];
}
std::cout << "Average: " << sum / n << '\n';
}
int get_int_from_user( const std::string& prompt )
{
std::string line;
std::size_t pos;
int i;
//repeat forever, until an explicit return statement or an
//exception is thrown
for (;;) //equivalent to while(true)
{
//prompt user for input
std::cout << prompt;
//attempt to read one line of input from user
if ( !std::getline( std::cin, line ) )
{
throw std::runtime_error( "unexpected input error!\n" );
}
//attempt to convert string to integer
try
{
i = std::stoi( line, &pos );
}
catch ( std::invalid_argument& )
{
std::cout << "Unable to convert input to number, try again!\n";
continue;
}
catch ( std::out_of_range& )
{
std::cout << "Out of range error, try again!\n";
continue;
}
//The remainder of the line is only allowed to contain
//whitespace characters. The presence of any other
//characters should cause the entire input to get rejected.
//That way, input such as "6sdfj23jlj" will get rejected,
//but input with trailing whitespace will still be accepted
//(just like input with leading whitespace is accepted by
//the function std::stoi).
for ( ; pos < line.length(); pos++ )
{
if ( !std::isspace( static_cast<unsigned char>(line[pos]) ) )
{
std::cout << "Invalid character found, try again!\n";
//we cannot use "continue" here, because that would
//continue to the next iteration of the innermost
//loop, but we want to continue to the next iteration
//of the outer loop
goto continue_outer_loop;
}
}
//input is valid
return i;
continue_outer_loop:
continue;
}
}
This program has the following behavior:
How many numbers will you input? 200
Error! Number should in range of (1 to 100) only.
How many numbers will you input? -31
Error! Number should in range of (1 to 100) only.
How many numbers will you input? test
Unable to convert input to number, try again!
How many numbers will you input? 4abc
Invalid character found, try again!
How many numbers will you input? 4
Enter number #1: 1
Enter number #2: 2
Enter number #3: 3
Enter number #4: 4
Average: 2.5
As you can see, it now correctly rejects the input 4abc.
I believe that using the function get_int_from_user makes the code in main much cleaner.
Note that the code above uses one goto statement. Under most circumstances, you should avoid using goto, but for breaking out of nested loops, it is considered appropriate.
#include <iostream>
#include <limits>
using namespace std;
int avg(int sum, int n)
{
int average;
average = sum/n;
cout<<"Avg = "<<average;
}
int main()
{
int n;
cout << "how many numbers will you input?: ";
cin >> n;
int w = n;
int num[w];
int sum;
while(n>100||n<=0)
{
cout << "Error! number should in range of (1 to 100) only." << endl;
cout << "Enter the number again: ";
cin >> n;
}
for(int i = 0; i < n; ++i)
{
cout << i + 1 << "Enter number: ";
cin >> num[i];
if(!cin)
{
cout << "Wrong Choice. " << endl;
cin.clear();
cin.ignore( numeric_limits<std::streamsize>::max(), '\n' );
n++;
continue;
}
else
{
sum += num[i];
}
}
cout<<"Sum = "<<sum<<endl;
avg(sum,w);
}
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);
}
}
I added a while statement around my code so that the user could repeat the process as my teacher instructed, the way I did it worked on other code but for some reason it broke this one I could use help making it work please and thank you. The point of the code is to just flip 10000 coins and output the number of heads and tails. Thanks for any and all help.
#include <iostream>
#include <ctime>
#include <cstdlib>
#include <string>
using namespace std;
// Keaton Graffis 12/22/2012
int coin()
{
int flip;
// assign random numbers
flip = rand() % 2 + 1;
return (flip);
}
int main()
{
char choice = 'y';
while (choice == 'y' || choice == 'Y');
{
double numFlips = 10000;
int count, face, heads = 0, tails = 0;
// initialize the random number generator
srand(static_cast<int>(time(0)));
// generate and count the number of heads and tails
for (int count = 1; count <= numFlips; count++)
{
face = coin();
if (face == 1)
heads++;
else
tails++;
}
cout << "The number flips: " << numFlips << endl;
cout << "The number of heads: " << heads << endl;
cout << "The number of tails: " << tails << endl;
// Asks user if they would like to go again(makes cod enot run, not sure why, this works on all my other code)
while (1)
{
cout << "Would you like to play again [Y]es or [N]o?\n";
cin >> choice;
if (choice == 'y' || choice == 'Y' || choice == 'n' || choice == 'N')
break;
}
}
}
Remove the semicolon after the while condition of the first loop. Only full statements are terminated by a ;.
Notes:
Since C++11, better facilities for random number generation are provided in the <random> header. Use these!
I have a homework assignment that requires me to calculate a percentage chance from an user input of the numbers 1 to 3. However, I'm not sure how to do this.
This is my code, not all of it though:
void SwingAtBall( Ball *tBall ) {
std::cout << "How hard do you want to hit the ball? Please enter a number between 1 to 3." << std::endl;
int tBallHit;
std::cin >> tBallHit;
if ( tBallHit > 3 || tBallHit < 1 ) {
std::cout << "That is not a valid value. Please enter a number between 1 to 3." << std::endl;
std::cin >> tBallHit;
}
}
// Prompt for 1 to 3. There is a (input * 15) percent chance the ball only goes 5 feet. Otherwise the ball is hit a random number between 0 and (input * 150). Print how far it went.
If my understanding is correct that there is an (input * 15) percent chance the ball will go 5 feet and an (100 - (input * 15)) percent chance it will go anywhere from 0 to (input * 150) feet, then the following code will calculate what you are looking for...
#include <iostream>
#include <ctime>
using namespace std;
int main()
{
int inp, chance1, dist1, dist2, dist_final;
do {
cout << "Enter integer between 1 and 3: ";
cin >> inp;
} while (inp < 0 || inp > 3);
dist1 = 5;
srand(time(0));
dist2 = rand() % (inp * 150);
chance1 = (inp * 15) / 100;
dist_final = chance1 * dist1 + (1 - chance1) * dist2;
cout << "It went this far: " << dist_final << endl;
// system("pause");
return 0;
}
There's a whole <random> header for things like this.
Simple percentages are easy, you can use integers for that. Pick either 0-99 or 1-100, and use that in a uniform_int_distribution. Sure, 15% is 3/20 so you could also use a uniform_int_distribution(1,20) but that's more obscure.
"0 to (input * 150)" is a uniform_int_distribution(0,input*150).
I'm writing a code for a game that prompts the user to pick how many times they want to flip a coin and guess how many times it will land on heads. I wrote most of, just need help finishing it up. I tried to include a count of the heads but ran into problems.
#include <iostream>
#include <cmath>
#include <ctime>
using namespace std;
int myRandNumGen(){
int num = rand();
return num;
}
char coinTossFunction( ){
char coinToss;
int coinTossValue = (myRandNumGen()%2); // 0 or 1
switch (coinTossValue) {
case 0:
coinToss = 'H';
break;
case 1:
coinToss = 'T';
break;
default:
break;
}
return coinToss;
}
int calcCoin(int n){
int cout_heads=0;
for(int i=0;i<=n;i++){
if(coinTossFunction() == 'H')
++cout_heads;
}
return (cout_heads/n);
}
int main(){
int coinflips, guess;
cout << "How many times do you want to flip the coin? " << endl;
cin >> coinflips;
cout << "Guess how many times a coin will land on heads if flipped: " << endl;
cin >> guess;
if (guess>coinflips) {
cout << "Guess Error";
}
for(int i=1;i<=coinflips;i++){
cout << calcCoin;
}
Here are a few problems with your code:
for(int i=0;i<=n;i++)
This will make i take the values from 0 to n, which means you will enter in the loop n+1 times, instead of n times.
return (cout_heads/n);
Since both variables cout_headsand n are integers, this will perform an integer division, and not a floating point division. The result will always be 0 or 1 in this case.
cout << calcCoin;
When you call a function you need to put parenthesis. Also your calCoin function takes a parameter.