Search

5.x — Chapter 5 comprehensive quiz

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:
* If your compiler is C++11 capable, use the Mersenne Twister algorithm from chapter 5.9 -- Random number generation to pick a random number.
* If your compiler is not C++11 capable, you can use rand() (also presented in chapter 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.

Show Solution

2b) Update your previous solution to handle invalid input (e.g. ‘x’) or valid input with extraneous characters (e.g. “43x”) when the user is guessing a number.

Hint: Write a separate function to handle the user inputting their guess (along with the associated error handling).

Show Solution

6.1 -- Arrays (Part I)
Index
5.11 -- Introduction to testing your code

563 comments to 5.x — Chapter 5 comprehensive quiz

  • Lennart Torstensson

    Firstly, thanks for an interesting and educational site. Secondly, this challenge feels like the first that I want another set of eyes on. Mostly to see if my code is sane. I have tried to follow best practice.

    • Hi Lennart!

      - Line 7, 20: Initialize your variables with brace initializers.
      - Line 32, 33: Duplicate comparison of `selection` to 'y'. You can move the comparison into the loop and return immediately.
      - Inconsistent formatting, use your editor's auto-formatting feature.
      - Line 58: Use single quotation marks for characters.
      - Line 66+: Should be do-while.
      - Inconsistent and overlapping naming (Modifier prefix + hungarian vs lower camel case vs upper camel case. Try using different name styles for variables, functions, and types.

  • Toms

    What about this code?

    • - Initialize your variables with brace initializers.
      - Don't pass 32767 to @std::cin.ignore. Pass @std::numeric_limits<std::streamsize>::max().
      - Use false/true for booleans.
      - Use `using` for type aliases.
      - Don't use `exit`.
      - Magic number/string: 7.
      - Line 81+: Should be do-while.

  • Arnima

    Hello!
    For question #2, my program seemed to work appropriately, but compared to the given solution, it was a few lines longer, so I was wondering if there were any key places I could improve the code for greater efficiency. Other notes would also be greatly appreciated!

    *Note: "main.h" is for a header file with forward declarations for playGame() and playAgain().

    • - Initialize your variables with brace initializers.
      - Don't pass 32767 to @std::cin.ignore. Pass @std::numeric_limits<std::streamsize>::max().
      - Don't use recursion (A function calling itself). Use a loop.
      - Don't mix '\n' and `std::endl` without a reason.
      - Magic number: 7.
      - `numberGuess` should be declared inside of the loop.
      - Line 47 is always true.
      - Line 39+: You know how often the loop will run before you start it, use a for-loop.

      You should try writing the game using loops, they're essential.

      • Arnima

        Thank you so much! I edited the program in accordance to the guidelines for question #3 while incorporating your notes. Are there any ways this version could improve as well?

        • - Line 50: Initialize your variables with brace initializers.
          - Line 40, 43: Duplicate comparison of `yn` to 'y'.
          - Line 48: Magic number: 7. Use `playCountMax`.
          - Line 64: Should be constexpr.

          Looks good otherwise!

  • @Nascar and @Alex, I tried so fucking hard to make this good. Did I do good? PLEASE PRAISE! ;___;

    • Hrm mh
      - Line 10, 15: Brace initialization.
      - "GetRandomNumber" is inconsistently named.
      - Magic numbers: 1, 7, 100.
      - `tryAgain::yesOrNo` should be a char.
      - You're using the same name style for variables and functions, this can lead to confusion.
      - Line 58 is always true.
      - `highLow`'s return value is unused. It should be `void`.
      - Use false/true for `bool`s, not 0/1.
      - `main::stillPlaying` can be removed. Use `tryAgain()` as the loop's condition.

      Praise!
      - You're seeding the rng only once.
      - You're not mixing '\n' and `std::endl`.
      - You're clearing `std::cin` correctly.
      - No duplicate comparisons.
      - You seem to have understood `while` loops. `while (true)` sometimes takes people long to learn.

      There's still room for improvement, but no one expects you to remember everything after a couple of small projects. Try applying my suggestions to your code to make sure you understand how to do so. If you continue solving the quizzes and trying hard, your code will get squeaky clean d:-)

      • Thanks! I will keep working through these lessons; I have a few, specific inquiries if you've got time.

        - I'm not sure how to approach clearing up the magic numbers in this code, could you point me in the right direction? I know that the goal here is to make them dynamic by referencing the variable from which they're pulled... I'm just having trouble figuring out a good way to do that.

        - How do I incorporate brace initialization in lines 10 and 15? I'm... not sure. The stuff out of the random #include is still looking a little Greek to me.

        - It was suggested to me that I call std::random_device as a function and use it to initialize std::mt19937 mersenne(), is this alright to do and will that allow me to remove the <ctime> include?

        THANK YOU FOR PRAISE AND CRITIQUE, MUCH APPRECIATE!

        • > magic numbers

          Then use those whenever you loop/print/generate.

          > brace initialization in lines 10 and 15

          > std::random_device
          `std::random_device` generates deterministic (non-random) numbers if the host system doesn't have a random source. `std::random_device` was used on learncpp, but too many people were experiencing this issue. You can use `std::random_device`, if you verify that the host supports it by checking `std::random_device::entropy()`. If the host doesn't support it, you'll have to fall back to another source (eg. `std::time`).
          Using `std::random_device` can improve the randomness of your numbers, but it doesn't decrease your code's size.

          > I tried to implement everything.
          Apart from the 2 things you didn't know how to do, this is left
          - `tryAgain::yesOrNo` should be a char
          You're not expecting an input longer than 1 character, so there's no need to use more memory.

      • I tried to implement everything.

  • Merlin Helm

    Dear teachers.

    Is this solution for 1) correct? I used a "for loop" instead of an "do while" loop. It gives me the output like expected but I want to make sure that everything is correct.

    With regards,
    Merlin

    • Hello Merlin!

      It's correct and can be improved

      - Initialize your variables with brace initializers.
      - Limit your lines to 80 characters in length for better readability on small displays.
      - Use double literals for doubles (2.0 instead of 2).

  • Please, let me know how this could be improved. One thing that is not working well is when else part of the getChar() function. This does not prompt a new question.

    • Actually this seem to do exactly what is asked from the program, but it seems to be long, any way that I can improve it.

    • - Line 19, 22: Initialize your variables with brace initializers.
      - Limit your lines to 80 characters in length for better readability on small displays.
      -  Don't pass 32767 to @std::cin.ignore. Pass @std::numeric_limits<std::streamsize>::max().
      - Use std::rand instead of its global-namespaced counterpart.
      - Don't use `goto`. Use loops.
      - Magic number: 7
      - Line 56 has no effect.
      - Inconsistent formatting. Use your editor's auto-formatting feature.

      > but it seems to be long
      Overall length isn't a problem, wink wink. The problem is that your code consists of a single function pretty much. Splitting it up will make your code more readable. Have a look at some other submissions for ideas on how to split.

  • Jonathan

    Just wanna share my code and see if it could be improved.

    • - Don't pass 32767 to @std::cin.ignore. Pass @std::numeric_limits<std::streamsize>::max().
      - Line 23 has no effect. If there was an error, it would've been cleared before.
      - Line 36, 38: Use brace initialization.
      - Inconsistent formatting. Use your editors auto-formatting feature.
      - Seed random number generators only once. Seeding them multiple times with the same seed will cause identical "random" numbers.
      - `findLarger` and `findSmaller` can be replaced by `std::min` and `std::max`.
      - Magic numbers: 0, 7, 8, 100. Add constants.
      - Line 78: You can omit parts of for-statements. `for(; guessCode < 8; ++guessCode)`.
      - Line 80+: Should be moved out of the for-loop.
      - Line 90: Comparisons are executed left-to-right. The first comparison yields a bool, you're then comparing this bool to `larger`.
      - Line 95: `break;`.
      - Avoid abbreviations.
      - `getContOrNot`: You're one of the very few that wrote this function without duplicate comparisons, good job!
      - Line 132+: Should be `do {} while (getContOrNot()). `getContOrNot` should clear the buffer, the caller doesn't care where `getContOrNot` gets the input from.
      - Print a line feed when your program is done to prevent mixed lines.

  • noobmaster

    Looking for advices for my solution and please answer my question at line 13

    • - Initialize your variables with brace initializers.
      - Limit your lines to 80 characters in length for better readability on small displays.
      - Don't pass 32767 to @std::cin.ignore. Pass @std::numeric_limits<std::streamsize>::max().
      - Line 51: That's an assignment
      - Use single quotation marks for characters.
      - Magic numbers: 1, 7, 100.
      - `tries` and `count` can be calculated from each other. Remove one.
      - Line 54: Could also be `tries => 1`.
      - Inconsistent formatting. Use your editor's auto-formatting feature.

      Line 13 calls `operator()` on `random`, which generates a random number uniformly distributed from `min` to `max` (inclusive). Operator overloading is covered later.

  • Lawrence

    Hi, how does my solution for #1 look? Thanks

    • - Use double literals for doubles.
      - Name variables descriptively.
      - `distanceFallen` should be declared inside the loop.
      - Use ++prefix unless you need postfix++.
      - "calculateTimeAndHeight" is a bad name. The function does more than calculations.

  • Matias

    Here's my solution (w/o error checking for the user guess entered - it can potentially be added on getUserGuess() function):

    • - Initialize your variables with brace initializers.
      - Limit your lines to 80 characters in length for better readability on small displays.
      - Use --prefix unless you need postfix--.
      - Seed random number generators only once. Seeding the multiple times with the same seed will cause them to produce identical sequences.
      - Inconsistent formatting. Use your editor's auto-formatting feature.

      Well structured!

  • Torraturd

    I was wondering if the I did was good practice or not since it was both different and longer than the actual answer to the question

    • * Initialize your variables with brace initializers.
      * Limit your lines to 80 characters in length for better readability on small displays.
      * Don't pass 32767 to @std::cin.ignore. Pass @std::numeric_limits<std::streamsize>::max().
      * Magic numbers: 1, 7, 100.
      * Avoid static variables.
      * @hi_lo's control flow is all over the place. Have a look at some other solutions. It seems you're having some trouble using loops.
      * Line 38, 39 and 45, 46: Duplicate code.
      * Line 51: Unnecessary comparison.
      * Avoid recursion (A function calling itself).
      * Line 66 and 68+: Duplicate comparison of @choice to 'y' and 'n'.

      • Torraturd

        Thank you so much for your advice! I tried to implement it and here's what I got:

        side note: When I write code, should I focus on having it be simple and understandable or should I focus on being efficient and compact as possible?

        • * Line 8, 12: Initialize your variables with brace initializers.
          * "I'm thinking of a number..." well that's a cheap fix. Declare a namespace holding the constants of your game. Then use those for the message and the logic.
          * Line 22, 69: Use single quotation marks for characters.
          * Avoid abbreviations. The time you save writing them is time wasted reading them.
          * Line 54: That expression is always true.
          * @hilogame still calls itself through @playagain. Add another loop.
          * Line 60: Only initialize variables to a specific value if you need than value. If you don't, initialize with empty curly brackets (They produce the default value).
          * Line 65, 68, 72: Duplicate comparison.
          * You're using the same name style for variables and functions, this can lead to confusion.

          > should I focus on having it be simple and understandable
          Yes

          > should I focus on being efficient
          Efficiency often comes with simplicity. Focus on simplicity until you really understand the language.

          > compact
          No. Compact code is often harder to understand without being beneficial for anything. If you find yourself writing huge blocks of code, split it into multiple functions or files.

  • Ryan

    This is my code for the second task. It seems working well but not quite sure if it is okay to do like this because many people here used bool function.
    Please correct me if I'm wrong.

    • * Initialize your variables with brace initializers.
      * Limit your lines to 80 characters in length for better readability on small displays.
      * You can only play the game twice.
      * @main: Missing return statement.
      * @Continue should return a bool, because there are only 2 states.
      * Seed random number generators only once.
      * Magic number: 7.
      * Line 23: Unnecessary comparison.
      * Line 26: Should be a return. "you lose" will always be printed otherwise.
      * Inconsistent formatting. Use your editor's auto-format feature.

  • OmegaX128

    Heyo! I've been going through these tutorials and trying my best to maintain style and clear, concise code. I noticed that the solution I came to was quite different. Any thoughts?

    • * Line 54, 65, 67: Initialize your variables with brace initializers.
      * Line 7, 53, 77, 94, 96: Limit your lines to 80 characters in length for better readability on small displays.
      * Line 28, 33, 84, 89, 120, 125: Don't pass 32767 to @std::cin.ignore. Pass @std::numeric_limits<std::streamsize>::max().
      * @Guess should be an enum class.
      * Line 94-96: Duplicate code. Restructure your loop. Have a look at the solution or other submissions.
      * Line 101, 104, 137: These make it hard to follow your programs control flow. Again, restructure the loop.
      * Line 109+: Same as the previous 2 comments.

      • OmegaX128

        Thanks for responding! I tried to implement your feedback. How does this look?

        • Already better than your last submission. Here are some things that went wrong in your update or I didn't spot last time:

          * Line 20: @_int64 is an internal type (Don't use anything that start with an underscore).
          * Line 20: You're mixing types. @limit is a @std::streamsize. Use that or auto and constexpr.
          * Line 53+, 56+: Should be wrapped in curly brackets.
          * Line 65+: Should 'continue', because you already know that it's not the input you want.
          * Line 77: Should be else, everything but 'y' and 'n' was excluded by the check above.
          * Line 87: Use brace initializers.
          * Line 91: Should be constexpr.
          * Line 111: Should be else.
          * Line 95+, 118+, 137+: Duplicate code.

          You don't have to update your entire code again, but you should understand everything I pointed out and apply it next time. You should definitely fix the duplicate code to understand how to avoid it in the future. Look at other people's submissions and the solution. If you can't figure it out, let me know and I'll show you how to do it.

          Please use the edit function instead of deleting and re-posting. The code highlighting works after refreshing the page.

  • Akhil

    Is this okay... when i tested it... it worked fine, if not pls tell

    • * Line 108, 116, 123, 21, 38, 39, 41, 43, 7, 13: Initialize your variables with brace initializers.
      * Line 7, 37: Limit your lines to 80 characters in length for better readability on small displays.
      * Line 110: Don't pass 32767 to @std::cin.ignore. Pass @std::numeric_limits<std::streamsize>::max().
      * Don't use goto.
      * @main: Missing return-statement.
      * Magic numbers: 7, 8.
      * @wonStat should be a bool.

  • Lorenz

    for the first time my version is quite different than the results, can you advice on this regarding exercise 2a?

    thank you

    • * Line 8, 13, 40, 57: Initialize your variables with brace initializers.
      * Line 7, 8, 13, 14, 18, 36: Limit your lines to 80 characters in length for better readability on small displays.
      * Line 61: Don't compare booleans to false/true.
      * Booleans are false/true, not 0/1.
      * Line 50: @selection cannot be 'y' or 'n' here. Should be while (true).
      * Magic numbers: 7, 8.
      * @main: There's no need for @contin, you can call @playAgain in the loop's condition.

      • Lorenz

        * Line 61: Don't compare booleans to false/true.
        * Line 50: @selection cannot be 'y' or 'n' here. Should be while (true).

        can you explain please? how shall I do that?

        * char selection;
        Ho do I initialize a char variable with braces? what is the "default" value?

        thank you for helping!

        • * Line 61: Don't compare booleans to false/true.

          * Line 50: @selection cannot be 'y' or 'n' here. Should be while (true).
          If @selection is 'y' or 'n', the switch statement already returned from the function.

          > Ho do I initialize a char variable with braces? what is the "default" value?
          Empty braces initialize to the type's default value. For chars, it's 0.

  • Artun

    Hi all, first time posting here. First of all, mandatory thank you to Alex for this great website and to those who help out in the comments.

    I believe I have the program working with error handling and tried to keep the code clean, and follow good practices. Any advice on errors/best practices would be appreciated :)

    • Hi Artun!

      * Line 11, 16: Initialize your variables with brace initializers.
      * Line 11, 12, 16, 22, 30, 31, 57, 60, 61, 64, 65, 68, 81, 84, 87: Limit your lines to 80 characters in length for better readability on small displays.
      * Magic numbers: 1, 7, 100.
      * @timesGuesses should be declared in @playGame.
      * Line 88, 91, 96: One comparison is enough.

      Well structured, error handling looks all right.

  • Dimbo1911

    Same for the nr. 2 :)

    • * Line 22, 23: Initialize your variables with brace initializers.
      * Line 22: Limit your lines to 80 characters in length for better readability on small displays.
      * Line 11, 15: Don't pass 32767 to @std::cin.ignore. Pass @std::numeric_limits<std::streamsize>::max().
      * Seed random number generators only once.
      * Magic number: 7
      * Line 77-80 should be [return (answer == 'y');]

  • Dimbo1911

    Quiz number 1. Any remarks or advices welcomed

  • Mitch Zakocs

    Hi Alex and nascardriver :D
    Just finished the hi-lo game, was a really good challenge!
    I used the effolkronium random header file instead of using std::mt19937 because I was having some issues with my getRandomNumber function and just decided to scrap all of it and use the library.
    Thank you for any feedback you can give!

    I did run into an issue where playAgain was unable to find runGame(), so I used the forward declaration at the top to combat this. There might be a better way but I felt like this was a better solution than creating a header file or another cpp file.

    • Hi Mitch!

      * Line 27: Initialize your variables with brace initializers. You used copy initialization.
      * Line 26, 44: Limit your lines to 80 characters in length for better readability on small displays.
      * Don't use @std::exit.
      * Use ++prefix unless you need postfix++.
      * Line 37: Unnecessary check.
      * @winStatus should be a bool.
      * Line 13, 19, 45, 48: Don't use recursion (A function calls itself). Use loops.
      * Line 45 and 48 are not conditional. Move them out of the if.

  • ethano

    would you call this passing the test? It seems fine, just i dont know if i fully got it right (as you wanted it)

    • * Line 3: Initialize your variables with brace initializers. You used direct initialization.
      * Line 16, 54: Initialize your variables with brace initializers.
      * Line 5, 21, 30, 77: Limit your lines to 80 characters in length for better readability on small displays.
      * Line 23, 69: Don't pass 32767 to @std::cin.ignore. Pass @std::numeric_limits<std::streamsize>::max().
      * Don't use "using namespace".
      * Auto the auto-formatting feature of your editor.
      * Seed random number generators only once.
      * Magic numbers: 1, 7, 8, 100.
      * @game: Unused return value.
      * @again should return a bool.
      * Line 37, 40: Should be else if and else.
      * Line 59: Should be else if.

  • Arthur

    I liked the ball drop and worked on it the first time , some modifications for this quiz. still would like to find out if  I can organize output better having variable numbers printing into straight columns.

    my constants.h

    io.cpp