CSCI 102 - Fall 2023 Fundamentals of Computation

HW 11

You will write a program that utilizes most, if not all, of the concepts you have learned so far this semester.

Writing Your Code

This assignment will again be submitted through Vocareum. To develop your code you can use any text editor/compiler you like. We recommend you use the virtual machine and get used to using Linux and developing, compiling and testing code on it. However, you can use the web-based editors/compilers we have referenced in the past.

Note: We will not provide Build and Run scripts for you. You will need to compile your code into an executable candycatcher manually at the command line. Our submission test requires this.

Candy Catchers

Description & Requirements

Congratulations… you’ve just been hired at a game design company! Your first project is to design a game called “Candy Catchers”. In this game, players will compete to collect as much candy as possible in a “Hunger Games”-style arena. Beware – a “Big Bully” with a sweet tooth hides somewhere in the arena. As the players collect candy, their scores will be updated on a leaderboard and displayed so that the players’ hometown “Districts” can cheer them on. Several rounds of events will take place as the players explore. Some events will cause players to gain candy; others will cause them to lose some of their candy. After all the rounds are finished the player with the most pieces of candy to be the winner! You will interact with the user with cout and cin statements. At the start of the program, the user can add players and initial candy counts (1 or more). You will then enter a sequence of “actions” that will affect the candy count of the players and drop/delete any player whose count is 0, and print the leaderboard before repeating for the next action. In addition, your leaderboard should be displayed in descending sorted order (i.e. most to least). In other words, it should reorder based on changed candy counts of the players. Consider the following list:

Batman 8
Spiderman 7
TreverNoah 6
KatnissEverdeen 4
PeterParker 2

If PeterParker collects 3 more candy pieces, then your new list should look like this:

Batman 8
Spiderman 7
TreverNoah 6
PeterParker 5
KatnissEverdeen 4

In other words, PeterParker should be moved up on the leaderboard.

You may choose to use any sorting algorithm for the leaderboard – we want to give you flexibility in your implementation. Thus will not enforce any ordering other than players with different candy counts must be sorted higher to lower but there is no ordering constraints on players that are tied.

At most your program needs to store 20 players. To store your data you must use two arrays (failure to do so will lead to no points awarded for the assignment). The first, players will store the names of the players and the second, candy will store the corresponding number of candy pieces held by each player. The candy count at location i in the candy array is the candy count for the player at location i in the player array. See the example below:

players[0] = "Batman"              candy[0] = 8
players[1] = "Spiderman"           candy[1] = 7
players[2] = "TreverNoah"          candy[2] = 6
players[3] = "PeterParker"         candy[3] = 5
players[4] = "KatnissEverdeen"     candy[4] = 4

While we will declare these arrays to be of size 20, we must also keep track of how many players are CURRENTLY in the game. This can be done with a separate integer that tracks how many players are currently playing (remember once a player reaches 0 pieces of candy, we delete that player). We will always pass these two arrays and the current number of players being stored in the arrays as argument to your various functions. Remember, you can modify the value of an array directly in a function, unlike trying to modify a primitive like an int. Refer to the class notes or your lab exercises for more details.

For this assignment, you have some flexibility in how you decide to implement the various requirements. Like the last assignment, we will provide some functions headers and you must write their implementations, but this time, you must also write a majority of the main() function and where to call the functions you wrote. You may also create additional functions of your own, if you see fit. One function: dropLosers() is completed for you in the skeleton code and you may use it as a sample of how to approach various aspects of moving data around in the arrays.


/**
 * Prints the leaderboard in the appropriate (sorted by candy count) order
 *
 * Parameters:
 *   players: Array of player names
 *   candy: Array of candy counts (candy count at location i corresponds to
 *          the player name at location i in the players array)
 *   numplayers: Number of players and candy counts in the respective arrays
 */
void printLeaderboard(string players[], int candy[], int numplayers);


