- Brad Vander Zanden
- Directory for files, executables and gradescript: /home/bvanderz/cs140/Labs/Lab6. There is no makefile for this lab. I want you to get some experience with writing your own compilation commands. You should create include, src, obj, and bin directories for this lab as you have done in some of the previous labs. Your .hpp files go in the include directory, your .cpp files in the src directory, your .o files in the obj directory, and your executable in the bin directory.
- Your executable should be named candyCrustTest and it will be created from the candyCrush.cpp and candyCrushTest.cpp files.
- This lab is intended to give you practice with using the STL doubly linked list library. You will do it by implementing a very simplified version of the game Candy Crush.
- Files to submit:
**candyCrush.cpp**and**candyCrush.hpp**. Unlike other labs, you are allowed to add additional methods to the candyCrush.hpp file. You may**not**alter the signatures of the existing methods nor may you delete the existing methods. - For this lab you will be using the srand() function to seed the random number generator and the rand() function to generate random numbers.

I have written a header file, candyCrush.hpp and a program candyCrushTest.cpp that uses the class/methods defined in that header file. Your job is to create the file candyCrush.cpp, which implements the methods defined in candyCrush.hpp.

You are allowed to add additional protected methods to candyCrush.hpp but you may not change the function prototypes of the existing methods nor may you delete any of them. You are not allowed to modify candyCrushTest.cpp. You will turn in candyCrush.hpp and candyCrush.cpp, and the TA's will compile and test them with the candyCrushTest.cpp that is in the lab directory.

One of the possible matches would be the two yellow-colored toffee candies at the beginning of the first row of the diagram and another would be the two purple-colored candies at the end of the first row of the diagram. There are other matches you could make in the columns, but for this lab we are going to focus on row matches. Specifically you are going to use an STL list to implement a single row of a simplified Candy Crush like game.

It would be too complicated to create fancy graphics for this lab assignment, so instead you will be using a list of strings to represent flavors of candy. In Part A you will write code to randomly generate the first candy sequence, put it in the list, and print out the portion of the list that you filled. In Part B you will generate enough candy sequences to completely fill a 12 item row of candies. In Part B you will also write code to allow the user to select a sequence of candies and assign points based on the length of the sequence. Finally in Part C you will remove the candy sequence selected by the user from the row, slide the remaining candies to the left, and fill the right side of the row with new candies.

Your program will read from stdin. Here is some sample input and how to interpret it:

256 10You will be using a random number generator for this lab so the first input is the seed you will use to the random number generator. It must be an integer.// Seed for the random number generator and length of a candy crush rowgrape cherry orange lemon toffee// The candy flavors20 10// The probability for each possible candy sequence length10 20 25 30 20 50 15 70 15 120 0 150 0 180 0 210 0 300

The second input on the first line is the length of the candy crush row and must be a non-negative integer between 1 and 100.

The second line of the input will be a list of the candy flavors that will be used in the game.

The remaining lines of the input will be the probabilities of generating a flavor sequence of a particular length and the points they are worth. The sequence lengths are not explicitly given. Your program should assume they begin with 1. Hence in the above input there is a 20% chance of generating a sequence of length 1 and it is worth 10 points if a player selects a sequence of length 1. Similarly there is a 25% chance of generating a sequence of length 3 and it is worth 30 points when a player selects it. You must provide a probability and point value for every sequence length up to the row length, since it is possible to have a row that consists only of one flavor. Note that there is no chance of generating a sequence of length 7-10. However, suppose you generate a "toffee" sequence of length 4 and then generate a "toffee" sequence of length 5. You will end up with a contiguous "toffee" sequence of length 9.

The probabilities must add up to 100 and must be non-negative integers.

Take a look at the header file candyCrush.hpp:

class candyCrush { public: candyCrush(const string &inputFile); int getRowLength() const; int getScore() const; void printCandy() const; int play(int choice); protected: list<string> candy; vector<string> flavors; vector<int> points; vector<int> probabilities; int score; int rowLength; }; |

You must minimally implement this public API. You are free to add additional protected methods and instance variables to help with your implementation. The method descriptions are as follows:

