# **Tetris**
:::danger
<b>Assignment Release: Saturday, November 2nd, 2024
Early Handin: November 9th, 2024
Regular Handin: November 11th, 2024
Late Handin: November 13th, 2024
</b>
:::
Watch the demo [here](https://www.youtube.com/watch?v=sPyzJtfCjdA)!
# Assignment Roadmap
:::info
[Silly Premise](#Silly-Premise)
[Collaboration Policy Reminder](#Collaboration-Policy-Reminder)
[New Concepts Covered](#New-Concepts-Covered)
[Helpful Resources](#Helpful-Resources)
### **[ASSIGNMENT SPECIFICATIONS](#ASSIGNMENT-SPECIFICATIONS)**
[Important Prelude](#Important-Prelude)
[Installing Stencil Code](#Installing-Stencil-Code)
[Coding Incrementally](#Coding-Incrementally)
[Section Checkpoint](#Section-Checkpoint)
[Bells and Whistles](#Bells-and-Whistles)
[Handing In](#Handing-In)
[README](###README)
[Handin](#Handin)
### **[FUNCTIONALITY](#Functionality)**
[Minimum Functionality Requirements](#Minimum-Functionality-Requirements)
[Full Functionality Requirements](#Full-Functionality-Requirements)
### **[DESIGN DETAILS](#Design-Details)**
[Design Questions](#Design-Questions)
[The Pieces](#The-Pieces)
[Moving and Rotating Pieces](#Moving-and-Rotating)
[Animation and Timelines](#Animation-and-Timelines)
[Piece-Board Interaction](#Piece-Board-Interaction)
[Constants Class](#Constants-Class)
[Keyboard-Interaction](#Keyboard-Interaction)
:::
## Silly Premise
Oh No! Azula is trying to drill through the Ba Sing Se walls! After two long nights of sieging, the defending earthbenders have realized that they have come up with a foolproof way to destroy the machine - hurling endless tetriminos down onto the machine. The only problem is that they don’t have a version of tetris where they can practice getting those perfect four row stacks! Good thing they have found an incredibly capable CS15 student (you!) within the walls of the city who is there to help!
Reference: Avatar the Last Airbender, Nickelodeon

## Collaboration Policy Reminder
If you ever have questions about the [collaboration policy](https://docs.google.com/document/d/10rbbd0Y6s1JUzPe8VmoWcL_Mz26XczX-i7p2LUFa9vc/edit?usp=sharing), refer to the collaboration policy or ask a TA!
<img style="display: block; margin: auto; padding-top: 15px;" src=https://hackmd.io/_uploads/BkSOpo1nC.png width=600px>
:::danger
**Note:** The usage of any artificial intelligence technologies, except those explicitly endorsed by CS15, is *strictly prohibited*. Because of TAs reading your code and a software package we use called MOSS (Measure of Software Similarity), illegal collaboration is easily detected in CS15.
:::
## New Concepts Covered
* Nested **`for`** loops
* Arrays
* Writing algorithms
* Designing a **large** program
## Helpful Resources
* This handout!
* [Tetris Pieces Code-along Recording](https://www.youtube.com/watch?v=26eNWBTScCI)
* The [demo](https://www.youtube.com/watch?v=sPyzJtfCjdA)
* The [help slides](https://docs.google.com/presentation/d/12IWPbhLZo3qtgmvpPfmlpns1y4L9ybpfAlsphi4HJsM/edit#slide=id.g4194649a4_00)
* [Style Guide](https://docs.google.com/document/d/1olSJxbrhuIystA_kVbmKu4V8JfN7HE-eDzM5blkoeFw/edit#heading=h.b1nvuu1nggmv), [GitHub Guide](https://docs.google.com/document/d/1tSxfUIn-Ro6Pr1X4y21BbYKdsiK-nlWW3pGDfyh7SQ8/edit), and [README Guide](https://docs.google.com/document/d/1QJPit-_8ZC3r4l_f5F3ydMK34-NchBYgwtm0c21iwsU/edit)
* [CS15 JavaFX Guide](https://docs.google.com/document/d/1cOq649OLNp0-UHxz5W5KAOH-KyM2VXvq_TKmuGHv0Rg/edit) and [JavaFX Javadocs](https://docs.oracle.com/javase/8/javafx/api/toc.htm)
* [CS15 Debugging Guide](https://docs.google.com/document/d/1UmARFvKHt5_llLrRJ61exDU-hj1mZ_LTVOTLBtIppmo/edit#heading=h.lmkvfgj19o2i)
### Help Slides
:::info
We highly recommend looking through the [Tetris Help Slides](https://docs.google.com/presentation/d/12IWPbhLZo3qtgmvpPfmlpns1y4L9ybpfAlsphi4HJsM/edit#slide=id.g4194649a4_00) to get a better understanding and hints for the project.
:::
# ASSIGNMENT SPECIFICATIONS
*Your assignment is to write the CS15 version of the game Tetris. If you are not familiar with Tetris, you should watch the [demo](https://www.youtube.com/watch?v=sPyzJtfCjdA) as soon as possible in order to see how the game works. There are many renegade versions of Tetris out there, with slight differences among them; to give you a better idea of what your assignment entails, read the following description of how the CS15 version of Tetris behaves.*
When the game starts, only an empty board with a border drawn around its edges should be displayed. A Tetris piece, chosen randomly from the seven possible Tetris pieces shown below, should appear at the top of the board.
This piece should fall by moving down the board, one row at a time. A piece cannot move into a square already occupied by a previously fallen piece. When a piece can fall no further, it should stop moving. A new random piece should then appear at the top of the board and begin to fall.
As pieces fall, full rows (or horizontal lines) of occupied squares spanning the board's width may form. When such a full row is formed, it disappears and all the squares above it are moved down one line to fill the newly empty row. This process continues until there is **a piece in the top row of the board**. The game is then over, and everything on the board should stop completely - pieces should stop being generated or moving, and the piece should not be able to be moved by pressing any keys. A message should be displayed to let the user know that the game is over.

**The seven Tetris pieces:** Each is an arrangement of four connected squares. We want to ensure that all piece colors pass Web Content Accessibility Guidelines (WCAG) 2.1 for accessible color contrast ratio. You will be tasked with picking 6 colors that will have an appropriate contrast ratio with respect to the black (or any other color) background!
While a piece is falling, the player may rotate or shift it by pressing certain keys on the keyboard:
* Pressing the **left** arrow should shift the piece one square to the left.
* Pressing the **right** arrow should shift the piece one square to the right.
* Pressing the **up** arrow should rotate the piece counter-clockwise by ninety degrees.
* **Note that square pieces should neither rotate nor move even if up is pressed.**
* At regular intervals, the piece should fall one row at a time. Pressing the **down** arrow should drop the piece an additional row each time, making the piece fall more quickly.
* The player should be able to drop the piece by pressing the **spacebar. This is an integral part of the game (otherwise the game would go very slowly). Please make sure that this feature is implemented.** By dropping a piece, the player forfeits their chance to manipulate the piece any further and the piece simply falls as far as it can.
The player should be able to pause the game at any time by pressing **‘p’**. Pressing **‘p’** again should allow the user to resume play. *When the game is paused or over, text should be displayed to notify the user, and the user should no longer be able to manipulate pieces.*
To reiterate, your program should have the following functionality (all of which can be seen in the demo):
* The seven pieces pictured above should be randomly generated
* At the start of the game, a random piece should appear and move down the screen, one square at a time
* Pieces should stop moving when they can fall no further; a new randomly generated piece should then appear at the top and fall down the screen
* When a row is full, it should be cleared and every row above it should move down
* The user should be able to interact with the game in the following ways:
* Pressing the **left** and **right arrow keys** should move the current piece left and right as *long as this would not move the piece into an occupied square or offscreen*
* Pressing the **up arrow key** should rotate the current piece 90 degrees counterclockwise. *Pressing up **should not** affect the square piece visually*.
* Pressing the **down arrow key** should move the piece down one row
* Pressing the **spacebar** should drop the piece as far as it can go, maintaining current rotation and left/right position
* Pressing **the ‘p’ key** should pause the game if it is running, unpause it if it is paused - when paused, **text** should be displayed to alert the user, and the piece **should not** be able to be manipulated with the arrow keys or space bar.
* When a piece is in the top row of the board or there is no room for a new piece to appear, the game is over. Text should be displayed to alert the user, and the piece should no longer move either due to a timeline or due to key input.
* A quit button
## Important Prelude
As with DoodleJump, you should **start early** and **code incrementally**. *Design the entire program before you start coding*! Please come to Conceptual Hours with any questions about design and implementation. Come to Debugging Hours only with bugs that you can't solve on your own. The IntelliJ Debugger, printlines, and other resources we’ve provided will help you fix most problems that you face (there is a [debugging guide](https://docs.google.com/document/d/1UmARFvKHt5_llLrRJ61exDU-hj1mZ_LTVOTLBtIppmo/edit#heading=h.lmkvfgj19o2i) on the website).
**<font color="#ff0000">Additionally, for this project, the [help slides](https://docs.google.com/presentation/d/12IWPbhLZo3qtgmvpPfmlpns1y4L9ybpfAlsphi4HJsM/edit#slide=id.g4194649a4_00) are particularly helpful. Please read through them and, if you have any questions please post on ed or come to hours.</font>**
If you go to TA hours seeking debugging help, **be prepared to show the TA ++extensive debugging efforts++. *If the TA feels that you haven’t spent enough time trying to solve the bug, they have the right to refuse you.*** It is in your best interest to remove yourself from the list if you resolve your bug or feel as though you haven’t debugged sufficiently, if you don’t you will get turned away and have to wait an hour to sign up again (as per the TA hours policy).
## Installing Stencil Code
Click **[here](https://classroom.github.com/a/28ZyHxBn)** to get the stencil from GitHub - refer to the [CS15 GitHub Guide](https://docs.google.com/document/d/1tSxfUIn-Ro6Pr1X4y21BbYKdsiK-nlWW3pGDfyh7SQ8/edit) for help with GitHub and GitHub Classroom.
Once you’ve cloned your personal repository from GitHub, you’ll need to rename the folder from **`tetris-<yourGitHubLogin>`** to just **`tetris`**. You will have issues running your code until you make the change.
## Grading
The grade for this assignment will be determined by [functionality](#Functionality) (45%), [design](#Design) (35%), and [style](#Style) (20%). An ‘A’ project would meet mostly all [full functionality](#Functionality) requirements with good design and style.
## Coding Incrementally
**Step 1:** Watch the [demo](https://www.youtube.com/watch?v=sPyzJtfCjdA)
**Step 2:** ***Thoroughly read this handout*** to make sure you understand the project design
**Step 3:** Read through the help slides
**Step 4:** Go through and develop a thorough design plan for your program
* Unlike previous projects, we aren’t providing you with the incremental coding order. You should come up with a roadmap for incremental coding!
**Step 5:** Start coding! It is important to code **incrementally**, meaning you completely accomplish one logical task before moving on to the next one. Always remember to test as you go!
### Section Checkpoint
This project will have a checkpoint with TAs to ensure you’re on track, and answer any questions you might have!
By your **section**, you should have the following steps completed for Tetris.
**<font color="#ff0000">The checkpoint is **much less than halfway through the project** and is there to make sure that you get started. The later parts of this project can be more time consuming than the first parts so please make sure you **keep working on it after you meet the checkpoint**! *
</font>**
1. Fill in the **`App`** class to make the project window appear.
2. Set up the **`Panes`** for your project in your **`PaneOrganizer`**.
3. Set up the board of squares with a visible border.
4. Make **at least one** Tetris piece appear at the top of the screen.
## Bells and Whistles
There is plenty of room for creativity in this assignment. **Remember:** First get your program to meet the specs; then, if time permits, go ahead and add Bells & Whistles!
Here are some suggestions for Bells & Whistles:
* Keep score and line count (remember: completing 4 lines at once is a Tetris!).
* Make the game progressively harder (e.g., make the pieces drop progressively faster) as the player completes more and more lines.
* Allow the player to change the difficulty at any time with the push of a button
* Allow the player to restart the game at any time (i.e., aborting the current game and starting a new game immediately).
* Allow the player to see the next piece which will fall down the screen.
* Give the player the ability to ‘store’ a piece they don’t want to use right now for later use.
* 2-Player Tetris
* 2-Player Tetris against AI
* Research accessibility considerations for colorblindness and implement a colorblind mode in your Tetris game that ensures elements are distinguishable by players with various types of color vision deficiencies. Explain this in your README.
Anything you can think of! Please document these bells and whistles in your Readme :)
Remember that you should make sure that you have a fully functional program before working on extra credit. Remember, from the [Course Missive](https://docs.google.com/document/d/1_zT7i5ApBusdW0GKzz5U939mZBQD02p5wG5e8V49cbg/edit?usp=sharing):
>“Extra credit is only to be done after the original assignment has been fully completed - if you have not met the requirements, you will not receive extra credit. Extra credit may not redefine the original assignment.”
## Handing In
### README
In CS15, you’re required to hand in a README file (must be named README) that documents any notable design choices or known bugs in your program. **Remember that clear, detailed, and concise READMEs make your TAs happier when it counts (right before grading your project).**
You are expected to create your own README file. Please refer to the [README guide](https://docs.google.com/document/d/1QJPit-_8ZC3r4l_f5F3ydMK34-NchBYgwtm0c21iwsU/edit) for information on how to create a README, what information your README should contain, and how you must format it. If you decide to implement any extra credit, please detail it in an **EXTRA CREDIT** section. As in previous projects, you are required to turn in your ++**diagram**++ as part of your README.
Label a section in your README titled ‘SRC.’ Include an explanation of the colors you chose and how they meet the standards of accessible design. Don’t overthink it!
At the bottom of your README, add the approximate number of hours you spent on this project. This will be used only to average how long the projects are taking students this semester, and it is completely anonymous.
### Handin
In order to hand in your code, submit your Tetris GitHub repository to Gradescope.
You can submit as many times as you want prior to the deadline, and only your most recent handin will be graded. If you handin before the deadline and again after the deadline, the submission will be counted as late.
**<font color="#ff0000">Do not include any identifying information on your handin (name, login, Banner ID) as we grade anonymously.</font>** **Including identifying information will result in a deduction from your assignment.**
---
# Functionality
## Minimum Functionality Requirements
MF Policy Summary: *In order to pass CS15, you will have to meet minimum functionality requirements for all projects. If you don’t meet them the first time around, you may hand the project in again until you succeed, but you will keep your original grade. MF requirements are **not** the same as the requirements for full credit on the project. You should attempt the full requirements on every project to keep pace with the course material. An ‘A’ project would meet all of the requirements on the handout and have good design and code style.*
To meet MF for Tetris:
* There are at least 6 kinds of randomly generated pieces that fall down the screen using a Timeline.
* Can move pieces left and right with the arrow keys.
* Can rotate pieces to 4 positions in “open space”, preserving the layout/shape of the Piece.
* Pieces cannot move through/overlap other pieces/the border when falling or moving.
* Lines clear when full, and board updates graphically and logically.
* When a line is full, all blocks in it should disappear and all pieces above should move down.
* Subsequent pieces should not “float on air” after a line has been cleared - this means that all squares above the row that was cleared should move down to fill in the space of the row that was just cleared.
* If a newly generated piece cannot move, pieces should stop being generated (game over).
## Full Functionality Requirements
Beyond the minimum functionality requirements, the rest of the functionality grade will depend on the following criteria:
* Seven pieces randomly generate
* The user should be able to interact with the game in the following additional ways:
* Pressing **the ‘p’ key** should pause the game if it is running, unpause it if it is paused - when paused, **text** should be displayed to alert the user, and the piece **should not** be able to be manipulated with the arrow keys or space bar.
* Pressing the **down arrow key** should move the piece down one row.
* Pressing the **spacebar** should drop the piece as far as it can go, maintaining current rotation and left/right position.
* Create a **‘Quit’ button** that closes the game.
* Every piece’s color should pass Web Content Accessibility Guidelines (WCAG) 2.1 (which can be confirmed/tested using https://contrast-ratio.org/ with the hex values of the color constants you are using, e.g., #FF0000) when compared to the color of the board (this can be black by default, but feel free to change this as well…!). Use the [JavaFX Javadocs](https://docs.oracle.com/javase/8/javafx/api/javafx/scene/paint/Color.html) to find more color options and their hex values. Document and explain your color choices in your README.
## Design Questions
There are several new concepts used in this assignment. Before you start designing and coding Tetris, you should make sure that you completely understand all of the concepts listed in this handout. Be sure to review the lecture slides, read Ed, and visit Conceptual hours and/or Debugging hours if you need further clarification. Tetris will be much easier to design and code if you thoroughly understand these concepts before you start.
Run the Tetris demo. Once you are familiar with how the CS15 version of the game behaves, you should think critically about your design. You will want to think about how to:
* Randomly create the different pieces
* Make it easy to add new types of pieces (extensibility)
* Make new pieces appear at the top of the board
* Keep track of each piece’s current location
* Make pieces fall
* Shift pieces to the left or to the right
* Rotate pieces
* Check if a desired move is legal - i.e., do not move a piece into a square that’s already occupied or outside the edges of the board
* Keep track of where the pieces have fallen
* Check if a row has been formed
* Update the board after a horizontal line disappears
* Stop the piece when the game is paused
* Check for the end of the game
* Prevent user input when the game is paused
* Actually stop playing the game and start coding
**Note:** You’ll notice that in many cases, there are several different classes that could handle the desired functionality. For example, either the piece or the board could be responsible for checking move legality. When making design decisions, think carefully about the tradeoffs between designs. All designs have their pros and cons - make sure your decisions are well justified for your design discussion and in your header comments!
## The Pieces
One major design consideration for the **`Pieces`** is how to create seven different **`Piece`** shapes while factoring out as much code as possible.
You will be using random numbers to decide which one of the seven possible Tetris piece shapes will be the next to appear (Remember **`Math.random()`** from Fruit Ninja and DoodleJump?). How can you employ the **++*factory pattern*++** to your advantage? Take a look at the [Math and Making Decisions](https://cs.brown.edu/courses/cs015/lecture/pdf/CS15.Lecture_8_Math_and_Making_Decisions.10.1.24.pdf) lecture for more information. We will also discuss the factory pattern in more detail at the algorithms section.
You’ll also need to consider how you want to add the individual squares in your **`Pieces`** to the Pane so that they are displayed on the screen. **Hint:** Look at the [JavaFX Lab](https://hackmd.io/@Fall2024-CS15/rkrTBrCs0) for a detailed reminder of how to add multiple objects of a similar type to a Pane.
## Moving and Rotating Pieces
When the user tries to move a piece to a new location, the piece should move only if the new location is not already occupied by a previously fallen piece and is not beyond the edges of the board.
In other words, if you are keeping track of already occupied squares within a board, then as the current piece falls, you simply have to check with the board to see if the squares where it wants to move are already occupied. This same sort of checking should be used for rotations. If all squares of the Tetris piece can make a valid move, then the piece can move/rotate; if any one of these squares is not free, then the piece cannot move/rotate.
Properly rotating a piece can be tricky, so here’s some of the math. To move a point 90 degrees counterclockwise in a circle around another point, you can use these formulas:
<b>new<font color="#00f">X</font>Location = centerOfRotation<font color="#00f">X</font> - centerOfRotation<font color="#f00">Y</font> + old<font color="#f00">Y</font>Location</b>
<b>new<font color="#f00">Y</font>Location = centerOfRotation<font color="#f00">Y</font> + centerOfRotation<font color="#00f">X</font> - old<font color="#00f">X</font>Location</b>
where **`newXLocation`** and **`newYLocation`** are the new coordinates of the point being moved, **`centerOfRotationX`** and **`centerOfRotationY`** are the coordinates of the *fixed* point around which this point is moving, and **`oldXLocation`** and **`oldYLocation`** are the original coordinates of the point being moved. For your Tetris pieces, you should use the location of one of the squares in your piece. For more information on these equations, check out the [help slides](https://docs.google.com/presentation/d/12IWPbhLZo3qtgmvpPfmlpns1y4L9ybpfAlsphi4HJsM/edit#slide=id.g4194649a4_00).
## Animation and Timelines
Like in previous projects, you’ll find a **Timeline** useful in controlling your pieces. Take a look at the [Graphics Part II lecture](https://cs.brown.edu/courses/cs015/lecture/pdf/CS15.Lecture_10_Graphics_Part_II.10.8.24.pdf) if you need to review tips and tricks for Timelines.
## Piece-Board Interaction:
The relationship between a piece and the board is as follows:
* Once a piece has fallen, the squares from that piece should (1) remain on the screen in their original color, (2) block other pieces' motion, and (3) be able to be removed from the board in rows.
* When clearing lines:
* You may only be removing part of what used to be a whole Tetris piece.
* Once a row has been removed, all the rows above it should move down one row.
**Remember:** Whenever you want to add or remove something from the scene, you need to add or remove that **`Node`** to/from the Pane in order to see a visible change.
* Prevent pieces from moving or rotating off the edge of the board. You could do this by checking the boundaries of your board's array, but it might be easier to come up with a design that allows edge-checking to occur in the same way as checking occupied squares within the board.
**Hint:** Take a look at the demo and think about how you might accomplish this.
## Constants Class
For Tetris, we’ve given you an incomplete **`Constants`** Class that has 3 constants that we’ve defined for you. The first constant we define is an integer that denotes the size of each of our squares. The second and third constants are integer arrays that use the **`SQUARE_WIDTH`** constant to define the locations of 4 squares in a tetris piece. To understand what **`T_PIECE_COORDS`** constant array represents, look at the graphic below. Think about what other coordinate arrays might look like and how you can use them! You will need to fill in the rest of this class with any more constants you need!
<img src="https://hackmd.io/_uploads/HkYqR1GnA.png" alt="Tetris piece" width="400" style="display: block; margin: auto">
## Keyboard Interaction
It’s that time again! You will once again be implementing keyboard interaction to allow the user to shift, rotate, and drop pieces, as well as pause the game.
As with before, the method we recommend involves using the interface **`javafx.event.EventHandler<KeyEvent>`**. You are welcome to use other ways of implementing keyboard interaction, of course, as long as they are readable and function well (but be aware that the TAs may not be familiar with a different implementation).
If you need to brush up on your keyboard-wizarding skills, refer to the Javadocs or [DoodleJump Handout](https://hackmd.io/@Fall2024-CS15/SkNDBHAs0) for pointers.
For a complete list of the different **`KeyCodes`**, go to: [Javadocs](https://docs.oracle.com/javase/8/javafx/api/javafx/scene/input/KeyCode.html).
**User Input Summary:**
Here’s a handy summary of all the required user inputs and what they should do:
* **Left Arrow Key:** Moves currently falling piece one space to the left
* **Right Arrow Key:** Moves currently falling piece one space to the right
* **Up Arrow Key:** Rotates currently falling piece 90° counter-clockwise
* **Down Arrow Key:** Moves the currently falling piece one space down
* **Spacebar:** Drops the current piece as far as it can go
* **‘P’ Key:** Pauses/unpauses the game
Good luck and remember:
**<font size="6" style="display: block; font-family: cursive; text-align: center; margin-left: auto; margin-bottom: -20px;">Start Early... Start Today... Start Yesterday!</font>**
<font style="display: block; text-align: center; font-family: courier">- William Shakespeare</font>
<img src="https://hackmd.io/_uploads/S1luUgM30.png" alt="Avatar picture" width="500" style="display: block; margin: auto">