/**
 * Update the candy count of the given player to reflect the number
 * of pieces of candy they found. Do nothing (just return)
 * if the given player does not exist in the arrays already
 *
 * Parameters:
 *   players: Array of player names
 *   candy: Array of candy counts (candy count at location i corresponds to
 *          the player name at location i in the players array)
 *   playerName: Name of the player to update
 *   candyFound: Number of pieces of candy found by playerName
 *   numplayers: Number of players and candy counts in the respective arrays
 *
 */
void struckGold(string players[], int candy[], string playerName, int candyFound, int numplayers);

/**
 * Add 2 to all player candy counts that are still in the game.
 *
 * Parameters:
 *   players: Array of player names
 *   candy: Array of candy counts (candy count at location i corresponds to
 *          the player name at location i in the players array)
 *   numplayers: Number of players and candy counts in the respective arrays
 *
 */
void rainingCandy(string players[], int candy[], int numplayers);

/**
 * Cut in half all candy counts of players who are in even positions on the
 * leaderboard (0-indexed). Use integer division, since the big bully
 * is greedy and doesn't like "half" pieces of candy.
 *
 * Parameters:
 *   players: Array of player names
 *   candy: Array of candy counts (candy count at location i corresponds to
 *          the player name at location i in the players array)
 *   numplayers: Number of players and candy counts in the respective arrays
 *
 */
void theft(string players[], int candy[], int numplayers);

/**
 * Gives one piece of candy from the top player to each other player in
 * reverse order.  Starting from the last player, Big Bully takes one
 * piece of candy from the top player and gives it to the last place player,
 * then repeats for the second  to last player, continuing until the top
 * player is out of candy or we've given one piece of candy to every other
 * player (i.e. we've reached the 2nd place player).
 *
 * Parameters:
 *   players: Array of player names
 *   candy: Array of candy counts (candy count at location i corresponds to
 *          the player name at location i in the players array)
 *   numplayers: Number of players and candy counts in the respective arrays
 *
 */
void toughLuck(string players[], int candy[], int numplayers);


/**
 * Returns the index of the specified player or -1 if it doesn't exist
 *
 * Parameters:
 *   players: Array of player names
 *   playerName: Name of the player to search for
 *   numplayers: Number of players in the players arrays
 *
 * Returns: Index of given playerName or -1
 */
int findPlayer(string players[], string playerName, int numplayers);

/**
 * Prints the main menu and returns the integer selection the user
 * wants to perform.  If the user provides an invalid selection,
 * simply return -1 which the calling function (e.g. main() can
 * use to detect the error.
 *
 * Returns: integer selection of the user or -1 if the selection
 *  was invalid
 */
int printPromptAndGetInput();


/**
 * Sort the player and candy array from highest candy count to lowest.
 *
 * We recommend one of the simplest sorting algorithms:  Selection sort
 * Look at the class notes or online resources for how to implement this.
 *
 * Parameters
 *   players: Array of player names
 *   candy: Array of candy counts (candy count at location i corresponds to
 *          the player name at location i in the players array)
 *   numplayers: Total number of players
 */
void sortLeaderboard(string players[], int candy[], int numplayers);

/**
 * Delete the given player and its corresponding candy count from the arrays
 * by moving all later players/candy counts up one spot, overwriting the
 * player to be deleted.  This function will be called by dropLosers()
 *
 * Parameters:
 *   players: Array of player names
 *   candy: Array of candy counts (candy counts at location i corresponds to
 *          the player name at location i in the players array)
 *   playerName: Name of the player to delete
 *   numplayers: Number of players and candy counts in the respective arrays
 *
 * Returns: false if the specified player does not exist, or true if
 *          the player was successfully deleted.
 */
bool deletePlayer(string players[], int candy[], string playerName, int numplayers);

/**
 * Delete all players from the game who do not have positive candy counts.
 *
 * Note that when a player is deleted, the index of other players may
 * shift, so special care must be taken.
 *
 * Parameters
 *   players: Array of player names
 *   candy: Array of candy counts (candy count at location i corresponds to
 *          the player name at location i in the players array)
 *   numplayers: Total number of players before deleting.
 *
 * Returns: the number of players remaining after deleting.
 */
int dropLosers(string players[], int candy[], int numplayers);

