// JBoardTest.java import java.awt.*; import javax.swing.*; import java.util.*; import java.awt.event.*; import javax.swing.event.*; /** JBoardTest is a unit test application for tetris -- its sole purpose is exercising the tetris classes. Its interface only make sense if you think of it as a direct connection to the Board and Piece interfaces. JBoardTest is provided in finished form so the students can use it to test their Piece and Board code.
Use the buttons on screen or the keys 4, 5, 6, 7, 0 for control. Add a piece, move it around. JBoardTest uses place() and undo() to move the piece around the board. Use the app to set up and test out specific cases for your tetris board and piece.
Transparency --
Board has all sorts of hidden state --
heights, widths etc.. The hidden state
is what makes Board hard to debug.
The unit test tries to make the state of the Board
transparent, so you can see what's going on as you exercise
your code.
*/
class JBoardTest extends JComponent {
// Board data structures
private Board board;
private Piece[] pieces;
private JLabel label;
// The currently played piece
// null if there is no current piece
private Piece piece;
private int pieceX;
private int pieceY;
public JBoardTest(int width, int height) {
super();
setPreferredSize(new Dimension(width, height));
pieces = Piece.getPieces();
reset();
}
private void reset() {
board = new Board(6, 10);
piece = null;
}
/**
Whenever the user clicks a button, this runs
to make the change. The strategy is:
compute what the new piece position should be,
undo to remove the old piece position,
put in the new piece position.
*/
public final int ADD = 1;
public final int ADDRANDOM = 2;
public final int LEFT = 3;
public final int RIGHT = 4;
public final int ROTATE = 5;
public final int DOWN = 6;
public final int DROP = 7;
public final int CLEAR = 8;
public final int RESET = 9;
public final int UNDO = 10;
public void action(int verb) {
if (verb==RESET) {
reset();
}
else if (verb==UNDO) {
board.undo();
}
else if (verb==CLEAR) {
if (board.clearRows()) {
board.commit(); // finalize the last position
piece = null;
}
}
else {
// compute a new piece based on the old piece and the verb
Piece newPiece = piece;
int newX = pieceX;
int newY = pieceY;
switch (verb) {
case ADD:
case ADDRANDOM:
// finalize the last position
board.commit();
piece = null;
if (verb==ADD) newPiece = pieces[6];
else newPiece = pieces[(int)(Math.random()*pieces.length)];
newX = 0;
newY = board.getHeight() - newPiece.getHeight() -1;
break;
case LEFT: newX--; break;
case RIGHT: newX++; break;
case ROTATE:
if (piece!=null) newPiece = piece.nextRotation();
break;
case DOWN: newY--; break;
case DROP:
// remove the piece before the drop computation so
// it doesn't hit itself on the way down!
if (piece!=null) {
board.undo();
newY = board.dropHeight(newPiece, newX);
}
break;
default:
throw new RuntimeException("Bad verb");
}
// now we have a newPiece
if (newPiece!=null) {
board.undo(); // remove the old state
// Try putting in the new piece
int result = board.place(newPiece, newX, newY);
// See if it worked
if (result <= Board.PLACE_ROW_FILLED) {
piece = newPiece;
pieceX = newX;
pieceY = newY;
}
else {
//System.out.println("bad placement:" + result);
label.setText("bad:" + result);
// put it back the way it was
board.undo();
if (piece!=null) {
board.place(piece, pieceX, pieceY);
}
}
}
}
// Redraw the whole board since we've changed it
repaint();
}
/**
Pixel helpers -- these centralize how
we map from block coords (x,y) to pixel
co-ords on screen. By centralizing here,
at least it's all consistent.
These return the distance in pixels
from the left or botton edge
to the upper left corner of the rect
for each tetris block.
*/
private int xPixelDist(int x, float dx) {
return(MARGIN + Math.round(x*dx));
}
private int yPixelDist(int y, float dy) {
return(Math.round((y+1)*dy));
}
// pixel space on the left and bottom
public final int MARGIN = 20;
public void paintComponent(Graphics g) {
// area where tetris blocks are drawn
int pixelWidth = getWidth()-MARGIN;
int pixelHeight = getHeight()-MARGIN;
// block size of the board
int bWidth = board.getWidth();
int bHeight = board.getHeight();
int bMaxHeight = board.getMaxHeight();
// pixels across of each block
float dx = ((float)pixelWidth)/bWidth;
float dy = ((float)pixelHeight)/bHeight;
g.drawRect(MARGIN, 0, pixelWidth-1, pixelHeight-1);
int x, y;
// draw the board blocks and the bits of text...
for (y=0; y