Do-while loop issue: Try to develop a simple game - c++

Well, I'm writing to make a dice game. I tried searching dice game here but none of it seems to answer my question. This isn't a problem about the dice roll thing anyway. It's about the do while loop. I am very new to this site, I just found out about this via Maximum PC Magazine so please bear with me. Also I am new to programming.
Here is my code:
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
int main(){
srand(time(NULL));
int userRoll = rand() % 6 + 1 ;
int computerRoll = rand() % 6 + 1 ;
string yesOrNoChoice;
string commandToThrowDie;
do{
cout << "Please enter \"throw\" (lowercase) to roll the die: ";
cin >> commandToThrowDie;
} while(commandToThrowDie != "throw");
do{
cout << "You rolled: " << userRoll << endl
<< "The Computer rolled: " << computerRoll << endl;
if (userRoll < computerRoll){
cout << "You lose. Try again? [Yes/No]: ";
}
if (computerRoll < userRoll){
cout << "You win! Try again? [Yes/No]: ";
}
if (computerRoll == userRoll) {
cout << "It's a draw. Try again? [Yes/No]: ";
}
cin >> yesOrNoChoice;
} while(yesOrNoChoice != "Yes");
system ("pause");
return 0;
}
The problem is that after asking the user to enter a choice at the end of the do-while-loop the program exits loop no matter what I enter, instead of looping back to another throw of the die.
It ends up like this:

I copied your code and it compiled and ran perfectly. Doesn't make sense exactly, but no issues. I say it doesn't make sense since when "Yes" is entered that is what kills it. I believe what you want it while(yesOrNoChoice == "Yes"). Perhaps having it as != was making you think you were getting the wrong behavior? Also, you should be using if, else if, else statements, not just if.

Related

For Loops (C++)

Assignment:
The program should ask the user to enter a positive number and display all numbers from 1 to the input value. If the number is not positive, an error message should show up asking the user to re - enter the number.
My specific problem:
For my program, if the user enters an incorrect number and then re - enters a positive number, it does not display all the numbers from 1 to the input value. The program just ends.
#include <iostream>
using namespace std;
int main()
{
int userChoice;
int i = 1;
cout << "Enter a positive integer" << endl;
cin >> userChoice;
if (userChoice > 0)
{
for (i = 1; i <= userChoice; i++)
{
cout << "Loop 1:" << endl;
cout << i << endl;
}
}
else if (userChoice < 0)
cout << "Please re - enter" << endl;
cin >> userChoice;
system("pause");
return 0;
}
You need some sort of loop at the top of your program, that keeps asking for input until the user provides something valid. It looks like a homework assignment, so I will provide pseudo-code, not something exact:
std::cout << "Enter a number:\n";
std::cin >> choice;
while (choice wasn't valid) { // 1
tell the user something went wrong // 2
ask again for input in basically the same way as above // 3
}
// after this, go ahead with your for loop
It is actually possible to avoid the duplication here for step 3, but I worry that might be a little confusing for you, so one duplicated line really isn't such a big problem.
As an aside, you may wish to reconsider your use of what are often considered bad practices: using namespace std; and endl. (Disclaimer - these are opinions, not hard facts).

cin not accepting user input in C++