Getting the skeleton

You can find the skeleton code on Vocareum when you start the assignment. From there you can copy this to your own laptop if you wish.

You must follow the guidelines and produce the return values that are provided in the comments above each prototype in the skeleton code. Those comments act as requirements just as much as this webpage does.

Getting Input (Initializing the game)

  1. You should first prompt the user by asking how many players will join the game (1 - 20 inclusive).
  2. You will then accept that number of player names and starting candy count – in other words, you should prompt the user to enter a name and initial candy count for each player in the game (separated by a space). So the initial input should look like this:
*Your prompt for number of players:*
4
*Prompt to enter name and starting number of candies*
KatnissEverdeen 4
*Prompt to enter name and starting number of candies*
PeterParker 2
*Prompt to enter name and starting number of candies*
Batman 5
*Prompt to enter name and starting number of candies*
ClarkKent 1

After the user has input all the players, you should output the initial sorter leaderboard like this:

Initial Leaderboard:
Batman 5
KatnissEverdeen 4
PeterParker 2
ClarkKent 1

Getting Input (Game Actions/Events)

You will then repeatedly ask the user to choose one of the 4 possible events to perform, quitting the game only when the user enters 0 as their choice. Each event will correspond to a function that you must implement. Each event will also potentially require additional user input – e.g. “Struck Gold” will require the user to enter a player name and a candy count. You should prompt the user with this menu for each round of the game:

What event will occur this round?
0. Quit
1. Struck Gold: Player “x” finds “y” pieces of candy
2. Raining Candy: All players collect 2 pieces of candy
3. Theft: Big Bully steals half of the candy of all even-index players (minimum 1 piece)
4. Tough Luck: Big Bully gives one piece of candy from the top player to each other player in reverse order.

Using cin you can get the menu choice (the user will type the integer number of the desired option), get any additional information needed by that choice, the carry out the event:

  1. When a player “Strikes Gold” the user will enter the name of the player (string) and the size of the candy stash discovered (int). You must increment that player’s candy count by the specified amount.
  2. When it is “Raining Candy”, everyone in the game who has not lost yet (gone to 0 pieces), receives 2 pieces of candy.
  3. When “Theft” occurs, the Big Bully steals half of the candy of each player at an even index on the leaderboard. The Big Bully is greedy, so for people with an odd number of pieces, he rounds up. So in the example above, Batman (at the 0th index) would go from 5 pieces to 2 (5/2=2.5, 2.5 rounds up to 3). PeterParker (at the 2nd index) would go from 2 pieces to 1 piece.
  4. When “Tough Luck” happens, the Big Bully takes pieces of candy from the top player and gives 1 piece to all other players in reverse order (from last place to 2nd place) until the the top player runs out of candy or we give 1 piece to every other player (which ever comes first).

Important Note: cin breaks at whitespaces. So even if the user types 1 Batman 5 after the menu appears you don’t have to get all 3 items at once. You can use cin to just get the menu choice (i.e. the first integer) then use some if statements to process what choice the user made, and based on that choice you can then use cin to get what you expect next from the user (i.e. Batman and 5).

Another implication of how cin works is that players with more than one word in their title will confuse us since cin stops at whitespace and we wouldn’t know what to expect next (another word or the candy count). If we entered option 1 as: 1 Katniss Everdeen 2 we would not be sure what we’re getting after the first word (i.e. Katniss). Will it be an integer candy count or a string? And, unfortunately, with cin we have to know what type to expect so we can use that type of variable. Thus, we will write all player names as 1 word like: KatnissEverdeen using capital letters if we desire to delimit each word. We offer an extra credit opportunity based on this limitation below.

You will need to write main() yourself and call your various functions. A general gameplan for main() is:

  1. Get the initial game and player data
  2. Enter a loop that continues receiving actions until the user chooses to quit.
  3. On each iteration
    • Print out the event menu and get the user’s choice
    • Determine which choice was entered and get any other necessary input
    • Call an appropriate function and/or update some variable(s) as necessary to process the event
    • Delete any players who have gone to 0 or below
    • Sort the remaining list of players from highest to lowest candy count
    • Output the newly sorted leaderboard

