Homework 2 

(20 points)

Tetris - Part 2


You will be completing the game Tetris. The features needed are
    1.  Adding the other 6 pieces
    2.  Adding the ability to rotate the pieces


The purpose of this assignment is to gain experience with the following new concepts:


Implementation Requirements

OTHER PIECES:  The first step in  the assignment is to add  the other six pieces.   Let's think a little about the planning though;  we don't want the Game class to have to know about all 7 different piece types (we wouldn't want Game to have 7 different instance variables, 1 for each type. How would it keep track of which one was current?)  Instead,  Game should know about 1 type ( a super type) and let dynamic dispatch do the work for us.

So to start, we need to redesign (or refactor)  the current code.  To do this, we want a super type that contains all of the behaviors common to all of the pieces. This can be achieved with an interface Piece. Then sub types will implement the interface for the individual pieces and their individual needs.  However, some implementations will be the same for all of the pieces (e.g. getColor()). To avoid repeating code, the implementation of the methods common to all of the pieces can be written in an abstract class AbstractPiece that implements the Piece interface. This abstract class will also list the fields that are common to all of the pieces.

So what is the same about all of the pieces?

What is different about each piece: 1) Therefore, start by breaking up the LShape.java class into an interface (Piece), an abstract class (AbstractPiece) and a sub class (LShape with most of its code removed).  At this point, test your program.  It should run as it did before.

2) Now it is time to add the other pieces.  You should create these new classes by deriving them from the AbstractPiece class. In the order they appear in the picture below, you can name the classes ZShape, SquareShape JShape, TShape, SShape, BarShape.  In particular, you will need to figure out how to initialize the pieces.   This will be similar to how the L-shaped piece was done, and, in fact, you may find it helpful to start each new class by copying the code from a previous shape and modifying it.  The pieces should be initalized in the following orientations:

where the numbers refer to the index of each square in the 1D array of squares (Square[] square). The actual values of the indices don't really matter at this point, but they will become relevant when we talk about rotation. In the constructors of the pieces, take (r,c) to be the row and column indices of square[1].

ROTATION: The current tetris piece needs to be able to rotate in quarter turns clockwise each time the down arrow key is pressed. As an example, see the figure below illustrating how the L-shaped piece rotates one full turn:

We will take the convention that all pieces rotate about their square at index = 1 (except for the gray square shape that shouldn't rotate). That is, after a rotation, the square at index 1 should not have moved in the grid. All of the other squares of the piece will have moved clockwise by 90 degrees. The image below shows how the L shape piece rotates within the grid: notice that the square at index 1 stays at the same location.

To implement the rotation feature in your code, do the following:

  1. Add the abstract method  void rotate(); to the Piece interface. 
  2. Implement the rotate()  method in AbstractPiece.  A piece should only rotate if the grid squares that it would pass through and occupy are all empty and in addition are all within the boundaries of the grid (i.e. the row index is greater than or equal to zero and less than Grid.HEIGHT and the column index is greater than or equal to zero and less than Grid.WIDTH). To check if a square can move, you can model its path as a square path about the square at index 1 (and not as an actual circular path, in which case the square could sweep through part of a square of the grid.)
  3. Add the  public method rotatePiece() to the Game class.  This method should be very similar to the movePiece() method except that it tells the piece to rotate.
  4. Add a new case to the keyPressed method in the EventController class to react to the down arrow key.

Unit testing

Add method(s) to the unit testing class that you developed in homework 1 to test the rotation of all of the pieces. Write tests that check that the rotation goes as planned when it is allowed. Write also tests that check that no rotation is done when the piece can't rotate because of a lack of space. You may modify some of the existing classes to add methods that return the values of some of the instance fields to check them in your tests. For instance, you may implement a getSquareArray method in AbstractPiece that returns the array of squares of the piece.


Diagram / Written report (should be typed and turned in as a pdf file)

Your program has to be your own.