**candyCrush(const string &inputFile):** This constructor function sets up your initial game state.
In this constructor you will generate a random sequence of candies and assign them to your candy list. You will do this as follows:

- You will read the input and assign it to the appropriate instance
variables. Here are a few additional instructions about what to
do with input:
- pass the seed to the srand function to initialize the random number generator. You do not need to save the seed once it's been passed to the srand function.
- The probabilities should be stored as cumulative probabilities in the
`probabilities`vector rather than individual probabilities. For example, suppose the maximum possible sequence was 4 and your probabilities were 40, 30, 20, and 10. Then your probabilities vector should be`40, 70, 90, 100`, not`40, 30, 20, 10`. The reason for storing cumulative probabilities is so that you can easily generate a sequence from a random number between 0 and 100. For example, if the random number is 30, you would generate a sequence of length 1 because 30 is between 0 and 40. If the random number is 90, then you will generate a sequence of length 4 because 95 is between 90 and 100. Note that these cumulative probabilities give each sequence the appropriate probability of being chosen because out of 100 random numbers, each has the appropriate proportion assigned to its sequence length.

- You will then perform the following operations to generate the candy sequence and fill the list:
- use
`rand()`to generate a random number between 0 and n-1 to choose a candy where n is the number of candy flavors. Assign numbers to the candy flavors in the order they are presented to you in the input. For example given the sample input shown above, assignment of numbers to candies should be as follows:0: grape 1: cherry 2: orange 3: lemon 4: toffee

- use
`rand()`to generate a random number between 0 and 99 to choose the length of the candy sequence. Find the range in the`probabilities`vector which contains this number. Add 1 to the index associated with that range and you have the length of your sequence. The random number must be**less than**the cumulative probability associated with the index for that index to be chosen. For example, suppose your probabilities vector is:0: 20 1: 30 2: 55 3: 75 4: 90 5: 100

and your random number is 90. Then the index you will choose is 5, not 4, and your sequence length will be 6. If you want to make life easier on yourself, you can start storing your probabilities at index location 1 rather than 0, so that you don't have to remember to add 1 to the index to get your sequence length. - If the sequence length is
`k`, add up to`k`strings of the flavor you generated in step 1 to the candy list. If adding the full`k`strings would cause you to overflow the row, then stop when you have filled the row.

- use
- Find the candy list element corresponding to the player's choice.
- Compute the length of the flavor's sequence and add the points for that sequence to the user's score.
- Delete the strings in that sequence from the candy list
- If the sequence is of length
`k`, then starting at the end of the candy list, add`k`flavors to the end of the list using the same strategy you used to generate the initial list (i.e., generate a flavor and a sequence length, add that many flavors to the end of the list, and repeat until the row is full). You probably want a separate method named something like`fillCandyList`to fill the list with candy.

**int getRowLength() const**: Returns the length of the candy crush row.

**void printCandy() const**: Prints the candy crush row as 8 flavors per row,
left justified, in fields 10 characters wide.

**int play(int choice)**: `choice` is an integer from
0 to `rowLength-1` indicating which candy flavor the player
selected. The test program error checks rowLength so you do not have
to do so yourself. The return value is the number of points scored by the player
on this turn. This method must:

**play()** does not print anything. There are commands you
can use in the test
program to print the candy crush row or the player's current
score.

**int getScore()**: Returns the players current score.

I've written a main() procedure in candyCrushTest.cpp. It needs to be compiled with your implementation of candyCrush.cpp. You run it as follows:

./candyCrushTest inputFile |

Then it accepts commands on standard input:

- PRINT: prints the candy list in the format stated above.
- CHOOSE index: chooses a flavor in the candy crush row.
- SCORE: prints the player's current score
- QUIT: quits

The gradescript is in an incremental format. The test cases are laid out as follows:

**Cases 1-10:**Tests PRINT**Cases 11-20:**Tests PRINT and CHOOSE**Cases 21-30:**Tests PRINT, CHOOSE and SCORE**Cases 31-100:**More complex input cases and error checking