You must print out the correct leaderboard after the user chooses to quit.

Errors and Other Checks

Your program should check for these errors:

  1. You may assume the user will not enter players with duplicate names.
  2. During initial data entry, you may assume the user will not enter players with a candy count of 0 or less.
  3. If, for the “Struck Gold” event option, the user enters a number that is 0 or less, output a message: Bad candy count...ignoring and do not carry out the request (simply go on to the next iteration of your main loop to print out the menu and take in a new choice).
  4. If, for the “Struck Gold” event option, the user enters a player name that doesn’t exist on the leaderboard, output a message: Invalid player...ignoring.
  5. If, the user types in any other event menu option besides 0-4, output the error message Bad event option...type a number in {0,1,2,3,4}. Go on to the next round/iteration.
  6. If the leaderboard ever becomes empty, you must quit the program by printing the blank leaderboard and exiting the program.

Notes

To implement your core functionality you must sort the leaderboard after each event, since the “Theft” and “Tough Luck” events depend on the current order of the leaderboard. We recommend using a bubble sort algorithm or selection sort algorithm. You can choose the one you think is easiest to implement.

Extra Credit (3 points)

You can earn extra credit by implementing the following function and integrating it into your program so that all movie names typed as one word with capital letters indicate “words” will have spaces inserted where the capital letters appear. So the user will continue to type names without spaces KatnissEverdeen and you should store the names without spaces, but when you print the list you will use the following function to make a “pretty” version of the name that you will actually print out to the screen (i.e. Katniss Everdeen with spaces added to the string that is displayed).

/**
 * !!!!!!!!!!!!!!!! EXTRA CREDIT !!!!!!!!!!!!!!!!!!!!!!!!!
 *
 * By implementing this correctly and integrating it into your
 * project so that  names are displayed with spaces, even
 * though the user enters them without spaces you can earn
 * some additional extra credit.
 *
 * Breaks up a string at capital letters and inserts spaces
 * So if the input is "KatnissEverdeen" return "Katniss Everdeen".
 * You may assume the first letter is a caps (and even if it
 * not you will still get a reasonable result; so "katnissEvedeen"
 * should still return "katniss Everdeen").
 *
 * Parameters:
 *  in:  string with no spaces
 *
 * Return a version of the string with spaces
 */
string breakStringAtCaps(string in);

For example, if the user enters these players:

KatnissEverdeen 4
peterParker 3

Then, if your extra credit function was applied correctly, the list printed for choice 4 would yield:

Katniss Everdeen 4
peter Parker 3

Build and Run

Since we have taught you to compile your code using g++ and run your code on the command line, we have removed the Build and Run Scripts. You will need to compile and test your code on your own in the Terminal window/area at the bottom of the Vocareum Editor window. The executable program must be named candycatcher. The Submit button will also NOT compile your code but expect that it is already compiled successfully.

Grading

This program is difficult to fully process with automated scripts. Thus, some of your points will come from automated tests and others will come from human tests. The automated tests will verify that your final leaderboard is correct. Human tests will evaluate your error outputs and ensure that your intermediate leaderboards are also correct. Therefore We encourage you to run your own tests and exercise various options like the error conditions, and different sequences of events that change orderings on the leaderboard.

Submitting your code

You can develop your code on your own environment or in Vocareum.

When you believe your program is finished login to Vocareum, start the HW12 assignment (Candy Counter), and in the upper-left of the resulting window, click New..File. A textbox will appear where you can type in the filename (leave the work/ portion there and) just type candycatcher.cpp. In the left window pane you should now see candycatcher.cpp appear (it must be named candycatcher.cpp) and you can click on it to open it. A blank window should appear on the right. Cut/paste your code from your other tab/window to this window and you can click Submit. Alternatively, rather than clicking New..File, you can just use the Upload button to upload the file if you have it on your VM (but the file must be named candycatcher.cpp).

Be sure you click submit otherwise your code will just be saved, but not submitted!! Please post any questions about using Vocareum on EdStem.