Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Board.java
- package tetris;
- import java.util.Arrays;
- import javax.management.RuntimeErrorException;
- /**
- CS108 Tetris Board.
- Represents a Tetris board -- essentially a 2-d grid
- of booleans. Supports tetris pieces and row clearing.
- Has an "undo" feature that allows clients to add and remove pieces efficiently.
- Does not do any drawing or have any idea of pixels. Instead,
- just represents the abstract 2-d board.
- */
- public class Board {
- // Some ivars are stubbed out for you:
- private int width;
- private int height;
- private boolean[][] grid;
- private boolean[][] gridBack;
- private boolean DEBUG = true;
- boolean committed;
- private int[] filled;
- private int[] filledBack;
- private int[] colHeight;
- private int[] colHeightBack;
- private int maxHeight;
- private int maxHeightBack;
- // Here a few trivial methods are provided:
- /**
- Creates an empty board of the given width and height
- measured in blocks.
- */
- public Board(int width, int height) {
- this.width = width;
- this.height = height;
- maxHeight = 0;
- maxHeightBack = 0;
- grid = new boolean[width][height];
- gridBack = new boolean[width][height];
- committed = true;
- filled = new int[height];
- filledBack = new int[height];
- colHeight = new int[width];
- colHeightBack = new int[width];
- }
- /**
- 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.
- */
- public int getMaxHeight() {
- return maxHeight;
- }
- /**
- Checks the board for internal consistency -- used
- for debugging.
- */
- public void sanityCheck() {
- if (DEBUG) {
- for(int i=0; i<height; i++) {
- int filledNum = 0;
- for(int j=0; j<width; j++) {
- if(grid[j][i]) filledNum++;
- }
- if(filledNum!=filled[i]) throw new RuntimeException("Incorrect fill on row "+i);
- }
- int maxColHeight = 0;
- for(int i=0; i<width; i++) {
- for(int j=height-1; j>=0; j--) {
- if(grid[i][j]) {
- if(colHeight[i]!=j+1) throw new RuntimeException("Incorrect height on column "+i);
- if(j+1>maxColHeight) maxColHeight = j+1;
- break;
- }
- }
- }
- if(maxColHeight != maxHeight) throw new RuntimeException("Incorrect maxHeight");
- }
- }
- /**
- Given a piece and an x, returns the y
- value where the piece would come to rest
- if it were dropped straight down at that x.
- <p>
- Implementation: use the skirt and the col heights
- to compute this fast -- O(skirt length).
- */
- public int dropHeight(Piece piece, int x) {
- int[] skirt = piece.getSkirt();
- int result = colHeight[x] - skirt[0];
- for(int i=1; i<skirt.length; i++) {
- if(colHeight[x+i]-skirt[i]>result) result = colHeight[x+i]-skirt[i];
- }
- return result;
- }
- /**
- Returns the height of the given column --
- i.e. the y value of the highest block + 1.
- The height is 0 if the column contains no blocks.
- */
- public int getColumnHeight(int x) {
- return colHeight[x]; // YOUR CODE HERE
- }
- /**
- Returns the number of filled blocks in
- the given row.
- */
- public int getRowWidth(int y) {
- return filled[y];
- }
- /**
- Returns true if the given block is filled in the board.
- Blocks outside of the valid width/height area
- always return true.
- */
- public boolean getGrid(int x, int y) {
- if(x<0 || x>=width || y<0 || y>=height) return true;
- return grid[x][y];
- }
- 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.
- <p>Error cases:
- A placement may fail in two ways. First, if part of the piece may falls out
- of bounds of the board, PLACE_OUT_BOUNDS is returned.
- Or the placement may collide with existing blocks in the grid
- in which case PLACE_BAD is returned.
- In both error cases, the board may be left in an invalid
- state. The client can use undo(), to recover the valid, pre-place state.
- */
- public int place(Piece piece, int x, int y) {
- // flag !committed problem
- if (!committed) throw new RuntimeException("place commit problem");
- committed = false;
- int result = PLACE_OK;
- TPoint[] points = piece.getBody();
- for(int i=0; i<points.length; i++) {
- if(x+points[i].x<0 || x+points[i].x>=width || y+points[i].y<0 || y+points[i].y>=height) {
- return PLACE_OUT_BOUNDS;
- }
- if(grid[x+points[i].x][y+points[i].y]) return PLACE_BAD;
- grid[x+points[i].x][y+points[i].y] = true;
- filled[y+points[i].y] ++;
- if(colHeight[x+points[i].x] <= y+points[i].y) {
- colHeight[x+points[i].x] = y+points[i].y+1;
- }
- }
- for(int i=0; i<piece.getWidth(); i++) {
- if(colHeight[x+i]>maxHeight) maxHeight = colHeight[x+i];
- }
- for(int i=0; i<piece.getHeight(); i++) {
- if(filled[y+i]==width) return PLACE_ROW_FILLED;
- }
- return result;
- }
- /**
- Deletes rows that are filled all the way across, moving
- things above down. Returns the number of rows cleared.
- */
- public int clearRows() {
- committed = false;
- int rowsCleared = 0;
- int down = 0;
- for(int i=0; i<maxHeight; i++) {
- if(filled[i]!=width) {
- if(down!=i) {
- for(int j=0; j<width; j++) {
- grid[j][down] = grid[j][i];
- }
- filled[down] = filled[i];
- }
- down++;
- }else {
- rowsCleared++;
- }
- }
- for(int i=maxHeight-rowsCleared; i<maxHeight; i++) {
- for(int j=0; j<width; j++) {
- grid[j][i] = false;
- }
- filled[i] = 0;
- }
- computeColumnHeights();
- sanityCheck();
- return rowsCleared;
- }
- private void computeColumnHeights() {
- maxHeight = 0;
- for(int i=0; i<width; i++) {
- colHeight[i] = 0;
- for(int j=height-1; j>=0; j--) {
- if(grid[i][j]) {
- colHeight[i] = j+1;
- if(j+1>maxHeight) maxHeight = j+1;
- break;
- }
- }
- }
- }
- /**
- Reverts the board to its state before up to one place
- and one clearRows();
- If the conditions for undo() are not met, such as
- calling undo() twice in a row, then the second undo() does nothing.
- See the overview docs.
- */
- public void undo() {
- for(int i=0; i<width; i++) {
- System.arraycopy(gridBack[i], 0, grid[i], 0, height);
- }
- System.arraycopy(filledBack, 0, filled, 0, height);
- System.arraycopy(colHeightBack, 0, colHeight, 0, width);
- maxHeight = maxHeightBack;
- committed = true;
- }
- /**
- Puts the board in the committed state.
- */
- public void commit() {
- committed = true;
- for(int i=0; i<width; i++) {
- System.arraycopy(grid[i], 0, gridBack[i], 0, height);
- }
- System.arraycopy(filled, 0, filledBack, 0, height);
- System.arraycopy(colHeight, 0, colHeightBack, 0, width);
- maxHeightBack = maxHeight;
- }
- /*
- Renders the board state as a big String, suitable for printing.
- This is the sort of print-obj-state utility that can help see complex
- state change over time.
- (provided debugging utility)
- */
- public String toString() {
- StringBuilder buff = new StringBuilder();
- for (int y = height-1; y>=0; y--) {
- buff.append('|');
- for (int x=0; x<width; x++) {
- if (getGrid(x,y)) buff.append('+');
- else buff.append(' ');
- }
- buff.append("|\n");
- }
- for (int x=0; x<width+2; x++) buff.append('-');
- return(buff.toString());
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement