(Mondays 2 PM)
(Fridays 2 PM)
|16||Apr||None||26||Apr (No late coupon)|
Remember to type the following lines at the top of any files that use the terminal or canvas classes.
import cs101.terminal.*; import cs101.canvas.*;
The design of this lab is somewhat different than Lab 10. The notion of a Side is gone. The reason is that the tetris pieces will occupy space on a grid-like canvas. It is therefore the area of the squares that count, and not the inducing vector.
Thus, pieces are constructed differently than before. For examples, take a look at TetrisGamma and its antimatter twin TetrisAmmag. You will have to construct the other Tetris pieces yourself.
This document describes the design without telling you the coding details. That is, the overall structure of the solution is given, but actual code is provided by you.
It is helpful to think of a tetris shape as if it were constructed of squares that are glued together:
|Above, you see a tetris piece (the Gamma piece, named for the shape of the Greek letter) in outline form, as you would see the piece when you play.|| Above, you see how the piece is constructed
using four square blocks. Check out the constructor in
A Tetris piece is constructed by gluing
block B is glued to block A, block B must follow block A around,
wherever A might go. When block B is glued to block A, block B is told
its offset, grid-wise, from block A.
moves around, so must the blocks glued to it. The blocks glued to it
Since a block has four sides, it can have at most four listeners.
You will keep track of a block's listeners using an array .
A block is moved by calling its
method. That block, in turn, must call its listeners'
A block is rotated by calling its
That block, in turn, must call its listeners'
To ease the placement of tetris shapes, you will extend
CS101CanvasGrid, so that
the space can be regarded as a grid of rectangles,
each of which is occupied or not occupied.
Additionally, this kind of canvas is setup so that it can listen to
key presses and call methods based on them. The class can register an
ArrowListener, so that
methods of the listener are called based on key presses as follows:
|On some computers, for some windowing systems, the arrow keypresses may not be transmitted. Thus, each gesture is duplicated by a text key. The keys are chosen to mimic the intended direction, based on the number keys' arrangement on the numeric keypad of most keyboards.|
|Key Press||Method Called|
| 2 |
| 4 |
| 6 |
| 8 |
the game, it will want to register itself as the
Here is the API:
CS101CanvasGrid(int nc, int nr)
Then, a grid (two-dimensional array)
set up. Initially, all grid locations are unoccupied
except those at the extreme
left, right, and bottom of the canvas.
setOccupied(int i, int j, boolean val)
jis occupied (if
valis true) or unoccupied (if
boolean isOccupied(int i, int j)
Rectso that a rectangle can remember whether it is occupied or not. In the extension, the following methods must be provided:
GridSquare(int col, int row, int squaresize)
Rectat the desired column and row. Remember to convert from column and row to pixel coordinates, using the supplied square size.
public void setOccupied(boolean val)
public boolean isOccupied()
Color.red. When the rectangle is unoccupied, it sets its color to
TetrisGame. You will need to add
selfTestcalls for any classes you add.
curPieceis the piece currently being manipulated on the screen.
TetrisGame(int cols, int rows, int pieces)
piecesparameter could be used to limit the number of pieces offered in a game. If your game continues indefinitely, you may choose to ignore this parameter.
Math.random()so that the pieces are randomly and uniformly distributed.
Note that polymorphism allows a particular shape (
TetrisTee, etc.) to be treated as the generic
If we used Java threads and concurrency, we could advance the piece down the screen automatically even if the user didn't do anything. This is what a real game would do, and you will learn about concurrency in CS 102.
ArrowListener, it must implement the methods in that interface:
TetrisBlock(leader, canvas, dX, dY)
leader, offset in grid positions by
For each of the following methods, once "this" TetrisBlock has performed its intended action, the block should invoke the same method on each of its listeners.
dYmust be adjusted, as discussed in class.
dYto its leader's coordinates.
TetrisPiece(CS101CanvasGrid canvas, int col, int row)
dYof 0. The column and row for "this" block is then established as the parameters' values.
boolean proposeMove(int newCol, int newRow, int oldCol, int oldRow)
allClearat the new location.
TetrisPiece(and therefore, on "this"
TetrisBlock) are propagated to all blocks making up this piece.
abstract String name()
Each of the following actions,
be reduced to a call to
proposeMove. Each returns
true if the move is successful; otherwise, false is returned.
Rotation requires a little more work. We have to try the rotation, and if it doesn't work out, then we have to unrotate the piece. Hint: You can unrotate a piece by rotating it three more times counterclockwise.
allClearat the new location.
Each of the
following objects extends
to obtain a particular kind of Tetris piece.