Today’s lab will build on your work from the loops and conditionals lab. If you haven’t finished that lab yet, that should be okay. You will eventually reach a point in this lab where you will need to go back to complete steps in the previous lab, but until then you may actually find it easier to work on this lab first.
We write functions in imperative programs for two main reasons, both of which will come up in today’s lab:
In both cases, functions help us keep our code organized and readable.
As you worked on the rock, paper, scissors implementation in the previous lab you likely found it difficult to follow all the nested loops and conditionals.
As you might have guessed, you will be breaking your rock, paper, scissors implementation into separate functions during today’s lab.
The general structure of your program will still live in main, but by the time you finish this lab you should have a much easier time seeing that structure because many of the important operations will live in separate functions.
We haven’t discussed magic numbers yet in this class, but they’re something we want to avoid.
A magic number is some value that appears in your code and has some special meaning, but doesn’t have any explanation.
We’ve been using these for the rock, paper, and scissors values and we’re going to need to fix that.
If you add these three lines above main you can use the names ROCK, PAPER, and SCISSORS instead of regular integers with special (secret) meanings:
#define ROCK 0
#define PAPER 1
#define SCISSORS 2
These #define lines create preprocessor constants, which are not variables.
Any time you write ROCK in your code, the C compiler will replace that with a 0.
Using these constants will make your code easier to read, and it will help us ensure all the different functions we write agree on how we’re representing rock, paper, and scissors.
Update your rock, paper, scissors implementation to use these named constants anywhere you interpret integers as one of these choices.
Not all integer constants have to be one of these named constants though.
You’ll often need the value zero for specific cases, like when checking the value returned from scanf.
It wouldn’t make much sense to check if scanf returned ROCK, so leave that as the constant 0.
Once you’ve made your updates, test the program to make sure it still works.
Once you are satisfied, commit and push your changes to the git server.
Part A of the prior lab asked you to write code that allows the computer player to choose rock, paper, or scissors. Make sure you’ve finished part A of the prior lab before starting this exercise.
Add the following function to rps.c above the main function:
// Randomly choose ROCK, PAPER, or SCISSORS and return it
int computer_choose_rps() {
}
Fill in the body of the function with the code you wrote that uses rand to make a choice for the computer player into this function.
You’ll also need to add a return statement to send the computer’s choice back from this function.
Your function should not print the computer’s choice;
we’ll still handle that in main.
All this function will do is make the choice and return it.
Once you’ve implemented the function, update the rest of your program so it calls this function instead of making the computer’s choice inside of main.
Test your implementation to make sure it works the same as the original version, commit your changes, and push to the git server.
Part B of the prior lab had you write code to prompt the user to choose rock, paper, or scissors. If you didn’t finish this part of the previous lab, do that first.
Add another function to rps.c, above main again:
// Ask the user to choose ROCK, PAPER, or SCISSORS and return the choice
int user_choose_rps() {
}
As with the previous exercise, move the code that asks the user to choose a move into this function.
The function should only return once the user has made a valid choice, so you’ll need a loop inside this function to keep asking for a choice as long as the user gives invalid input.
This might require you to make some changes to the structure of your code from part B.
Don’t forget to return the user’s choice from this function.
Make sure you return ROCK, PAPER, or SCISSORS and not the slightly different numbers the user types to make a choice.
As with the previous step, your function should not print the computer’s choice;
we’ll still handle that in main.
The only things this function should print are the prompt messages and the feedback when the user enters an invalid option.
Once you have the function implemented, update your main function to call user_choose_rps instead of prompting the user directly in main.
Test your code to make sure it still works after your changes.
Commit and push your changes once the implementation is working.
Part C of the previous lab asked you to implement an actual game of rock, paper, scissors using the user and computer choices. Make sure you’ve completed that part of the lab before you start this exercise.
We’re going to add two functions in this exercise.
One function, is_tie, will take the two moves as parameters and return true if the two players tied and false otherwise.
The other function, is_win, will take the two moves and return true if the first move wins against the second move.
You’ll have to write these functions yourself.
Don’t forget to #include <stdbool.h> so you can use bool, true, and false in your code.
Update rps.c to use the is_tie and is_win functions instead of checking for a tie, win, or loss entirely in the main function.
Test your implementation.
Once you are confident it works, commit and push your changes.
Part D of the prior lab asked you to add an outer loop that asks the user if they want to play again after finishing each game. If you didn’t finish that part already you can implement it with functions right away, or you can start by writing the version without functions. Talk with your lab group to decide which approach you want to start with.
Add a function called user_prompt_again that takes no parmeters and returns true if the user wants to play again (or false otherwise).
Update main to use this function to prompt the user after each game.
Test your implementation to make sure it works. Once you are happy with it, commit and push your changes.
(Optional)By this point you’ve probably noticed that you have very similar code in main that prints the computer’s and user’s choices.
We’re going to fix this by adding a function print_choice that prints “rock”, “paper”, or “scissors” when given the value ROCK, PAPER, or SCISSORS, respectively.
For example, you should be able to use the following code to print the computer’s choice:
printf("The computer chose ");
print_choice(computer_choice);
printf(".\n");
Note that only the last print operation should include a newline character, so all three parts of the message will appear on one line.
Add a print_choice function to your implementation and update your code in main to use it to print both the computer’s choice and the user’s choice.
If you didn’t finish part E of the prior lab, do that now. Your final implementation should use all of the functions described above, and should print the user’s wins, ties, and losses after each game. You don’t need to add a function to print these messages, but you can if you’d like.