(Mondays 2 PM)
(Fridays 2 PM)
| || 9 ||Apr
|| 12 ||Apr
|| 16 ||Apr
(click the name to play)
- A game of skill, cunning,
strength, and endurance.
- A game where you match your wits against a computer program written
by a clever, CS101 student, who is just two labs
away from finishing this course.
- A game where dangerous (sharp and rectangularly constructed)
shapes plunge from death-defying heights on a
moving at tens, perhaps hundreds of pixels per second,
guided only by your skill (or the skill of a Java class implementing
the proper interface).
- A game where you show you are not afraid to
set up objects that communicate with each other, so as to determine
their position on the screen.
By the end of this lab, you should
This lab contains two parts, design
and implementation, due on the dates shown above by 2 PM.
- Tire of your professor's hyperbole in describing labs
- Understand how to create tetris shapes by composing objects
- Understand some of the mathematics that underlies graphics programs
- Understand how to rotate tetris shapes, using
a simple listener model
The design will be discussed Monday in class.
your graded design will be returned.
No other handouts or code will be issued. So, think
carefully about your design!
[[[ Download PC zip ]]]
- Read over this entire document before you start.
- Run the sample solution.
- If you need help, please ask.
- Files you are given but you shouldn't modify:
- Files you are given that you must modify:
type the following lines at the top of
any files that use the
Although this lab does not involve a lot of coding, it is tricky. In the
design, you apply (high-school) algebra to simplify what must be done
in the lab.
This lab will combine with the next lab to make a Tetris game. The division
of work is as follows:
- In this lab, you analyze how to construct, translate (move),
and rotate Tetris shapes.
- In the next lab, you give control to a player, who can manipulate
the shapes by hand, while the computer continuously lowers the piece down
What makes a tetris shape?
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.
You see that
one of the square blocks is distinguished; it is the main component,
or the first block put down to form this piece.
The entire piece is constructed of such blocks, glued together. When
block A is glued to block B, block A must follow the joined side around,
wherever that side of block A might go.
Each block is added to the piece in this way.
main block moves or rotates, so do its sides. Any piece joined
to a side that moves also moves, which moves its sides.
By moving one block of the piece, the entire piece eventually moves.
So, each block follows its glued side around.
Even the first block of a Tetris piece is glued to a special side, known
as the root side of the tetris piece. The root is invisible, but
movement of the root side causes the main block to move, which causes
the entire piece to move, as described above.
Above you see another kind of
tetris piece, the zigzag piece. Zigzag
is also constructed from four blocks,
but glued together differently from the first
piece you saw.
In this discussion, suppose the blocks in the above piece
are placed in
the order A, B, C, D.
When a block is placed, it must be glued to some side.
A side is essentially a vector,
with a length and direction. Above, you see a vector to the left of
the partially constructed block A. The vector runs from South to North.
The vector that induces block A is shown to the left of block A,
but really the vector conincides exactly with side 0 of block A.
The sides of a block are established as
- Side 0 is drawn as the reverse of the inducing vector.
Above, you see that side 0 of block A is the reverse of its inducing
The square is completed by placing three more sides, proceeding
counterclockwise to complete the square.
All squares are drawn in this manner. Side 0 is the first side drawn,
side 1 is the next side drawn, and so on.
Thus, picture above shows sides 0, 1, and 2 completed for block A. Side
3 would be drawn next, closing the square.
The zigzag piece is completed by
When block C is glued to block A, side 1 of block A is chosen as the
inducing vector. Thus, C's side 0 is drawn as the reverse of
A's side 1. The remaining sides of B are drawn by moving counterclockwise
to complete the square.
The picture above shows blocks A and C separated by space, but really
they would abut. Side 0 of C would coincide with side 1 of A.
- inducing block B at A's side 0.
- inducing block D at C's side 3.
How do you determine a square from the inducing side?
(covered in class)
The side that induces a block always coincides with the block's Side 0,
except that the inducing side runs the opposite direction. Once Side 0
of a block is determined, the other sides are given, since they proceed
counterclockwise, they are are all the same size, and they form the
sides of a square.
Side 0 of a block
will either be horizontal or vertical, and will either
point East, West, North, or South. Let us assume the
side is drawn from
(x,y) to (x+h, y+k). For any given Side 0:
In other words, Side 0 must be one of
the following vectors:
- One of h or k will be zero.
- The nonzero value will be +s or -s, where s is the size of the
side (and therefore the length of a side of the block).
Based on the particular value of h and k, we can
compute the four sides as follows:
|| (x,y) to (x,y-s)
|| (x,y) to (x+s,y)
|| (x,y) to (x,y+s)
|| (x,y) to (x-s,y)
|| From || To
|| (x,y) || (x+h, y+k)
|| (x+h,y+k) || (x+h+k, y+k-h)
|| (x+h+k,y+k-h) || (x+k, y-h)
|| (x+k,y-h) || (x, y)
How do we rotate a side?
Translating (moving) a side is simple: we can change the coordinates
of the side's starting and ending points by displacement.
Rotation is trickier. To rotate a tetris piece, we must rotate the
side that induces its main piece.
Above, you see an inducing side in its original state, and then taken
through 3 rotations.
A fourth rotation would return it to its
original state. Although the rotations are shown separated by space,
they would really abut so that each rotation moves the vector to another
side of a square.
The letter s refers to the length of the side.
Thus, the original vector goes from (x,y) to (x,y-s)
on a CS101
Graphics Canvas, because the "y" coordinate increases as you move down
We need a function that tells a side how to move when it is rotated.
One part is easy. Note that when a vector rotates, its new ending position
is its old starting position. But what about the new starting position?
assume that it is possible to obtain the new starting point from the
old one in some linear way. If so, then the following linear system of equations
will determine the next start.x from the previous start.x and start.y:
|| start.x || start.y || start.x || start.y
| x || y
|| x+s || y
| x+s || y
|| x+s || y-s
| x+s || y-s
|| x || y-s
| x || y-s
|| x || y
start.x start.y start.x
x a + y b + c = x+s
(x+s) a + y b + c = x+s
(x+s) a + (y-s) b + c = x
x a + (y-s) b + c = x
Similarly, we can formulate equations for the next start.y from the
previous start.x and start.y:
start.x start.y start.y
x d + y e + f = y
(x+s) d + y e + f = y-s
(x+s) d + (y-s) e + f = y-s
x d + (y-s) e + f = y
- This class is given and is self-explanatory. You might take
a look at the phrase
final public that declares
y instance variables.
- Contains the usual testing calls. You will need to add
selfTest calls for any classes you add.
- This class is used to represent a side of a block. A side can also
be stand-alone, in which case it probably controls a Tetris piece and is
- Self-explanatory. Optionally, a canvas and color can be provided,
in which case the side is drawn on the canvas. Otherwise, the side is
void displace(int shiftX, int shiftY)
- Shifts the side by the specified amount. This should be
accomplished by the appropriate call to
moveTo, so that
the listener can be informed of the move.
- Establishes the supplied
TetrisBlock as the object
that should be informed, via its
sideMoved, whenever this
- If there is a listener for this side, notify it that the
side has potentially moved.
moveTo(Point start, Point end)
- Any motion of the side funnels through this method.
The provided code does the following:
- Updates the side's start and end.
- If the
canvas is not null, then the line previously depicting this side is
removed, should it exist. Then, a new line is added to the canvas to show
the current location of this side.
- Notify the listener that the side may have moved.
- This class represents a block (square) that can be part of a
You have to set up the block as a listener to its inducing side. You
also have to place the block's four sides, given the analysis in this
- returns a reference to the desired side (0, 1, 2, or 3).
This is handy for obtaining a side to be an inducer for yet another
- is called by the inducing side whenever the side
potentially moves. Thus, a
TetrisBlock is a listener
of its inducing side.
- This is the base class for all Tetris pieces. The
instance variable is the inducing side.
You will have to complete the methods that cause movement and rotation,
updating the inducing side approprately. Notice that clockwise rotation
is taken care of for you.
- Creates a piece whose inducing side goes from (x,y) to
(x,y-size). The values for a,b,c and d,e,f need to be
- This exercises a piece, moving it, rotating it, and then
randomly applying those transformations.
This class is abstract, and its subclasses must provide a name for
- This is the simplest tetris piece imaginable---just a single block.
This is provided as an example for you.
What to turn in:
- Design (due Monday)
Collaborate as much as you like on the conceptual and design aspects
of labs. You can work together to solve the equations, too. But
the write-up you turn in is to be your own work. For
more information, consult the course's
- Complete a design cover sheet.
- Draw the blocks that comprise the Gamma tetris piece, labelling
each with a letter A, B, C, and D that show the order in which they are
placed. Number the sides within each piece as described in this document.
- Discover another tetris piece (if necessary,
use the game linked at the
top of this document). Name the piece and show how it is constructed
using the technique presented here.
- In class, you are shown the computation for forming the sides of
Block A (for zigzag) given its inducing vector. If the inducing
vector for block A is (100,100)->(100,50),
show the computation
for the sides of block C of zigzag. Above, you see that block
C's inducing vector is A's side 1.
- Analyze the equations for rotating the inducing side and determine
the values of a,b,c and d,e,f that satisfy the equation. You can probably
do this by inspection with some substitution: the equations are not all
- Implementation (due Friday)
- Complete a code cover sheet.
- Provide a
transcript from your self-tests.
- Complete the classes as described above.
TetrisGamma to make
the appropriate shapes.
- Provide a printout of any files you have modified.
- Be prepared to demo in lab.
Last modified 14:00:17 CDT 17 April 1999
by Ron K. Cytron