Quick review
If statements allow us to execute a statement based on whether some condition is true. Else statements execute if the associated if statement is false. You can chain together multiple if and else statements.
Switch statements provide a cleaner and faster method for selecting between a number of discrete items. Switch statements pair great with enumerations.
Goto statements allow the program to jump to somewhere else in the code. Don’t use these.
While loops allow the program to loop as long as a given condition is true. The condition is evaluated before the loop executes.
Do while loops are the same as while loops, but the condition is evaluated after the loop execution. They’re great for menus or things that need to execute at least once.
For loops are the most used loop, and are perfect when you need to loop a specific number of times.
Break statements allow us to break out of a switch, while, do while, or for loop. Or a for each loop, which we haven’t covered yet.
Continue statements allow us to move immediately to the next loop iteration. Be careful when using these with while and do while loops, as your loop counter may not get incremented properly.
And finally, random numbers give us a way to make our programs behave different each time they are run. We’ll see an example of this in the quiz below!
Quiz time!
Warning: The quizzes start getting harder from this point forward, but you can do it. Let’s rock these quizzes!
1) In the chapter 2 comprehensive quiz, we wrote a program to simulate a ball falling off of a tower. Because we didn’t have loops yet, the ball could only fall for 5 seconds.
Take the program below and modify it so that the ball falls for as many seconds as needed until it reaches the ground.
In constants.h:
In your main code file:
Show Solution
2a) Implement a game of hi-lo. First, your program should pick a random integer between 1 and 100. The user is given 7 tries to guess the number.
If the user does not guess the correct number, the program should tell them whether they guessed too high or too low. If the user guesses the right number, the program should tell them they won. If they run out of guesses, the program should tell them they lost, and what the correct number is. At the end of the game, the user should be asked if they want to play again. If the user doesn’t enter ‘y’ or ‘n’, ask them again.
Note: You do not need to implement error handling for the user’s guess.
Here’s what your output should look like:
Let's play a game. I'm thinking of a number. You have 7 tries to guess what it is.
Guess #1: 64
Your guess is too high.
Guess #2: 32
Your guess is too low.
Guess #3: 54
Your guess is too high.
Guess #4: 51
Correct! You win!
Would you like to play again (y/n)? y
Let's play a game. I'm thinking of a number. You have 7 tries to guess what it is.
Guess #1: 64
Your guess is too high.
Guess #2: 32
Your guess is too low.
Guess #3: 54
Your guess is too high.
Guess #4: 51
Your guess is too high.
Guess #5: 36
Your guess is too low.
Guess #6: 45
Your guess is too low.
Guess #7: 48
Your guess is too low.
Sorry, you lose. The correct number was 49.
Would you like to play again (y/n)? q
Would you like to play again (y/n)? f
Would you like to play again (y/n)? n
Thank you for playing.
Hints:
* Seed your random number generator with time(0).
* Visual Studio users: Due to a flaw in the Visual Studio implementation of rand(), call rand() once after seeding to discard the first result.
* Use the getRandomNumber() function from lesson 5.9 -- Random number generation to pick a random number.
* Write a function that allows the user to play a single game of hi-lo.
* Write a function that asks the user if they want to play again and handles the looping logic for an incorrect input.).
> Warning: The quizzes start getting harder from this point forward, but you can do it. Let’s rock these quizzes!
Awesome! 😀
Quiz #1 felt pretty straightforward, but Quiz #2 was the real fun! I tried to make use of almost everything I learned so far from Alex, and here’s the result:
- gameFunctions.h -
- gameFunctions.cpp -
- gameHiLo.cpp -
It looks pretty similar to Alex’s own solution, as well many others’s above.
Question: is the default statement in the switch inside my playAgain() function totally pointless? As I’ve marked in the comments, I know it is superfluous since the loop iterates without it as indented if the control reaches there. But I felt including that made the logic clearer. Or am I being too fussy?
Any other suggestions welcome too. 🙂
Yes, the default case is superfluous because your switch is already at the end of the loop. However, it doesn’t really do any harm either, and if being able to document that case makes you feel better, then go with it.
That’s the expert’s opinion we all need. Thanks Alex!
And I hope the rest of the solution is overall okay. That’s almost everything I’ve learned from here so far. 🙂
So I mostly used the same code for question 1 as above, however, I found that using || on my conditionals in the while loop meant that my loop would run until both height and time had been satisfied, whereas && would terminate when only one of the conditions was met. Surely the behaviour should be the other way round?
That doesn’t sound right. Your equality checks may have been incorrect, leading to behavior opposite of what you were intending.
in quiz 2 i replaced this code :
whit mine code :
and my program work correctly . is it ane need to declare
and make if statement work with that ???
Your code is fine! Using the temporary variable makes the intent of the code slightly more obvious, but it’s not hard to figure out in context.
For Q1, I went with a for loop but I probably broke a "rule" about functions being too complicated, but at least it works haha:
None of these functions looks too complicated.
For Quiz Q1., I think this is more modular:
I agree. I’ve updated the solution to be more reflective of yours. Nice work!
"* Visual Studio users: Due to a flaw in the Visual Studio implementation of rand(), call rand() once after seeding to discard the first result."
I don’t think this is only a VS problem. I use Code::Blocks and the rand() function returns the same number as before, plus something.
I also need to call two times to recieve a more randon number.
Hi, Alex. big supporter. My bro actually introduced me to this website 2 months ago and slowly but surely going through it, you might remember he says he used to talk to you quite a lot back in the day (Shemseddine) anyways, I tried accomplishing this task using a for loop and was stuck for a long time and then thought to use a while loop. Why is this
not acceptable - its an infinite loop but i cant seem to see why.
Anyways thanks for the help and looking forward to finishing this series and learning so much 🙂
You never set heightNow, so if heightNow is ever >0, it will always be >0.
I did, maybe I should of posted the full code but everything is the same apart from my calculateAndPrintHeight function.
Again much thanks for your help, I got so frustrated with myself of not being able to do it I’v started this chapter again to refresh myself and hopefully have a better crack at it at the end.
EDIT: PS how do assign expressions to an if statement
for example in free pascal I do
and
and if the if statement returns true it executes everything withing the begin and end.
With c++ to my understanding is that this
would give me an output of 5, so what can I do to avoid this and organize my code.
I managed to figure it out , but I’m absolutely certain that its bad programming.
There are a few things that are wrong with this:
1) You’re using the comma operator in a while statement, which is very unconventional. Comma also evaluates to the rightmost operand, so your while statement essentially evaluates to while (time++).
2) You shouldn’t need the if (heightNow == 0) statement if you fix the loop condition
3) since heightNow is a double, you shouldn’t use the equality operator. Use <= instead in case of floating point error.
Regarding if statements, operator= is used for assignment. Operator== is used for comparison. So you’d want your if statement to look like this:
Ahh I get it now, much thanks!, I’v seen that alot of people in the comments could not complete the random number generator problem. I tried accomplishing the task but not using the techniques learnt in your lessons (well one, mersenne). I got an error on two different occasions so I did this instead - is it still valid or bad code again?
Anyway’s if anyone cant seem to get the mersenne function to work, I think my solution works fairly well.
much thanks again!
srand() should only be called once at the start of the program. Yours is inside the do loop.
Also, the way you’re doing your random numbers will result in a slightly uneven distribution (low numbers will come up slightly more often than higher numbers) but that shouldn’t matter for this exercise since it’s not important to have an even distribution.
No idea if you still post in here, but this was my solution. I just finished first year of computer science and I’m just going through your
guides to touch up on my skills and make sure I understand most things.
I still don’t feel like I’m as good as I should be after one year of university so I’m still looking to be ahead for next year.
If you are still replying, some feedback on the layout & design of my code would be nice.
Thanks =)
Well, thanks a lot for this C++ tutorial, it’s far better than the one in french I found so far.
After looking for the correction, it look’s like I’m close to what you did, I have just a question about the getRandomNumber.
When you first spoke about having a random number between a mini and a maxi, in my mind it looked like :
Is something wrong with this fonction?
Thanks a lot for your time.
Btw, sorry for the "far to be" fluent english.
Yes, if maxi-mini isn’t a divisor of the largest number generated by rand(), you get lopsided results due to the modulo (where some numbers are slightly more likely to occur than others).
Haha, well I got a solution to question 2. Not very elegant though :p
Oops, disregard
in the playGame function.
That was just to tell me what the random number was, for testing purposes.
this is my solution for number 2. I just wanna ask you what are the bad things about my solution? it is fine use void instead bool like yours on play() function? and my main() is so short because few statement placed in other function, it is good or bad? Thank you.
This is fine. Just a minor difference in where you and I put the winning/losing message.
paragraph 3.5 says this is bad, but it is still used in reference solution to 1)
In general, doing equality/inequality comparisons with floating point numbers is dangerous.
However, this is one of the few cases where it works, since:
* 0.0 can always be represented exactly in floating point.
* We’re not doing any math operations on currentHeight between the point where we assign 0.0 to it, and the point where we check if it’s set to 0.0 (so there’s no chance to accumulate floating point errors).
I find the solution to 1st question a bit too large. I did it that way: (Back in chapter 2)
constants.h
main.cpp
PS: With two additions, printout the exact hit time at the end and restart the whole program at it’s end.
Hello Alex, for the first question I took another route from what you put as the answer and I wanted to see if this was a bad choice. Also, just so you know, I am currently using cpp.sh as my compiler due to the fact I am unable to get to my main computer at this time and the one I am using is a little weird when it comes to visual studio, so there is no header for this program.
This looks fine. The use of a different variable for the loop counter and loop condition is clever.
Yeah, the logic behind that for-loop is really nice. Elegant thought.
One thing that occurred to me though is, you don’t need to call the function twice inside the loop. Instead,
can optimise the code. IMHO this looks a little bit better logically as well.
Hope that helps. 🙂
something is wrong with the RNG ,it just keeps showing the same number for two or three intervals
You should only call srand() once at the start of main(). You’re calling it every time randomNumberGenerator gets called.
Just a comment from a mathematician … nice game: you always win 😀
Only if you play semi-optimally. 🙂
Hi, Alex.
It seems to me, that "do-while statement", is more appropriate for quiz number 2, because a statement checks the condition after it has been executed at least once.
Please tell me, if there are any mistakes in this code:
*I’m using C::B for Windows*
Yes, on reflection, I agree with you. I’ve updated the example.
Alex, thank you for your answer, and I have the last question related to quiz number two, and to programing generally. Is there some kind of "gold" code, in case if needed to choose between 3 conditions? Is there a shorthand method for doing a particular type of "if/else if/else" statement? It seems to me, that there are a lot of "more"-"less"-"equal" cases in programing.
Not really. Most common thing to do is:
I’d advise against using the conditional operator to do these tri-state conditionals, as they’re harder to follow and easier to inadvertently mess up.
Hi Alex, first of all thanks so much for your work.
I have a question about the 2nd quiz (high low game), particularly for my function ‘playAgain’.
I preferred to implement it using std::string instead of char but I got an unexpected result.
When the function is called it prints "Would you like to play again (y/n)? " twice, and I really don’t understand why. Can you help me please.
This is my complete program, anyway I think the issue is inside ‘playAgain’ as the rest works as expected.
Another little question.
How can I change ‘getNumber’ function to be sure the user typed a number instead of a character.
I tried typing a character and the program seems to get into an infinite loop inside ‘playAgain’ function.
Any hint will be appreciated.
Thx
After the user enters a number, you can check to see whether it succeeded:
Put this inside a loop to keep asking the user for input until cin doesn’t fail.
Ok, I got it. I understand that I should be careful when using std::cin, and have to be aware of it’s behavior with the buffer.
About the std::cin buffer, is 32767 its maximum size?
This is my new implementation and it seems to work properly.
If there’s a better way please let me know.
Thx again.
The maximum stream size can be accessed like this: std::numeric_limits::max(), which lives in the limits header.
So technically, you should do this:
You’ll only need to use this if you think you’ll have more data in your buffer than 32767 chars.
The problem is that when you enter a number previously, the ‘\n’ character that the user entered is still in the input stream. So the first time you read the stream to get the user input into your string, it reads the ‘\n’ into your string and continues. This doesn’t match your conditional, so it loops one more time. Now the stream is empty, so it waits for user input.
You can fix this by removing the ‘\n’ from the stream before asking the user if they want to play again, like this:
Hey Alex, I need your opinion. I have been using your tutorials to learn C++ and I can’t quite seem to do the two quiz questions above. I have been able to do all the quizzes before these. Do you think I should keep reading on or not proceed until I can complete these quizzes? Some things I asked myself after attempting to write those programs and failing, and after checking the correct answers was: how did you know that some of those functions needed to be of the bool type? When I was attempting both of them, I didn’t even think of doing that. Is there a certain way to think when I read the questions, that will tell me what kinds of functions and what not to use? I feel like if I had a teacher for this, I could learn it no problem but it is kind of hard learning it on my own. I think my main problem is converting what you want me to do in the quiz question into the actual code but I have gotten better! So, thank you very much for your tutorials!
The quizzes in this section are harder than the ones that you’ve seen previously.
That’s intentional: they are designed to challenge you and force you to stretch a bit.
Even if you don’t get it right, as you learn from your mistakes, and can understand why I did something the way I did, you can move on.
If you don’t understand why I did something the way I did, ask.
> Is there a certain way to think when I read the questions, that will tell me what kinds of functions and what not to use?
Figuring out how to structure your programs is something that takes practice. For me, I usually ask: “what are the main things this program needs to do?” and those become functions. If any of those things are complicated or need to be done more than once, they get broken down into smaller functions. From there, it’s just a matter of understanding how to use parameters and return values effectively.
This is my solution, without following all the hints. Please tell me guys, how bad is it?
srand() should only be called once at the start of your program, so it needs to be outside the loop.
Your code is hard to follow because you have loops inside of loops. Functions would be good here.
I also think the continue at the end of main() may be unnecessary.
Heyho, Alex!
i’ve solved the 2nd problem and this is my solution :
like what you can see there, i got some different algorithma from yours.
so, i wanna ask you what are the bad things about my solution? except the use of "goto" of course.. i use it because im a little bit stuck on how to ask player to play again.. haha.
thx before.. your tutorials are great :3
I see a couple of things:
1) You should only call srand() once. Your srand() gets called every game.
2) Your main() function is a bit long -- if you broke it up into more functions, then I think you’d have an easier time using a loop to replay instead of goto.
Hi Alex,
Is this good practice (to use the static variable) or should I just move the first two statements to the main function?
Yes, this is good. Variable mersenne will only be initialized once, but you’ll get a different number each time you call the function.
You can actually solve the equation for "seconds" of the "Ball falling from a tower" problem, and let the height == 0.
Then you can post the exact time-elapsed when the ball hits the ground.(Using Visual Studio 2015 Community)
========================================================================================================================
// quiz2ques4.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include "constants.h"
#include "math.h"
double getInitialHeight() {
using namespace std;
cout << "How high is the tower, in meters? ";
double height(0.0);
cin >> height;
return height;
}
void printHeightChart(double height) {
using namespace std;
using namespace myConstants;
double instantHeight = height;
for (int seconds = 0; instantHeight >= 0 && seconds <= 10; seconds++) {
instantHeight = height - myConstants::gravity * seconds * seconds / 2;
if (instantHeight < 0.0) {
double lastSeconds = (sqrt((2 * (height) / myConstants::gravity)));
cout << "At " << lastSeconds << " seconds, the ball has landed." << endl;
break;
}
cout << "At " << seconds << " seconds, the ball is at " << (instantHeight > 0 ? instantHeight : 0) << " meters." << endl;
}
return;
}
int main()
{
double height = getInitialHeight();
printHeightChart(height);
return 0;
}
Hello Alex, how are you
I was recently trying to solve #2 and wrote this solution:
Your solution is undoubtly the best one. I just want to ask you, is my program acceptable or I am doing something that shouldn’t be done for #2 problem?
Your program has a few issues:
1) You should only call srand() once, not every time game() is run. Move it to the top of main().
2) Avoid using goto. Use a loop instead.
3) You call game() in two different places. Consolidate this into a do-while loop.
4) I’m not sure why game() returns anything since you always return 0.
5) You should avoid using system() calls.
6) The if statement to determine whether the user has lost isn’t needed. The user lost if the for loop terminated. So you can move the “you lost” string underneath the for loop and make it unconditional.
Can command prompt only print 296 lines? When I tried my solution (above posted) with a large input (1236549), it prints 296 lines of output and rest are not printed. I also noted that the only last 296 lines were printed. For example: if my input is 1236549, the first line the program prints is "At 207 seconds, the ball is at height: 1.02659e+006" and the last line my program printed was "The ball is at height 0 meters now". I first thought that it’s an overflow problem. I changed the double variables to long double but the result remained unaffected. I then wrote this:
Result was counting of numbers from 4 to 299 where each number was printed in a new line. Does all command prompts are limited to print maximum 296 lines or this is a machine specific problem? Whatever this is, because the whole tutorial seems to use non-gui programs, you should tell the readers about this limitation of CMD somewhere in this tutorial 🙂
The limitations of the console vary depending on operating system. In all likelihood, your program printed all of the lines, but the buffer on your console was set to only retain the last 296 lines. There’s likely a way to change how large the console buffer is, but that’s outside the scope of this tutorial. Ask Google. 🙂
Oops…I forgot to #include constants.h
The following is my solution:
Could it be better?
Hi! This tutorial is great and very useful. I am running into something odd in my solution to the first problem. It runs almost fine, except that it prints a seemingly random (but not infinite) number of "At (time) seconds, the ball is at height: 0" messages after the ball has hit the ground.
This is my main function (everything else is the same as the original program):
I agree that your solutions are quite a bit better, but I am curious as to why this is happening.
You’re calling calculateAndPrintHeight() with argument height instead of argument initialHeight.
This is pretty straightforward to discover using the debugger.
There seems to be an issue with this random number generator. It always gives 10 when you first run it.
It sounds like maybe seeding the random number generator is failing for some reason.
Can you tell me the following:
* What compiler/OS are you running?
* sizeof(time_t) on your system
* sizeof(unsigned int) on your system
* Whether static_cast<unsigned int>(time(0)) always comes out the same number?
Let me first say thank you very much for writing and maintaining such a fantastic tutorial on C++. I am new to C++ and am learning a lot for your work.
Here are the information you asked for:
* What compiler/OS are you running?
I am using the latest version of Xcode on the latest version of Mac OS X.
* sizeof(time_t) on your system
8
* sizeof(unsigned int) on your system
4
* Whether static_cast<unsigned int>(time(0)) always comes out the same number?
No. It changes every time I run it.
By the way, I am not getting 10 anymore. I was consistently getting 11 about 20 minutes (maybe) after I posted my post. Today as of right now I am consistently getting 75 every time. Could it be that the seed changes rather slowly so the random number generated changes even slower?
If static_cast<unsigned int>(time(0))) is coming out a different number every time you run your application, then your random number generator should generate a different sequence every time you run your program. However, from the symptoms you’re seeing, it sounds like your seed value is only being changed periodically
Are you sure static_cast<unsigned int>(time(0))) changes _every_time_ you run your program, and not just once every 20 minutes or so?
Normally when casting a larger int to a smaller one, compilers truncate, keeping the low bits (which are the ones that change every second, in this case). Maybe your system is doing something else, since technically casting a larger int to a smaller one results in undefined behavior.
Try this instead:
and see what happens?
I am having the same problem (in Visual Studio) and I tried what you suggested here. It still produces the same number every time it starts. I waited ten minutes, then tried it again, and the same problem occurred except that the repeated number was different (I just tried it again after typing up this comment, and the repeated number has changed again. Both times it went up by two). So I suppose it doesn’t actually change every time the program is run, just every so often.
It took a while, but I discovered the root cause of the issue.
In Visual Studio, the first result of rand() is heavily dependent upon the seed value. Since the seed value from time() isn’t changing much, the first result from rand() isn’t changing much either. getRandomNumber() is then compressing that into the same number.
After the first result, the sequence of numbers generated from rand() appears to be properly randomized.
The easy solution is to discard the first result from rand(). I’ll update the examples accordingly.
Hey Alex,
the second if is useless and gives out a compiler error
anyways I love your tutorials thank you for making them!
Oops, copy/paste error. Thanks for pointing that out.
Name (required)
Website