The grading programs are in **/home/ssmit285/public/gradescripts/cs140_bvz/lab6** as **gradeall** and **gradescript**, like usual.
Your executable must be named **candyCrushTest** for you to run it, and it will flag you wrong if it doesn't find that file.

Don't go assuming that the test cases are error-free either. I've purposefully hidden a few faulty/bad examples (14 in total) in the gradescripts from 31 to 100. Just like the previous lab assignments, you can use the gradescripts and solution example to debug until you match outputs. If you run into an infinite loop, the gradescript will auto-fail that particular test case after 2 seconds of run time.

The following example interaction with the test program uses this input file:

157 10 grape cherry orange lemon toffee 20 10 10 20 25 30 20 50 15 70 10 120 0 150 0 180 0 210 0 300Here is a series of sample interactions with the test program and the output the test program will produce. In each case I have highlighted the flavor that the user has chosen:

UNIX> ./candyCrushTest input.txt PRINTThe player chose index location 0, which corresponds to "lemon". There is a sequence of 1 lemon flavors here so the player receives 10 points (note that in the input file, a sequence of length 1 is worth 10 points).lemongrape grape grape grape grape grape orange orange cherry CHOOSE 0 you scored 10 points

PRINT grape grape grapeNotice that after the user chooses the lemon sequence in the above example, that the lemon has been deleted and the remaining entries have been "moved over" one element. Finally a new flavor, cherry, has been added at the end of the row.grapegrape grape orange orange cherry grape CHOOSE 3 you scored 120 points

The user now chooses a grape candy. This grape candy is in the middle of a sequence of 6 grape candies so the user scores 120 points. The program then deletes this 6 candy sequence, moves the remaining 4 candies to the left, and adds 4 candies at the end of the row to get the following sequence:

PRINT orange orange cherry grape lemon lemon lemon lemon orangeThe user now chooses the last candy in the sequence, which is an orange candy. This candy belongs to a sequence of two orange candies and hence the user scores 20 points. The program deletes this sequence of two candies and adds two new candies to the end of the row to get the following sequence:orangeCHOOSE 9 you scored 20 points

PRINT orange orange cherry grape lemon lemon lemon lemon lemon lemon SCORE current score = 150 QUITNote that two lemon candies were added at the end of the sequence, so the lemon sequence that was previously 4 candies long is now 6 candies long. Hence it is possible for candy sequences to increase in length, either because additional candies of the same flavor are added at the end of a row, or because candies with the same flavor are both before and after a chosen candy sequence. For example, suppose that you had the following row (

PRINT toffee toffee toffee grape grape toffee toffee toffee toffee toffee CHOOSE 4 you scored 20 pointsThe player chose index location 4, which corresponds to "grape". When the grape sequence is deleted, the two toffee sequences on either side of the grape sequence are concatenated, resulting in a toffee sequence that is 8 candies long:

PRINT toffee toffee toffee toffee toffee toffee toffee toffee lemon orange

In order to generate to same output as my sample executable, you will need to do two things:

- Run your program on a hydra machine. Different machines/OS's will
use different random number generators and hence will generate different
random numbers from the same initial seed. Hence if you want to match
my output, you need to run your executable on a hydra machine. All of
the hydra machines run the same OS and hence the same random number
generator so you can use any of the hydra machines.
- Use the numbers generated by the random number generator in the
same way that I used them. Here is the order you should use:
- Generate the random number used to select the candy (grape, cherry, orange, etc).
- Generate the random number used to select the length of the candy sequence.

- You must use srand() to seed the random number generator and rand() to generate your random numbers. If you use a different function, such as lrand48(), then you will get random numbers that are different from mine.

As always you should strive to break the program into parts and code up and test each part before moving to the next part. I coded the constructor, printCandy, and rowLength functions first, then the play and getScore functions, and finally I inserted error checking code. There are a fair number of error checks you need to perform. In order to use the test editor to test your constructor and printCandy functions (use the PRINT command), you will need to provide empty stubs for the remaining methods in the public API.

In lab you will be asked to try to enumerate these error checks. You can run my test executable to see the exact error message that your program should generate.