// Board.java // @author Jack Morrison // @date 4/28/08 import java.awt.*; import java.util.*; /** Represents a Tetris board -- essentially a 2-d grid of booleans. Supports tetris pieces and row clearning. Has an "undo" feature that allows clients to add and remove pieces efficiently. Does not do any drawing or have any idea of pixels. Intead, just represents the abtsract 2-d board. See Tetris-Architecture.html for an overview. This is the starter file version -- a few simple things are filled in already @author Nick Parlante @version 1.0, Mar 1, 2001 */ public final class Board { private int width; private int height; private boolean[][] grid; private int maxHeight; private int widths[]; private int heights[]; private boolean committed; // backup data structures private boolean[][] bGrid; private int[] bWidths; private int[] bHeights; private int bMaxHeight; private boolean DEBUG = true; private static final int HEIGHT = 2; /** Creates an empty board of the given width and height measured in blocks. This is not quite done, you still need to initialize your backup data structures (and erase this comment!) */ public Board(int aWidth, int aHeight) { width = aWidth; height = aHeight + HEIGHT; grid = new boolean[width][height]; widths = new int[height]; heights = new int[width]; maxHeight = 0; bMaxHeight = 0; committed = true; bGrid = new boolean[width][height]; bWidths = new int[height]; bHeights = new int[width]; for (int i = 0; i < width; i++) { heights[i] = 0; bHeights[i] = 0; for (int j = 0; j < height; j++) { grid[i][j] = false; bGrid[i][j] = false; } } for (int i = 0; i < height; i++) { widths[i] = 0; bWidths[i] = 0; } } /** Returns the width of the board in blocks. */ public int getWidth() { return width; } /** Returns the height of the board in blocks. */ public int getHeight() { return height; } /** Returns the max column height present in the board. For an empty board this is 0. Remember, this should be constant! */ public int getMaxHeight() { return maxHeight; } /** Checks the board for internal consistency -- used for debugging. */ public void sanityCheck() { System.out.println("sanityCheck()"); if (DEBUG) { // consistency check the board state for(int i=0;i Implementation: use the skirt and the col heights to compute this fast -- O(skirt length). */ public int dropHeight(Piece piece, int x) { if(DEBUG){ System.out.println("dropHeight()"); printGrid(grid); } // Initialize variables int[] skirt = piece.getSkirt(); int dropHeight=0; int leastDistance = 0; // Go through the skirt and calculate the correct height // by calculating the piece of the body with the least distance // between it and the height below it. for(int i=0;i=width){return true;} if (y<0 || y>=height){return true;} if (grid[x][y]==true){return true;} return false; } public static final int PLACE_OK = 0; public static final int PLACE_ROW_FILLED = 1; public static final int PLACE_OUT_BOUNDS = 2; public static final int PLACE_BAD = 3; /** Attempts to add the body of a piece to the board. Copies the piece blocks into the board grid. Returns PLACE_OK for a regular placement, or PLACE_ROW_FILLED for a regular placement that causes at least one row to be filled.

Error cases: If part of the piece would fall out of bounds, the placement does not change the board at all, and PLACE_OUT_BOUNDS is returned. If the placement is "bad" --interfering with existing blocks in the grid -- then the placement is halted partially complete and PLACE_BAD is returned. An undo() will remove the bad placement. */ public int place(Piece piece, int x, int y) { if(DEBUG){ System.out.println("place()"); } // You're not allowed to do 2 places in a row. if (committed==false){return PLACE_BAD;} Point[] pieceBody = piece.getBody(); // Uncommitts the board and backs it up committed = false; backupBoard(); // Checks to make sure that no part of the // piece is in a bad place and if it is, then it // returns the correct value. for (int i=0;i=width){return PLACE_OUT_BOUNDS;} if (placeY<0 || placeY>=height){return PLACE_OUT_BOUNDS;} if (grid[placeX][placeY]==true){undo(); return PLACE_BAD;} } // Places the piece at the correct location in the grid for (int i=0;i=0;j--){ if(grid[i][j]==true){ colHeight=j+1; if (colHeight>maxHeight){maxHeight=colHeight;} heights[i]=colHeight; break; } } } sanityCheck(); } /** Deletes rows that are filled all the way across, moving things above down. Returns true if any row clearing happened.

Implementation: This is complicated. Ideally, you want to copy each row down to its correct location in one pass. Note that more than one row may be filled. */ public boolean clearRows() { if(DEBUG){ System.out.println("CLEARING ROWS"); } // Stores all the rows that have been cleared Vector clearedRows = new Vector(); // Goes through each row, starting at the bottom for(int j=0;j