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 range-based for 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!

Question #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

Question #2


a) 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:
* Use the Mersenne Twister algorithm from 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.
* Avoid magic numbers by defining constants for the minimum/maximum random range and the number of guesses.
* In an if-statement, if you already checked 2 numbers for equality and compared them with either the < or > operator, but all checks failed, the relation between the numbers must be the one you didn’t check. For example, if guess is neither equal to nor less than number, it must be greater than number.

Show Solution

b) 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

768 comments to 5.x — Chapter 5 comprehensive quiz

  • Swaraj

    Is this a good solution for quiz 1:

    • nascardriver

      You tell me what's wrong
      - Line 8, 28, 41, 52, 55 (Lesson 1.4)
      - "\t", "\n" (Lesson 4.11)
      - Line 28 again (Lesson 4.8)
      - "accduetog" (Lesson 1.7)
      If you need help, please ask

      Additionally
      - Your naming is inconsistent (All lower case, camel case, upper camel case, all upper case). Choose one name style and stick to it.
      - Your formatting is inconsistent. Use your editor's auto-formatter.
      - You're calling `TimeTakenToHitGround` in every iteration of your loop. Call it once and store the return value in a variable. Use that variable in your loop's condition.
      - math.h is a C header. C++ has cmath.
      - `sqrt` should be `std::sqrt`. This was wrong in the lessons too, sorry about that.

      • Swaraj

        I understood everything except for "-Line 28 again (Lesson 4.8)".
        Thank you for this wonderful tutorial and for replying.

        • nascardriver

          - Line 8, 28, 41, 52, 55: Should be initialized with list initialization.
          - "\t", "\n": Should use single quotes, because they're characters.

          - Line 28 again: Should be 2.0 to prevent accidental integer arithmetic.

          - "accduetog": Don't use abbreviations.

          • Swaraj

            "Should be 2.0 to prevent accidental integer arithmetic"

            I thought of that but wont the integer literal 2 be promoted to 2.0 because heightoftower and accduetog are type double......or should I use 2.0 because it is good programming practice in
            general?

            • nascardriver

              2 will be promoted to `double`, because `heightoftower` is a `double`. It's bad practice to mix types in arithmetic, so 2.0 should be used.

  • samira

    I was wondering if my solution is good enough as I implemented all the steps using functions!

    • nascardriver

      I'll give line numbers, you guess what's wrong with these lines. If you need help, just ask

      - Line 36, 37, 72, 76
      - Line 47
      - Line 100

      In addition to those

      - Avoid recursion (A function calling itself) (`startPlayingGame` -> `replayTheGame` -> `startPlayingGame` -> ...). Your program will crash after a couple of runs because you run out of stack memory. Use loops instead.
      - Printing a space before a line feed doesn't make sense. If you don't like having the \n touching the last word, you can put it in a separate string literal ("Correct!You win!" "\n"). The compiler will concatenate the literals.

  • samira

    Do you think this  can be a short solution for Question #1 with preserving all the functions used in the first place?

  • Innervate

    This was my attempt at the second questions. I'm not entirely comfortable using for-loops, so I fell back to using While and do-While, and relying on if-statements. I would appreciate it if anyone would give me some advice on where I can improve, or what steps I should start thinking about in order to optimize it.

    Many thanks!

    • nascardriver

      HI!

      Line 39 should be `else if`, line 46 should be `else`.
      Line 33-37 and 42-45 should be moved out of the conditional part.
      Magic string: 7. Use your constant.

      • Innervate

        Thanks for the feedback nascardriver!
        for line 7, How should I approach to use my constant to replace the while statement? I am guessing I should use the condition while(RemainingGuesses > 0) instead of while(true). But doing so without another return statement gives me the error "Semantic issue: Control may reach end of non-void function".

        I have changed the following:

        • nascardriver

          Not line 7, the string "7" in what is now line 85. You can move `RemainingGuesses` above that line and use it to print the message.

          • Innervate

            Ahh okay that makes sense. is it still alright to use the condition "while(true)" in GetPlayerGuess() to test for invalid input?

            This is my updated code:

  • Eric

    Hey, just FYI - the error check doesn't prevent a user from entering a real number (double). When ::cin is expecting an int it therefore truncates the decimal? if so how would I detect a double type input?
    Thanks!

  • Eric

    Firstly thanks for this tutorial series! You're helping a lot of us learn to program well; I'm grateful.

    I want to keep all of my quiz solutions in an efficient manner. Do you have a suggestion for storing/ managing these? it seems like creating a project in Visual studio for each of these is a bit of overkill.

    Cheers and thanks again!

  • phil

    If I don't enter anything and just press enter, when asked to enter a number. I get flashing cursor on the next line. Is there a way to fix that ?

  • RJ

    Could someone critique my work I want to see how i'm progressing. I know there are many ways to solving problems in C++.

    This program was separated into different files when i made it, but I posted it like this just to keep it simple.

    • nascardriver

      `GenerateRandomNumber` isn't random. Sees random number generators only once.
      `&` is a bitwise and. You probably meant to use the modulus operator `%`.
      Use your editor's auto-formatter.
      Don't use goto, use loops.
      Magic string: 7. Use your constant.
      Use ++prefix unless you need postfix++. postfix++ is slower.
      Use characters for characters. Using integers is wildly confusing.
      Line 83 is always true on the first iteration. Use a do-while-loop instead.
      Separate code into as many functions as possible to make it easier to read, maintain, and reuse.

  • Saiyan

    This is what I have. Thanks for sharing your knowledge. Always regretted dropping out of Intro to C++ so many years ago.

    • nascardriver

      Hi!

      - Name variables descriptively. "x" isn't helpful.
      - Compile-time constants should be `constexpr`.
      - Line 59 is always true.
      - The caller of `playAgain` shouldn't care about what the user input looked like. Return a `bool` instead. Then you can remove line 83 and 87 and just call `playAgain` in the main loop's condition.

      • Saiyan

        Thanks for the feedback! Regarding your last point, would something like this be more preferable?

        • nascardriver

          Yes, that's what I meant. Now the caller doesn't have to worry about how the user interface is implemented. Say you translate your program to french and you use 'o'/'n' as input. You just have to update `playAgain`, and not every call to it.

          You never need an `if`-statement like this

          it can and should be replaced with

          You now have a duplicate comparison of `ch` to 'y'. That can be avoided by checking `ch` inside of the loop.

  • M.J

    Hello everyone.
    This is question #2
    i copied the code of part b and used it in my function to validate user input. however it shows zero and continues when i test invalid input. can anyone suggest solution?

    • nascardriver

      Please use an auto-formatter. You code is hardly readable.

      • M.J

        yeh sorry about that, I updated.

        • nascardriver

          You're returning from your `while (true)` loop no matter what happened before. Even if you detect invalid input in line 32, you're returning in line 43.

          Other notes:
          - `generateRandomNumber` isn't random. Seed random number generators only once.
          - Enable compiler warnings, read them, fix them.
          - By returning a `char` from `getUserChoice`, you're forcing the caller to perform another check for 'y'/'n'. Return a `bool` instead.
          - Magic numbers/strings. Add constants.
          - Use ++prefix unless you need postfix++. postfix++ is slower.
          - Line 102 is always true.
          - Line 106-120 and 126-142: Duplicate code.

          If you have questions to any of those points, please ask. Feel free to post your code for review when you're done with the quiz :)

          • M.J

            I tried fixing most issues you mentioned. i tried getting rid of the extra duplicate code. i ended up with a smaller block of duplicate code :p
            - i ran the program several times and got different random numbers, so i couldn't figure the random number generator's seeding part you mentioned.
            - i have "w-error" activated in code blocks as mentioned in ch 0.11
              the program runs fine now.
            here is the updated version.
            THANKS a lot for your efforts... much appreciated. :)

            • nascardriver

              > I tried fixing most issues you mentioned
              - `generateRandomNumber`

              Outputs the same number over and over again, because you're re-seeding `mersenne` every time, resulting in the random sequence being reset. Make `mersenne` `static` so it only gets created once no matter how often the function is called.

              - compiler warnings
              It looks like you're not compiling with -Wall -Wextra. There are still warnings, because the parameters of `gamePlay` are unused.

              - getUserChoice
              Looking good now :)

              - Magic numbers/strings
              Still there. Add a constant for `7`, use that in line 108, 112, 149.

              - ++prefix
              Yep, gone.

              - Line 102 is always true
              Correct fix

              - Duplicate code
              You can move the game part (Line 104-164, but without 132-140 and 153-161) into a new function. That will get rid of the duplicate code and the `goto`.

              Notes on your updated code:
              - Line 78 and 86 are basically returning the value of `userChoice`. You can remove these lines and add an unconditional `return userChoice;` to the end of `replay`.

              • M.J

                hey! thank you fro your note.
                - I declared 'mersenne' in an namespace. as i saw it in one of the comments, that seems to have solved the issue with random number generation. thank your for pointing that out.
                - I added the provided extensions to my compiler settings.
                - i decided to go for a do while loop as it seems to have solved most problems lol :))
                this is my final version of the code :)

                p.s.
                I want to solve more similar problems to try improve my logic and computational thinking before advancing to the next chapters. If you happen to have any useful resources on where i can find such. Please be generous.
                Thank you again.. :)

                • nascardriver

                  > logic and computational thinking
                  The best source to get that is by practice. Keep on programming and you'll get better.

                  Unless you're using notepad, your editor probably has a feature to auto-format your code. You should look into that.

  • Raul T

    Hi!
    In the first instance I wanted to put the 'secondsPassed post-increment' in the for loop 'end-expression', but from that resulted in a small bug.
    Assignment #1

    • nascardriver

      > I wanted to put the 'secondsPassed post-increment' in the for loop 'end-expression'
      If you don't know how often a loop will run, a `while`-loop is usually the better choice.

  • These lessons have been awesome! I have followed from the very first chapter, and I can tell my skills are better now. I hope to land a job with this skill. Take a look at my solution. Could I have done anything better?

    constants.h

    main.cpp

  • Fosterwerks

    Just wondering if my uses of const and static inside my version of startGame() are good uses or not. (Did not include the whole program for brevity). Thanks!

    • nascardriver

      Hi!

      `mt` is right, but `dist` is problematic. `startGame` can be called multiple times, with different `numRange`. But `dist` is only created once, at doesn't care about any `numRange` after the first one.

  • mindenki

    Hey! Here is my solutioon for question #1? Is it any good?

    • nascardriver

      If it works, it's good.

      Suggestions:
      - Initialize variables with list initialization.
      - Use double literals for doubles (0.0).
      - Duplicate calculation of the current height. Add a variable.
      - Line 22 and 24 break your program. The given formula calculates this distance fallen since the beginning.
      - Line 32 is never false.

  • Nathuunn

    I made height a global variable, im wondering if thats okay, and if its not why?

    • nascardriver

      Global variables are bad, we explained why in lesson 6.9. You can get rid of it with minimal modifications to your code, just add a return value to `calculateAndPrintHeight`.
      Avoid `static` local variable. `incrementSeconds` isn't reusable. Say you wanted to let the simulation run several times, each time asking the user for another height, you can't do that.

  • veqes

    Hello again! I had a go at Q2 and I ran into a really frustrating problem. I don't know how to avoid using goto at the end of my "win" condition. Could you please have a look at my code and give me some clues on how to avoid it in this case?
    I'd appreciate feedback on the rest of the code as well if possible :)
    Thank You!

    • nascardriver

      `getRandomNumber` isn't random. Don't re-seed random number generators.

      Use `bool` with `false`/`true` for values that have only 2 options, not `int`.

      When the number is correct, you can `break` the loop. Now you just have to move the "Sorry" message (Don't duplicate it!), or find a way of remembering the result until after the loop, so you only print the message when the user lost.

  • Anto

    i know it could be better, but i tried to change the least possible.

  • Gabe

    Quiz 2

    What could I have changed? I feel it could have been better.

    constants.h

    main.cpp

    • nascardriver

      - Initialize variables with list initialization.
      - Magic string: 7
      - "user_input" isn't a good name for what the function does. "play_game" or similar would be better.

      If `validate_user_input` returns false, the user loses a guess. If that's not what you intended, you could decrement `count` in the event of an input failure or use a different kind of loop.
      Your play again loop is good, many people get this part wrong ;)

      • Gabe

        Thanks again! Yeah I was aware of the "user loses a guess" part;however, I thought my code was a bit messy the way it was already, so I didn't add it I guess.

        Also, for the "magic string, " I should have added the NUM_OF_GUESS instead?

  • Sahib

    Can I get some feedback?

    • nascardriver

      - Inconsistent formatting. Use your editor's auto-formatting feature.
      - Magic number/string: 7
      - Your main loop can be simplified by using a do-while-loop. You don't need `replay` if you do that. Try rewriting it to make sure you know how to do it in the upcoming quizzes. If you need help, don't be afraid to ask :)

  • Miko

    Hello and greetings from Finland! Thank you for all the amazing lessons on this site. I've been going through these lessons for a week now and what a ride it has been. Probably the best free curriculum on anything I've ever stumbled upon.

    Here's my attempt on the second quiz question. All comments and suggestions will be highly appreciated.

    constants.h :

    user_input.hpp :

    main.cpp :