This code is working fine, however this whole time I've tried avoiding using the goto statements that you will see in the switch (dice_total) statement.
Without the goto statements, the program will not loop back to the beginning of while (again=='y' || again=='Y'), and instead it keeps looping itself when it reaches the do-while loop.
However, I believe that it is also important to say, that if dice_total is = to the point_total the first time around then the program will function properly, and loop back to the beginning. For example, when the program starts, the first round will generate the point_total, which we will say its 10. Which is a value that will allow the program to continue to the next round, and if the dice_total also gets the same number, 10, the program will say you win, and the loop will work properly. However, if the program reaches the do while loop, and generates a number that isn't 10, but generates a 10 after a few loops, then the program will not loop to the beginning. So what I want to ask, what is wrong with my switch(dice_total) statement, and how can I fix it, to give the program the same effect without using the goto statements?
#include "stdafx.h"
#include <iostream>
#include <random>
#include <string>
using namespace std;
int main()
{
//Declared Variables***********************************
char again = 'y';
int point1;
int point2;
int point_total;
int round_1=1;
int dice1;
int dice2;
int dice_total;
//*****************************************************
//RANDOM SEED******************************************
random_device rd;
mt19937 mt(rd());
uniform_int_distribution<int>dist(1, 6);
//*****************************************************
start://TEMPORARY
while (again == 'y'||again=='Y')
{
int round_1 = 1;
system("CLS");
cout << "WELCOME TO THE CRAPS GAME" << endl;
cout << "THROWING ROUND:" << round_1 << " DICES.............." << endl;
point1 = dist(mt);
point2 = dist(mt);
point_total = point1 + point2;
cout << "ROUND: " << round_1 << " First dice is: " << point1 << " and second dice is: " << point2 <<" and the total is:"<<point_total<< endl;
switch (point_total)
{
case 7:
case 11:
cout << "YOU WON CONGRATS PRESS Y TO PLAY AGAIN!!" << endl;
cin >> again;
break;
case 2:
case 3:
case 12:
cout << "YOU LOST, PRESS Y TO TRY AGAIN" << endl;
cin >> again;
break;
default:
do
{
++round_1;
cout << "ROUND " << round_1 << endl;
dice1 = dist(mt);
dice2 = dist(mt);
dice_total = dice1 + dice2;
cout << "THROWING ROUND: " << round_1 << " DICES.............." << endl;
cout << "ROUND 1 DICE TOTAL IS: " << point_total << endl;
cout << "ROUND: " << round_1 << " First dice is: " << dice1 << " and second dice is: " << dice2 << " and the total is:" << dice_total << endl;
switch (dice_total)
{
case 11:
cout << "YOU WON CONGRATS PRESS Y TO PLAY AGAIN!!" << endl;
cin >> again;
goto start;
case 2:
case 3:
case 7:
case 12:
cout << "YOU LOST, PRESS Y TO TRY AGAIN" << endl;
cin >> again;
goto start;
default:
if (dice_total == point_total)
{
cout << "YOU WON CONGRATS PRESS Y TO PLAY AGAIN!!<<endl;
cin >> again;
break;
}//if
else
{
cout << "Going to next round" << endl;
}
}//dice_total
}//do
while (dice_total != point_total);
break;
}//switch point
}//again while
}//main
The problem you're facing is usual when you have too many nested loops in the same function, and is an indicator that you need to refactor parts of your code to be in their own functions.
If you do this, then you have more possibilities to control the flow of your code: in each function you have break and return, and as you can return a custom value, you can use it to determine in the surrounding function if you need to break or return again.
Besides, this gives you the opportunity to put self-explanatory names to your functions, which makes your code clearer for people that look at it for the first time (as it's written, it's so dense that I can't understand it unless I stare at it for some minutes).
An example of what I mean in code:
Before
int main() {
start:
while (a) {
b1();
switch(c) {
case 1:
do {
d();
if (cond) goto start;
} while(e);
break;
}
b2();
}
}
After
int main() {
while (a) {
if (!doStuff1())
break;
}
...
}
bool doStuff1() {
b1();
while (a) {
bool res = doStuff2();
if (res) return true;
}
b2();
...
}
bool doStuff2() {
switch(c) {
case 1:
if (doStuff3()) return true;
}
return false;
}
bool doStuff3() {
do {
d();
if (cond) return true;
} while (e);
return false;
}
How about this design?
bool stop=false;
while(!stop && (again == 'y'||again=='Y'))
{
while(again == 'y'||again=='Y')
{
// ...
break; /* breaks inner while*/
// ...
stop=true;
break; /* breaks inner while, and prevents running outer loop*/
}
}
Related
Can anybody please explain why this while loop is not working properly?
#include <iostream>
using namespace std;
void ask_user(int a, int b){
char choice = ' ';
while(choice != 'q' && choice != 'a' && choice != 's' && choice != 'm'){
cout << "choose operation" << endl;
cout << "a to add, s to subtract, m to multiply and q to quit" << endl;
cout << "----------------------------" << endl;
cin >> choice;
switch(choice){
case 'a' : cout << "a + b = " << a + b;
break;
case 's' : cout << "a - b = " << a + b;
break;
case 'm' : cout << "a * b = " << a + b;
break;
case 'q' : break;
default: cout << "please Enter a valid choice " << endl;
}
}
}
int main(){
ask_user(7, 9);
return 0;
}
If I enter p for exemple which is not valid then it works fine and asks for valid input again,
but if I enter pp that's when it starts bugging and prints the message twice. If I enter ppp it
prints three times etc...
First thing, you have a misunderstanding of how switch works. Each case must end with break statement so that the following one won't get executed.
Which means that a break will break the switch, not the while.
But the main issue is that the logic of your program is wrong.
You should not loop over the validity of the given input, let the switch statement handle that in the default clause.
Instead you should loop over a flag that will be set when the user press the q key.
So considering you have the following functions defined to respectively display the menu and ask for the operands to operate on (defined for code readability):
void display_menu(char & choice)
{
std::cout << "Operation:\na: Addition\nm: Multiplication\ns: Substraction\nq: Quit\n";
std::cin >> choice;
}
void ask_operands(int & a, int & b)
{
std::cout << "\na ?";
std::cin >> a;
std::cout << "\nb ?";
std::cin >> b;
std::cout << '\n';
}
The logic of your code can be then rewritten as:
int main()
{
bool quit = false;
char choice;
int a, b;
ask_operands(a, b); // Ask the user which operands to use
while(!quit) // loop over the flag
{
display_menu(choice);
switch(choice)
{
case 'a': std::cout << (a+b);
break;
case 'm': std::cout << (a*b);
break;
case 's': std::cout << (a-b);
break;
case 'q': std::cout << "Exiting...";
quit = true; // Set the flag to false
break;
default: std::cout << "Invalid choice, try again."; //Here you handle the invalid choices (i.e. let the loop iterate again)
}
std::cout << '\n';
}
return 0;
}
Live example
Note: If you want the user to be able to change the value of the operands at each iteration, just move the ask_operands(a, b); call inside the loop.
I'm self-teaching myself here so I don't have a model answer available.
Working through program flow examples and trying to get a number guesser based on binary searching. I've got it to run and catch edge cases successfully but one objective is to have main() return the number of guesses made. I refactored the main code into a separate function to make it clearer, but I can't get the return code correct, I suspect it's to do with variable scope but can't figure it out.
#include <iostream>
using namespace std;
int guessNumber(int highest, int lowest, int lAttempts)
{
int guess = lowest + ((highest - lowest) * 0.5);
char response = 'a';
lAttempts++;
cout << "My guess is " << guess << ", am I correct?" << endl;
cout << "(y)es/too (h)igh/too (l)ow/(q)uit" << endl;
cin >> response;
while (response != 'y' && response != 'h' && response != 'l' && response != 'q')
{
cout << "I'm sorry, I didn't understand that" << endl;
cout << "(y)es/too (h)igh/too (l)ow/(q)uit" << endl;
cin >> response;
}
switch (response)
{
case 'y':
cout << "I guessed correctly after " << lAttempts << " attempts";
break;
case 'h':
highest = guess;
guessNumber(highest, lowest, lAttempts);
break;
case 'l':
lowest = guess;
guessNumber(highest, lowest, lAttempts);
break;
case 'q':
cout << "Exiting program";
break;
}
return lAttempts;
}
int main()
{
cout << "Think of a number between 1-100" << endl;
int highest = 100;
int lowest = 0;
int attempts = 0;
attempts = attempts + guessNumber(highest, lowest, attempts);
return attempts;
}
cout returns the correct number of attempts but the program (so main()) always exits with 1.
What am I missing here?
Thanks.
You're missing to update your attempt variable within your switch statements.
It should be like this.
lAttempts = guessNumber(highest, lowest, lAttempts);
#include <iostream>
#include <string>
#include <vector>
#include "Player.h"
using namespace std;
void PlayerMenu();
int main() {
int z;
cout << "Please press 0 to see the PLayers Menu. " << endl;
cin >> z;
while (z == 0) {
PlayerMenu();
}
cout << " Now You're Functional Lets get started. ";
};
void PlayerMenu()
{
char ch;
int num;
do {
system("cls");
cout << "\n\n\n\t Player Menu";
cout << "\n\n1 Wallet Balance ";
cout << "\n\n2 Player Invetory";
cout << "\n\n3 To Exit";
cin >> ch;
system("cls");
switch (ch)
{
case '1':
cout << "Your Balance at the moment is ..."<<endl;
cout << "\n";
Bank();
break;
//Show Wallet Balance
case '2':
cout << "Here is your Inventory"<<endl;
cout << "\n";
break;
//Show Inventory
case '3':
cout << " Bye.\n";
break;
//exit i'VE TRIED bREKA BUT it will not go back to the main source code or main method
}
cin.ignore();
cin.get();
} while (ch != '3');//If not 1 or 2 or 3 will ignore it
}
I tried break statements, but the break method will not exit to the main method and run the last following statement. I would like to also run methods inside of the case to case so when a player is selecting 1 it will show the balance of the player. Also when the player inputs a value of 2 it will show a vector of weapons bought.
Use return instead of break to exit from the current function. You then don't need the while (ch != '3'). Instead, you can just use an infinite loop:
while (true) {
// ...
case '3':
cout << " Bye.\n";
return;
}
cin.ignore();
cin.get();
}
You can also use for (;;) instead of while (true), but that's just a stylistic choice.
Also, don't call PlayerMenu() in a loop in main. Just do:
int main()
{
int z;
cout << "Please press 0 to see the PLayers Menu. " << endl;
cin >> z;
if (z == 0) {
PlayerMenu();
}
cout << " Now You're Functional Lets get started. ";
}
break in this context exits the switch. If you wish to exit the function, you will need to return instead.
Your PlayerMenu() function is exiting just fine. The problem is in main():
while (z == 0) {
PlayerMenu();
}
There is nothing in the loop that modifies z, so it never exits. It just keeps going back to the menu forever.
I don't know if you intended to loop there or just test it with an if.
I'm trying to get it back to loop if they enter anything from the choices. everytime I enter 4, it just ends. and if I pick the right one it also ends. Is there anyway I can get it to ask user to input the right one?
void towsoncourse ()
{
cout << "Enter Course: 1 is COSC,2 is ENGL,3 is MATH" << endl;
int course;
bool finish;
bool finishcourse = true;
cin >> course;
while (finishcourse != true)
{
cout << "Enter correct number for course" << endl;
if (course == 1 || course == 2 | course == 3)
{
finish = true;
}
else
{
cout<< "Error: Enter number corresponding to course." << endl;
}
}
switch (course)
{
case 1:
cout << "COSC" << endl;
break;
case 2:
cout << "ENGL" << endl;
break;
case 3:
cout << "MATH" << endl;
break;
default:
cout << "Error: Enter number corresponding to course" << endl;
}
}
int main ()
{
towsoncourse ();
return 0;
}
Not a complete answer, but rather a guide to point the way.
You want to keep reading an input until it is one of 3 possible values. So a good place to read and test the input would be inside a loop, exiting only when the test conditions are met.
while loops test continue criteria before each execution. do loops test continue criteria after each execution. In you case it is necessary to execute at least once.
There were some issues with the code.
1) while (finishcourse != true) condition was wrong. It should be while (finishcourse == true).
2) finish = true; assignment was wrong. It should have been finishcourse = false;
3) cin >> course; should be taken inside the loop. Because if you place it outside, it will lead to infinite loop in case of incorrect entry.
So, Just to ensure readability, I have rewritten the code. I have assumed that it gets back to the loop in case of incorrect entry and in case of correct entry, it terminates.
#include <iostream>
using namespace std;
void towsoncourse ()
{
bool finishcourse = true;
while (finishcourse == true)
{
int course;
cout << "Enter Course: 1 is COSC,2 is ENGL,3 is MATH" << endl;
cin >> course;
switch (course)
{
case 1:
cout << "COSC" << endl;
finishcourse = false;
break;
case 2:
cout << "ENGL" << endl;
finishcourse = false;
break;
case 3:
cout << "MATH" << endl;
finishcourse = false;
break;
default:
cout << "Error: Enter number corresponding to course." << endl;
}
}
}
int main ()
{
towsoncourse ();
return 0;
}
Having some trouble with some code and I cannot get to the bottom of it. This code:
int main()
{
int choice;
while (choice != -1)
{
system("cls");
std::cout << "Main Menu: " << std::endl
<< " 1. Encode." << std::endl
<< " 2. Decode." << std::endl
<< "-1 to exit." << std::endl;
std::cin >> choice;
switch (choice)
{
case 1:
encode();
break;
case 2:
decode();
break;
case -1:
break;
}
}
getchar();
return 0;
}
void encode()
{
std::string plainText;
std::string encText = "Test";
std::cout << "Enter text to be encrypted.\n";
getline(std::cin, plainText);
for (int x = 0; x < plainText.length(); x++)
{
//encText += plainText.substr(x, x + 1);
}
std::cout << encText;
getchar();
return;
}
If I enter '1' at the first cin >> choice, I go into encode(), once there, entering any text causes the program to go back to the while, perform system("cls"), and then jumps right back to "Enter text to be encrypted." down in encode().
Any help? I'm clueless.
If you'd like to exit your while loop after encode() or decode(), you have to satisty the while's condition. You can do this by simple setting choice to -1 after the function calls:
case 1:
encode();
choice = -1;
break;
case 2:
decode();
choice = -1;
break;
Just so you're aware, the return at the end of encode() causes the encode() function to finish, not main. That line of code actually does nothing; since there's nothing after it, it would happen anyway.