Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Board.java
- package tetris;
- /**
- * 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[][] saveGrid;
- private boolean DEBUG = true;
- boolean committed;
- private int[] w;
- private int[] h;
- protected int maxHeight;
- // 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;
- grid = new boolean[width][height];
- committed = true;
- w = new int[height];
- h = new int[width];
- for (int i = 0; i < w.length; i++)
- w[i] = 0;
- for (int i = 0; i < h.length; i++)
- h[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.
- */
- public int getMaxHeight() {
- for (int i = 0; i < h.length; i++)
- if (h[i] > maxHeight)
- maxHeight = h[i];
- return maxHeight;
- }
- /**
- * Checks the board for internal consistency -- used for debugging.
- */
- public void sanityCheck() {
- if (DEBUG) {
- int[] theights = new int[width];
- for (int r = 0; r < height; r++)
- for (int c = 0; c < width; c++)
- if (getGrid(c, r))
- theights[c] = r + 1;
- for (int i = 0; i < theights.length; i++)
- if (theights[i] != h[i])
- throw new RuntimeException(
- "row heights is not correct. expected "
- + theights[i] + " but was " + h[i]
- + " for " + i + "th height.");
- int[] twidths = new int[height];
- for (int c = 0; c < width; c++)
- for (int r = 0; r < height; r++)
- if (getGrid(c, r))
- twidths[r]++;
- for (int i = 0; i < twidths.length; i++)
- if (twidths[i] != w[i])
- throw new RuntimeException(
- "widths is not correct. expected " + twidths[i]
- + " but was " + w[i] + " for " + i
- + "th width.");
- /*
- * int tMaxheight = 0; for (int height : h) tMaxheight =
- * Math.max(tMaxheight, height); if (tMaxheight != maxHeight) throw
- * new RuntimeException( "max height is not correct. expected " +
- * tMaxheight + " and was " + 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 res = 0;
- for (int i = 0; i < skirt.length; i++) {
- int hits = 0;
- if (h[x + i] - skirt[i] > 0)
- hits = h[x + i] - skirt[i];
- if (hits > res)
- res = hits;
- }
- return res;
- }
- /**
- * 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 h[x];
- }
- /**
- * Returns the number of filled blocks in the given row.
- */
- public int getRowWidth(int y) {
- return w[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 >= getWidth() || y >= getHeight() || 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.
- *
- * <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");
- int res = 0;
- for (int i = 0; i < piece.getBody().length; i++) {
- if (piece.getBody()[i].x + x >= getWidth()
- || piece.getBody()[i].y + y >= getHeight())
- res = PLACE_OUT_BOUNDS;
- if (getGrid(piece.getBody()[i].x + x, piece.getBody()[i].y + y)) {
- if (res != PLACE_OUT_BOUNDS)
- res = PLACE_BAD;
- }
- if (!getGrid(piece.getBody()[i].x + x, piece.getBody()[i].y + y)) {
- grid[piece.getBody()[i].x + x][piece.getBody()[i].y + y] = true;
- w[piece.getBody()[i].y + y]++;
- if (piece.getBody()[i].y + y + 1 > h[piece.getBody()[i].x + x])
- h[piece.getBody()[i].x + x] = piece.getBody()[i].y + y + 1;
- }
- }
- for (int i = 0; i < w.length; i++) {
- if (w[i] == height)
- res = PLACE_ROW_FILLED;
- }
- if (res == 0)
- res = PLACE_OK;
- committed = false;
- return res;
- }
- /**
- * Deletes rows that are filled all the way across, moving things above
- * down. Returns the number of rows cleared.
- */
- public int clearRows() {
- System.out.println(this);
- int rowsCleared = 0;
- for (int i = 0; i < grid.length; i++) {
- int rowcnt = 0;
- for (int j = 0; j < grid[0].length; j++) {
- if (grid[i][j] == true)
- rowcnt++;
- }
- if (rowcnt == grid[0].length) {
- rowsCleared++;
- for (int s = 0; s < grid[0].length; s++) {
- grid[i][s] = false;
- }
- for (int n = i; n < grid.length-1; n++) {
- for (int m = 0; m < grid[0].length; m++) {
- boolean temp;
- temp = grid[n][m];
- grid[n][m] = grid[n+1][m ];
- grid[n+1][m] = temp;
- }
- }
- for (int k = i; k <w.length - 1; k++) {
- w[k] = w[k + 1];
- }
- w[w.length - 1] = 0;
- i--;
- }
- }
- for (int j = 0; j <h.length; j++) {
- h[j] = h[j] - rowsCleared ;
- }
- System.out.println(rowsCleared);
- committed = false;
- System.out.println(this);
- sanityCheck();
- return rowsCleared;
- }
- /**
- * 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() {
- committed = true;
- for (int i = 0; i < saveGrid.length; i++) {
- for (int j = 0; j < saveGrid[0].length; j++) {
- grid[i][j] = saveGrid[i][j];
- }
- }
- }
- /**
- * Puts the board in the committed state.
- */
- public void commit() {
- committed = true;
- saveGrid = new boolean[width][height];
- for (int i = 0; i < grid.length; i++) {
- for (int j = 0; j < grid[0].length; j++) {
- saveGrid[i][j] = grid[i][j];
- }
- }
- }
- /*
- * 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