I'm a beginner in programming, and I'm trying to make a program that calculated how much radiation you've been exposed to throughout your life. For some reason, the 'cin' in my xray function doesn't accept user input, and just exits with code 0.
#include <iostream>
#include <conio.h>
#include <windows.h>
#include <stdlib.h>
#include <string>
#include <sstream>
using namespace std;
bool nearpowerplant;
int XRay; // the amount of times you got an x-ray
double tRads = 0; // your total dose of radiation in your lifetime, measured in mSv (millisievert)
int age;
//the sleep function
void sleep() {
Sleep(1000); // 1000 miliseconds = 1 second
}
/*
>system("CLS")< for clear the console
*/
//introduction and pretty much the menu
void intro() {
cout << "Welcome to the Radiation Level Calculator" << endl;
sleep();
cout << "Conceptualized and created by Anatoly Zavyalov" << endl;
sleep();
cout << "Press the ENTER key to begin." << endl;
cin.get();
}
//introduction to general questions
void genintro() {
// intro to the medical
system("CLS");
sleep();
cout << "Let's begin with general questions." << endl;
sleep();
cout << "Press the ENTER key to continue." << endl;
cin.get();
}
//medical questions
void Age() {
//age
system("CLS");
cout << "How old are you?\n" << endl;
sleep();
cin >> age;
if (age <= 0) {
cout << "Your age can't be less or equal to 0." << endl;
Age();
}
else {
tRads += (age * 2);
sleep();
cout << tRads << endl;
}
}
//live close to powerplant?
void powerplant() {
system("CLS");
cout << "Do you live within 75 kilometers of a nuclear powerplant?" << endl;
sleep();
cout << "If yes, type YES. If no, type NO." << endl;
cin >> nearpowerplant;
if (nearpowerplant = "YES") {
tRads += (age * 0.01);
}
else {}
sleep();
cout << tRads << endl;
}
void xray() {
system("CLS");
cout << "How many times have you had an x-ray?\n" << endl;
sleep();
cin >> XRay;
if (XRay < 0) {
cout << "You can't have an x-ray a negative amount of times." << endl;
}
else {
tRads += (XRay * 3.1);
}
sleep();
cout << tRads << endl;
}
//main function, put all of the loops into here
int main() {
intro(); // the introduction
genintro(); // medical intro
Age(); // asks for age
powerplant(); // asks if lives close to powerplant
xray(); // asks for x-ray
return 0;
}
EDIT: I have edited the post to include the whole code. By the way, I am using Visual Studio Community 2017.
bool nearpowerplant;
nearpowerplant is a bool. It is true or false. That is it. It's worth noting that there is no reason for this variable to be globally accessible and consuming storage for the entire run of the program. It is used twice in the program, both times in the same function. It should be an Automatic variable scoped by the function that uses it.
cout << "If yes, type YES. If no, type NO." << endl;
cin >> nearpowerplant;
Reading "YES" or "NO" into a variable of type bool fails. cin cannot convert the string input into a boolean value and cin stops accepting input until the error is cleared. It's also a good idea to remove the garbage input that caused cin to fail or guess what? cin's just going to fail again. There are hundreds of SO questions on how to handle this, so I'm just going to drop keywords here: clear and ignore.
Takeaways: Make sure the data entry matches the type of the data being entered into and test the stream after every read to make sure the read succeeded.
eg:
if (cin >> nearpowerplant)
{
// do stuff
}
else
{
// clean up
}
This solves OP's visible error, but since it is heavily entwined with the next bug they are likely to find, we might as well cover it as well.
if (nearpowerplant = "YES") {
tRads += (age * 0.01);
}
else {}
if (nearpowerplant = "YES") { uses = (assignment) where it should use == (comparison). C++ is unforgiving here because this will compile. What it really did was takes the address of the string literal "YES", test that it's not null, and set nearpowerplant to the result. Since the address of the string literal is never going to be NULL, the result is always true, and when the if tests the result, the if will always enter.
Eg: http://ideone.com/4QL2jn
So what we need is something more like
cout << "If yes, type YES. If no, type NO." << endl;
string temp;
cin >> temp;
if (temp == "YES") {
tRads += (age * 0.01);
}
else {}
Note this will skip if the user inputs "yes", "y", "Yes" or anything other than exactly "YES". How you deal with this is up to you, but std::tolower and std::transform may help somewhat.
I think with sleep() comes undefined behavior, you should test it without, the os handles user-input and you do not have to care about the user typing in. endl flushes cout, so the text is directly shown.
Edit:
Maybe system("CLS") or sleep produces a silent error.

Print out last line and then run program again Y/N

I am stuck on this random guessing game for school.
I have added the code that needed to be added, but the console keeps closing without returning the last strings.
I would also like to learn how to make the program run again with clicking Y to run again.
I am still learning C++, so any help would be appreciated.
Code:
// GuessingGameApp.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <string>//added to run string
#include <locale>//added toupper run again
using namespace std;
int main()
{
//Seed the random number generator
srand(time(0));
int selectedNumber = rand() % 20 + 1; int numberOfTries = 0;
int inputtedGuess;
std::cout << "Guess My Number Game\n\n";
//Ask the user for a value until the correct number is entered
do {
std::cout << "Enter a guess between 1 and 20:";
std::cin >> inputtedGuess;
++numberOfTries;
if (inputtedGuess > 20 || inputtedGuess < 1) {
cout << "Your guess is out of range.\n\n";
}
else if (inputtedGuess > selectedNumber) {
cout << "Too high!\n\n";
}
else if (inputtedGuess < selectedNumber) {
cout << "Too low!\n\n";
}
}
while (inputtedGuess != selectedNumber);
//Congratulate the user and end the program
std::cout << "\nCongratulations! You solved it in " << numberOfTries << " tries!\n" << std::endl;
//fix problem with console closing and (add "play again" option), so I can
//learn
//printf; did not work... Break did not work..
//
return 0;
}
I was able to get the console to stay open by putting a break at line 33, but I want to learn how to do this correctly so I deleted the break.
The last line of your output should actually be printed. The reason why the last line "is not printed" is probably that your IDE closes the console before you can see the final output (though it should be there). Many IDEs allow to make the console visible after program termination. BTW: Note that when pasting the code you probably lost a << before std::endl in std::cout << "\nCongratulations! You solved it in " << numberOfTries << " tries!\n" std::endl; But this has actually to be a copy-paste problem, because your program would not have compiled otherwise.
Anyway, by providing a "Try again?"-logic, your program does not terminate and the problem is solved.
I'd suggest to provide a separate function performing the guess, which is then called in a do-while loop with the "Try again="-question.
void guess() {
// your code (except srand) goes here...
}
int main() {
srand(time(0)); //Seed the random number generator only once
char doAgain;
do {
guess();
cout << "Try again (Y/N)?";
cin >> doAgain;
}
while (toupper(doAgain)=='Y');
return 0;
}
As people suggested, you can add another do-while loop to repeat the game.
int choice = 0;
do {
// first part of code..
do {
// inner do-while
} while (inputtedGuess != selectedNumber);
std::cout << "\nCongratulations! You solved it in " << numberOfTries << " tries!\n" std::endl;
cout << "\nWould you like to play again?\n\n";
cout << "1 - Yes\n";
cout << "2 - No\n\n";
cout << "Choice: ";
cin >> choice;
} while(choice == 1);

Safe [Y/N]; [1/2/3/etc.] function

I tried to make a an introduction to a "game", and in its functions I made some Yes/No, 1/2/3, situations.
Im new to this however it wasn't that difficult, worked perfectly. The problem appeared when handling with invalid inputs. So this is what the code looks like by now:
#include "Introduction.h"
#include "GameConstants.h"
#include "PlayerCharacter.h"
#include <iostream>
#include <windows.h>
using namespace std;
Introduction::Introduction()
{
}
/////////Function N.1///////////
void Introduction::presentation()
{
char confirm;
string enteredName;
cout << constants.line() << "Welcome traveler! What is the name?" << endl;
getline(cin,enteredName);// Gets the WHOLE LINE as the name.
while (confirm != 'Y') //If the player doesn't confirm the name with 'Y' in will run again until it does.
{
cout << constants.xline() << "Your name is " << enteredName << " right? (Y/N)" << endl;
cin >> confirm; //The player's answer
cin.sync(); //Only takes the first character
confirm = toupper(confirm); //Turns player message into CAPS for easier detection in the "if" statements
if (confirm == 'N'){ //If not the correct name, gives another chance
cout << constants.xline() << "Please, tell me your name again..." << endl;
cin >> enteredName;
cin.sync();}
if ((confirm != 'Y')&&(confirm != 'N')){ //If an invalid input is entered, gives another chance. And insults you.
cout << constants.xline() << "Fool Go ahead, just enter your name again." << endl;
cin >> enteredName;
cin.sync();}
}
if (confirm == 'Y'){ //When the answer is yes ('Y') /* Uneeded line */
PC.setName(enteredName); //Saves the name
cout << constants.xline() << "Excellent! I have a few more questions for you " << PC.name() << "..." << endl;
}
}
//////////Function N.2///////////
void Introduction::difSelection(){
int selectedDif = 0; //Variable to store selected difficulty whitin this function.
Sleep(2500);
cout << constants.xline() << "What kind of adventure do you want to take part in?" << endl;
Sleep(2500); //Wait 2,5 s
cout << "\n1= Easy\n2= Normal\n3= Hard" << endl;
while(selectedDif != 1&&2&&3){ //Selected option must be 1/2/3 or will run again
cin >> selectedDif; //Sets the user selected difficulty
cin.sync(); //Gets only first character
if((selectedDif != 1||2||3)&&(!(selectedDif))){ //If the input isn't 1/2/3 AND is an invalid character, this will run. And it'll start again
cout << constants.xline() << "Criminal scum. Go again." << endl;
cin.clear();
cin.ignore();
}
if(selectedDif != 1&&2&&3){ //If selected option isn't 1/2/3, this will run and will loop again. However I know this conflicts with the previous statement since this will run anyways.
cout << constants.xline() << "Wrong input, please try again." << endl;
}
else if(selectedDif == 1){
constants.setDiff(1);
constants.setStatPoints(15);
} else if(selectedDif == 2){
constants.setDiff(2);
constants.setStatPoints(10);
} else if (selectedDif == 3){
constants.setDiff(3);
constants.setStatPoints(5);}
}
}
The first function works perfectly you can type "aaa" or "a a a" and will work. However I'd like to know if there's a simpler way to do it. (Understandable for a beginner, just started 3 days ago lol; if it includes some advanced or less known code prefer to stay like this by now).
Now, the second one, I really have no idea how to fix it. I need something that if the user's input was an invalid character type, throw certain message, and if it's an int type, but out of the range, another message. And of course, run again if it fails. Did a lot of search and couldn't find anything that meet this requirements.
To check if the user input is an int, you could use the good() function.
int val;
cin >> val;
if( cin.good() ) {
// user input was a valid int
} else {
// otherwise
}
As for the range check, the syntax is a bit different.
This returns true if the number is not equal to 1 nor 2 nor 3:
selectedDif != 1 && selectedDif != 2 && selectedDif != 3
Another shorter way would be to use:
selectedDif < 1 || selectedDif > 3
Another thing, in c++, there are two keywords break and continue which will allow to reduce the code in the loops.

Random number generator for C++ popping up with an error?

I am having trouble with my number generator. Syntax wise, everything is working properly. I mainly wanted to use functions to see if they would work properly. When I run the program, a message pops up and says that my variable "guess" is not initialized. Can anyone give insight as to why this may be happening?
Also note that even though I didn't include my libraries in the code below, they are present in the actual program itself.
using namespace std;
int game();
string playAgain();
int main(){
game();
playAgain();
return 0;
}
int game(){
int guess;
int guessesTaken = 0;
int number = rand() % 10 + 1;
int count = 0;
cout << "I am thinking of a number between 1 and 10, can you guess it? " << endl;
while (guessesTaken < count){
cout << "Take a guess: " << endl;
cin >> guess;
if (guess > number)
cout << "Too High. Try again!" << endl;
if (guess < number)
cout << "Too Low! Try again!" << endl;
if (guess == number)
break;
}count++;
if (guess == number)
cout << "Congratulations!" << endl;
return 0;
}
string playAgain(){
string play;
cout << "Want to play again?: " << endl;
if (play == "y" || "Y")
main();
else
cout << "Thanks for playin" << endl;
return 0;
}
It happens because you did not initialise guess, precisely as the warning says.
Sure, if you assume that the cin >> guess operation will always succeed, then initialisation becomes largely irrelevant as the variable will take on a deterministic value.
But:
the compiler does not know this when it warns you, and
you have no error checking on your cin >> guess operation; not only can you not assume that it will always succeed, but your program has no clue whether it actually did.
Furthermore, the entire loop may not be executed at all if your other variables have the right values, so the compiler is completely right in its observation.
Initialise your variables and put error checking around your stream operations.
Furthermore, that count++ should obviously be in the loop body, and your loop otherwise needs refactoring in general because it begins with the 0 < 0 case. You should think hard about what you intend the semantics of your program to be.