Match-3
Objectives
- Read and understand all of the Match-3 source code from Lecture 3.
- Implement time addition on matches, such that scoring a match extends the timer by 1 second per tile in a match.
- Ensure Level 1 starts just with simple flat blocks (the first of each color in the sprite sheet), with later levels generating the blocks with patterns on them (like the triangle, cross, etc.). These should be worth more points, at your discretion.
- Creat random shiny versions of blocks that will destroy an entire row on match, granting points for each block in the row.
- Only allow swapping when it results in a match. If there are no matches available to perform, reset the board.
- Implement matching using the mouse. (Hint: you’ll need
push:toGame(x,y); see thepushlibrary’s documentation here for details)!
Getting Started
Download the distribution code for your game from cdn.cs50.net/2d/2025/x/projects/3/match.zip and unzip match.zip, which should yield a directory called match.
Then, in a terminal window, move to the directory where you extracted match, and run
cd match
A Match (3) Made in Heaven
There was a lot to learn with timers, tweens, and more in this lecture, but unfortunately, our game is still lacking in a few areas. By extending its functionality, we’ll have something even closer to famous titles such as Bejeweled and Candy Crush Saga!
Specification
-
Implement time addition on matches, such that scoring a match extends the timer by 1 second per tile in a match. This one will probably be the easiest! Currently, there’s code that calculates the amount of points you’ll want to award the player when it calculates any matches in
PlayState:calculateMatches, so start there! -
Ensure Level 1 starts just with simple flat blocks (the first of each color in the sprite sheet), with later levels generating the blocks with patterns on them (like the triangle, cross, etc.). These should be worth more points, at your discretion. This one will be a little trickier than the last step (but only slightly); right now, random colors and varieties are chosen in
Board:initializeTiles, but perhaps we could pass in thelevelvariable from thePlayStatewhen aBoardis created (specifically inPlayState:enter), and then let that influence whatvarietyis chosen? -
Create random shiny versions of blocks that will destroy an entire row/column on match, granting points for each block in the row. This one will require a little more work! We’ll need to modify the
Tileclass most likely to hold some kind of flag to let us know whether it’s shiny and then test for its presence inBoard:calculateMatches! If the match is horizontal and involves a shiny block, destroy the row; if the match is vertical and involves a shiny block, destroy the column. -
Only allow swapping when it results in a match. If there are no matches available to perform, reset the board. There are multiple ways to try and tackle this problem; choose whatever way you think is best! The simplest is probably just to try and test for
Board:calculateMatchesafter a swap and just revert back if there is no match! The harder part is ensuring that potential matches exist; for this, the simplest way is most likely to pretend swap everything left, right, up, and down, using essentially the same reverting code as just above! However, be mindful that the current implementation uses all of the blocks in the sprite sheet, which mathematically makes it highly unlikely we’ll get a board with any viable matches in the first place; in order to fix this, be sure to instead only choose a subset of tile colors to spawn in theBoard(8 seems like a good number, though tweak to taste!) before implementing this algorithm! -
Implement matching using the mouse. (Hint: you’ll need
push.toGame(x,y); see thepushlibrary’s documentation here for details!* This one’s fairly self-explanatory; feel free to implement click-based, drag-based, or both for your application)!
Have fun!
Be sure to comment your code in the places where you implement the above items. This is true for all implementations, but particularly if you do so in a spot we might not expect you to.
Errata
NONE
How to Submit
When you submit your project, the contents of your branch must match the file structure of the unzipped distribution code exactly as originally received. That is to say, your files should not be nested inside of any other directories of your own creation or otherwise deviate from the file structure we gave you. Your branch should also not contain any code from any other projects, only this one. Failure to adhere to this file structure will result in your submission being rejected.
By way of a simple example, for this project that means that if the grading staff visits https://github.com/me50/USERNAME/blob/games50/projects/2025/x/match/src/Tile.lua (where USERNAME is your own GitHub username as provided in the form, below) we should be brought to your Tile.lua file for Match-3. If that’s not how your code is organized when you check (e.g., you get a 404 error or don’t see your edits), reorganize your repository as needed to match this paradigm. Code improperly organized will not be eligible for a passing score.
- If you haven’t already, visit this link, log in with your GitHub account, and click Authorize cs50. Then, check the box indicating that you’d like to grant course staff access to your submissions, and click Join course.
-
Install Git and, optionally, install
submit50. -
Using Git, push your work to
https://github.com/me50/USERNAME.git, whereUSERNAMEis your GitHub username, on a branch calledgames50/projects/2025/x/matchor, if you’ve installedsubmit50, executesubmit50 games50/projects/2025/x/matchinstead.
-
Record a screencast, not to exceed 5 minutes in length in which you demonstrate your game’s functionality. Upload that video to YouTube (as unlisted or public, but not private). This video’s requirements are:
- It is not a YouTube “short”.
- The video begins with a slide or text overlay containing both your edX and GitHub usernames.
- It must show your game live and in action. Do not use this video to walk us through any code.
- It demonstrates that all five (5) items of the specification have been implemented.
- The video description has been timestamped at the (first) point where your video demonstrates each of the above-referenced implementations.
- The video has been uploaded less than one month from the time of your submission of the form for this project (the final step below).
- Submit this form.
You can then go to https://cs50.me/cs502d to view your current progress!