ENGG1110 ProjectChangelog
Rev.DateDescriptionv1.2 2024/11/11P.10 [5.2 2(b)] Fixed Printout typo of printGameBoard()P.13 [5.5.1.1/candies in first round.P.14 [5.5.2]Added the checking of empty cells for
Target cell at swap.P.14 [5.5.4]Added clarification on howfindAndRemoveMatch() checking order.P.22 [6.3.2]Added clarification on how the cascadematching checking order.P.25 [8]Elaborated the grading specification.ENGG1110 Project1 of 26ENGG1110 Problem Solving by ProgrammingThe Chinese University of Hong Kong2024-2025 Term 1ProjectDue Date: 2024/12/04 (Wed) 23:59IntroductionCandy Crush is a popular match-three puzzle game in the world, originally released in2012 for Facebook and later adapted for mobile platforms.In the basic gameplay, the gameboard consists of a grid filled with various types of
candies, each represented by different shapes and colors. The player’s goal is to creatematches of three or more identical candies by swapping adjacent one. When a match ismade, the matched candies are cleared from the gameboard, and new candies will falldown to fill the empty spaces. This sometimes leads to “chain reactions”, where new
matches are automatically created as the board refills.Figure 1. Sample Gameplay. Snapshots fromhttps://www.flickr.com/photos/alper/10330168576In this project, you will develop a Candy Crush game using the C programminglanguage. The project is structured in two phases: Part I focuses on implementing thebasic version of the game, while Part II builds upon the first part by adding advancedWeek 14CascadeENGG1110 Project5 of 26
Sample Runs for Part I
The following shows several examples of inputs and the resulting candy clearings. User
inputs are indicated by bold, highlighted underlined text. The matches found by thefunction are in red font.4| # | * | | | | |5| % | # | | * | % | @ |Game Over! No more possible moves.ENGG1110 Project9 of 26
- Detailed Program Design Flow – Part IIn this project, you are required to follow exactly the output format specified. Usingother output formats will jeopardize yourmark.This program will
- Read and initialize the game board from source
- Display the game board
- Allow the player to select a candy to swap
- The player can only swap two candies at a time
- The player will choose a candy by entering the coordinates (row, column)
- The player will also input a direction (U for Up, D for Down, L for Left, R for
Right) to specify where to swap the selected candy.
- Find and remove matches
- After each swap, check for matches of three or more identical candies in
a row or column.
- If a match is found, display a message indicating the match’s location,
remove the matched candies, and update the game board.
- Check for a game-over condition
- Check if no further matches are possible on the gameboard.
- If the board has no possible moves left, display the message and end thegame.5.1.Header files, Functions, and Variable DeclarationsAt the beginning of the main.c file, we include two headers, <stdio.h> and<stdlib.h>.
No other header files or library are allowed in the project. We define several macros after the header line. Macros are identifiers defined b#define, which are replaced by their value before compilation. The first two are H and W.#define H 6 // height#define W 6 // widthH is the height of the game board, while W is its width. Therefore, our Candy Crush gameboard is a 6x6 square. In our test cases, we do not have any test cases with varying boardsize. You may try it if you are interested.Each cell on the game board stores a candy, with different types of candies represented
by numbers. To assist in converting these numbers into their corresponding candyrepresentations, the following global variable is provided.char candies[] = {'*', '#', '@', '%'};ENGG1110 Project10 of 26No other global variables are permitted. All variables you define must be declared
within functions and passed as parameters or return values as necessary. Violations of
this rule will result in a deduction of marks.
Also, there are a number of helper functions declared in the project. You can add new
functions to aid your work, but you CANNOT modify (function signatures – function
names, return type, parameters), or delete the given functions.
5.2.Main FunctionThe main function is given to control the game flow.There are some local variables already declared for you. You can declare your own locavariables for your use.Variables Usages
nt board[H][W]Stores the candies on the game board.The main function controls the gameplay as follows:
- Call askForSwap() to execute the swapping logic. If the askForSwap(returns zero (0), indicating the swapping is unsuccessful. In this case,print the following error message:Please try again.\nENGG1110 Project
11 of 26
- Call isGameOver() to check if any moves are possible. If no valid moves
remain, display a game over message and exit the game loop. In this case,
print the following error message:
Game Over! No more possible moves.\nENGG1110 Project
12 of 265.3.Initializing Game BoardThe main() function will first call the initGameBoard() function, which initializes theboard[] array for the later gameplay. In Part I, the content of the array should be readfrom another hard-coded arrays – board_samples[].␣5|␣%␣|␣@␣|␣#␣|␣*␣|␣%␣|␣%␣|There are two types of elements displayed on the grid:
- Candies: Use the candies[] character array to convert the numericalvalues stored in board[][] into the corresponding candy symbols.Empty Space: Display the space character (' '), which is stored in
board[][] as ASCII 32 (space).
It is crucial that your output format follows the example exactly, including the number
of spaces and any other formatting details, as the program will be graded using an
autograder. Any deviation in the format could result in a loss of marks.
5.5.
Ask for input for swappingThe main function will call askForSwap() to handle the game action. The swappinglogic will be implemented inside this function. This function will return an integer toindicate whether the swapping is successful or not. (Details of return value)ENGG1110 Project13 of 265.5.1.
User Input5.5.1.1. CoordinatesThe function should first ask the users for input two integers for the coordinates first:Enter the coordinate (row, column) of the candy:After receiving the user input, 代写ENGG1110 gameplay Elaborated validate the input based on numerical correctness. You
can assume the user will only input integers. Ensure that the coordinates are within thevalid game board range. If the coordinates input is out of bounds, output thefollowingerror message and return zero (0).Coordinates Out of Bound.\n5.5.1.2. EmptyCellsThen, the function should check whether the selected cell is empty or not. If the cell isempty, output the following error message and return zero (0).
Empty Cell Selected.\n
.5.1.3. Direction to Swap
After the coordinates are valid, the game should ask for the direction:
Enter the direction to swap (U for Up, D for Down, L for Left, Rfor Right):You can assume that the user will input one character only. This input should bevalidated to ensure it is correct – i.e. Upper case and should be one of the fourpossibilities (U,D,L,R).If the direction is incorrect, output the following error messageand return zero (0).Wrong Direction Input.\n5.5.2.
Valid Swapping CheckWhen attempting to move a candy, the program should validate that the move stayswithin the boundaries of the game board, For example, thecandy at position (0, 0)cannot be swapped to the left, as it is already at the left boundary of the board
f the move is out of bounds, output the following error message and return zero (0).
Move Out of Bound.\nENGG1110 Project14 of 26In addition, the program should also check the Target cell (e.g. if swapping (1,3) to theleft, Target cell is (1,2)) is empty. In this case, output the following error message andreturn zero (0).Empty Cell Selected.\n5.5.3.xecute Swap
f the input validations pass, the swap action is performed by calling the swap()function. You should implement the swap() to take the board, the starting coordinate,
the target coordinate, and the direction as arguments. The function will then swap theselected candies in the specified direction. For example, if the direction is U (up),thecandy at (row,col) will be swapped with the candy directly above it at (row-1, col).Similarly, if the direction is L (Left), the candy at (row, col) will be swapped with the
candy to the left (row,col-1). After the swap, you may use printGameBoard() toinspect the result, but remember to remove this call after completing your inspection.
5.5.4.
Find and Remove MatchesAfter the swapping, the findAndRemoveMatch() function is called to locate anyches involving the candy at both the target position and theoriginal position, as amatch may form in either direction. The function checks the neighboring cells aroundech of these positions to detect any sequence of three or more identical candies
horizontally or vertically.To facilitate auto-grading and maintain consistency, you should check the matches inthe following order.
- Order of Checks: When checking for matches, start with the Target Position
(where swap has just placed a new candy). After completing all the checks andremoval at the Target Position, move to the Start Position (the original cell wherethe candy was swapped from) and perform the same operations.For example, swapping (1,2) downwards: Target Position is (2,2); and the Start Position is (1,2).
- Horizontal Matches: Starting for the given cell, if it is not empty (‘ ’), check tothe left (if any) to see if there are three or more consecutive identical candies inthe same row. Then check the right direction (if any).
- Vertical Matches: From the given cell, if it is not empty (‘ ’), check upwards (ifany) to see if there are three or more consecutive identical candies in the samecolumn. Then check the bottom direction (if any).3| % | * | @ | # | * | @ |4| # | * | @ | % | % | @ |5| % | # | @ | * | % | % |If a match is found in the horizontal/vertical direction, output the correspondingmessage on the screen and indicate the row and column where the match occurred.Horizontal Match found at row <Row Index>!\ne.g. Horizontal Match found at row 1!Vertical Match found at col <Column Index>!\ne.g. Vertical Match found at column 1!
After finding the match, the game should remove the matching candies from the gamboard. This is the intermediate status of the board after the removal.nter the coordinate of the candy you want to swap:0 0 Enter the direction to swap (U for Up, D for Down, L for Left, Rfor Right):R
No Match found!In this function, you should return one (1) to the caller – i.e. AskForSwap() function. 5.6.Game Over CheckingAs the game progresses, there will be eventually no more matches in the game board.you should implement isGameOver() to check the whole board to see if there is atformed in any four directions (Up,Down, Left, Right). Therefore, you will implement a helper function isMatching() to
do the checking. This function will do a simple checking to see if there is at least onematch-three that can be formed by the given cell in any of the directions. It shallreturnone (1) if there is at least one match; If there is no match found, return zero (0).You may need to call it twice to check both the original position and swapped positionfor any potential matches.After each check, immediately undo the swap to restore the board to its original state.If a match is found during any swap, return one (1); If no matches are possible after allcheck, return zero (0). The main function will check this status andThe following input can be used to check the game over status:50 5DBelow shows the last game round:Enter the coordinate (row, column) of the candy:0 5Enter the direction to swap (U for Up, D for Down, L for Left, Rfor Right):DHorizontal Match found at row 1!Game Over! No more possible moves.The main() function will handle this, print out the error message,Game Over! No more possible moves.\nand will eventually terminate the game loop.** End of Part I **ENGG1110 Project18 of 26
- Program Design Flow – Part IIIn the part, we will extend the work of Part I to enhance the program functionality. Make
a copy of your source code of Part I. You will need to submit another source code forPart II.6.1.Main FunctionIn the main function, three more variables are introduced for the next section.int stacks[100]stores the extra candies, which are usedto fill empty spaces after matchedcandies are removed. Maximum 10candies can be stored.numCandiesRepresents the total number of candiesavailable in the stacks[] array forrefilling the board.currentActs as a pointer or counter that keepstrack of the current candy being usedfrom stacks[] to refill the board duringgameplay. The current variable will beinitialized to 0 and will be incremented aseach candy is used during gameplay.6.2.Read board and stacks from filePreviously in Part I the game board and stacks are read from hard-coded arrays foreasierdebugging. Now let’s extend the function to file I/O and give us flexibility toreplace the game board to a different initial status.The main() function will first call the initGameBoardFromFile() function, whichinitializes these arrays. The contents of the arrays should be read from a file named“board.txt”. Finally the function should return the number of candies in the stack,which will be stored in the numCandies variable in the main function.ENGG1110 Project
- First Line: Contains two integers representing the game board dimensions – thenumber of rows r and columns c.
- Next r Lines: A grid of r x c integers representing the initial game board. Eachinteger corresponds to a candy type.
- Following Line: Contains a single integer n, which corresponds to numCandies represents the total number of extra candies in the stacks[].
- Final Line: A list of n integers, each representing an extra candy that will be usedto fill the board when matches are removed.Please ensure that the file is read correctly, and handle file operations properly. If anerror occurs (e.g., the file cannot be opened), output the following message andApplying GravityThere will be empty cells after the candy’s removalYou should implement the gravity algorithm in the applyGravity() function forsimulating “gravity”. The main() function will call this function if the swapping issuccessful – i.e. the return value of askForSwap() is non-zero.In this function, implement the gravity feature to shift candies downwards into empty
spaces.Starting from the bottom of the each column, the function should upward to find emptyspaces (represented by ASCII 32 ‘ ’). When such empty space is detected,shift any ENGG1110 Project20 of 26candies above it down by one row . Repeat this process until each column has no emptyspace remaining below any candies.At the endof the applyGravity(), call printGameBoard() to output the game board.In this example, the candies at the top of column 2should fall down to fill the emptyspaces below. and the result should look like this:|Once the original candies have fallen to the bottom (highlighted in yellow above), anyremaining empty spaces are refilled sequentially using candies from the stacks[] array.The current variable in the parameter keeps track of the position in stacks[] from wherethe next candy should be drawn. Each time after the candies is drawn, current isincremented to point to next candies.Here is the example of how current variable workswith the stacks[]. After thebeginning of the game, the current variable is set to zero (0) to indicate the candy drawnnext is the first item in the stack. current = 01 2 3 3 2 1 1 0After one candy is drawn for refill, the current variable is incremented to one (1) suchthat next candy drawn is the second item in the stacks[].1 2 3 3 2 1 1 0In the game, this is the array that helps you to convert the number to the candyrepresentation.char candies[] = {'*', '#', '@', '%'};With this array, you can observe that theempty cells are filled with “#”, “@” and “%”from bottom to top, which is 1,2,3 in the stacksarray respectively.The process will continue until all the candies in the stack are exhausted. When fillingthe candy, if thenumber of candies remaining in the stacks[] is less than the number ofempty spaces on the board, the game will be unable to fill all spaces. In this case,thegame should display an error message and terminate the program with an exit codeof - more candies available.ENGG1110 Project22 of 26This check will naturally handle both cases: if stacks[] is exhausted during normal gameplay, or if stack[] is empty from the very beginning, as both conditions would trigger thesame error and exit the program at this point.If multiple columns contain empty spaces, fill these spaces in a bottom-to-top orderwithin each column, moving from the leftmost column to the rightmost column. Here isthe example of the case of filling in multiple column spaces. The number in red italicand brackets indicates the filling sequence.6.3.2.Cascade MatchingWhen the candies are refilled, new matches may form on the board. To mimic realgameplay, the game should continuously check for new matches as the boardrefills,repeating the process until the board is stable with no further matches.The main function will call cascade() function right after the matching process. Withinthe function, you should call both the applyGravity() and fillEmpty() for thecascade process. As a result, any previous calls to these functions in the main functionshould beremoved, as they are now called within cascade().In the cascade function, you are required to check if there are any matches for eachcell. For this, you will callfindMatchAndRemove() function (developed in part I) to findall matches on each non-empty cell. You can make use of the return value offindMatchAndRemove() to determine whether a match is found.In the cascade function, repeat the process until no further matches can be found in theboard. In each checking round:Apply the gravity.Fill in all the empty cells on the board and get the updated value of currentPrint the Gameboard to show the current statusRemove all matches on the board.Starting from the top-left corner (0,0),check each cell for matches in the following order:
Row by Row, Column by Column: For each cell, proceed across each rowfrom left to right, then move down to the next row.
- Check Directions: For each cell, check for matches in the order of Left,Right, Top, and BottomENGG1110 Project23 of 26Clear Matches: If a match is found, clear the matching candiesimmediately before proceeding to the next cell.
- If there is any removal, output the following at the end of checking:Cascade Matches found!\n
- After the cascade checking completes with no further matches, return theupdated value of current to the main() function.Repeat these steps until no matches are left, ensuring that all cascading actions arecompleted before returning to the main function.Below is the sample of a cascade matching, the matches found by the cascade functionAcademic Honesty and Declaration Statement
Attention is drawn to University policy and regulations on honesty in academic work,and to the disciplinary guidelines and procedures applicable to breaches of such policyand regulations. Details may be found athttps://www.erg.cuhk.edu.hk/erg/AcademicHonesty .You are required to fill in the following declaration statement as the comment at thebeginning of the main.c source code with your information. Assignments without the signed declaration will not be graded.Tools such as software similarity measurement, AI-tool fingerprint detection, etc., might used to inspect all submissions./*** ENGG1110 24R1 Problem Solving byProgramming
Course Project** I declare that the project here submitted is original* except for source material explicitly acknowledged, and that the same or closely related material has not been* previously submitted for another course.* I also acknowledge that I am aware of University policy a nd* regulations on honesty in academic work, and of the disciplinary* guidelines and procedures applicable tobreaches of such* policy and regulations, as contained in the website.
Grading Platform and SubmissioWe will grade your work in Gradescope autograder. Please note that while passing thetest cases is necessary, it is not sufficient on its own for full marks. Additional marks willbe allocated based on the completeness and adherence to all requirements specified in project documentation, including code organization, functionality, and adherenceto the design specifications.ENGG1110 Project26 of 26Please follow the steps below to submit your work by the deadline.
- Rename the modified main.c for part I to main_part1.c
- Rename the source code for part II to main_part2.c
- Submit your .c file to the Gradescope.Please only submit the source file (.c). You may submit many times before the due date,but the latest attempt will be graded.
- Late SubmissionThe late submission penalty is as follows:
- Within 3 days (72 hours): 10% per 24 hours
- 3-7 days: 50% penalty
- More than 7 days: 100% penalty (Your work will not be graded)NOTE: Submitting the project is crucial in PASSING the course.