Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Board.java
- package tetris;
- import java.util.Arrays;
- import org.junit.internal.ArrayComparisonFailure;
- /**
- * 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 DEBUG = true;
- boolean committed;
- private int[] widths;
- private int[] heights;
- private int maxHeight;
- private int[] xWidths;
- private int[] xHeights;
- private boolean[][] xGrid;
- private int xMaxHeight;
- // 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;
- widths = new int[height];
- heights = new int[width];
- maxHeight = 0;
- xWidths = new int[height];
- xHeights = new int[width];
- xMaxHeight = 0;
- xGrid = new boolean[width][height];
- }
- /**
- * 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) {
- // System.out.println("sanity checked");
- checkHeights();
- checkWidths();
- checkMaxi();
- }
- }
- private void checkHeights() {
- int[] newHeights = new int[width];
- for (int x = 0; x < width; x++) {
- for (int y = height - 1; y >= 0; y--) {
- if (grid[x][y]) {
- newHeights[x] = y + 1;
- break;
- }
- }
- }
- if (!Arrays.equals(newHeights, heights)) {
- throw new RuntimeException("not valid heights");
- // System.out.println(toString());
- }
- }
- private void checkWidths() {
- int[] newWidths = new int[height];
- for (int y = 0; y < height; y++) {
- int curRow = 0;
- for (int x = 0; x < width; x++) {
- if (grid[x][y]) {
- curRow++;
- }
- }
- newWidths[y] = curRow;
- }
- if (!Arrays.equals(newWidths, widths))
- throw new RuntimeException("not valid widths");
- }
- private void checkMaxi() {
- int maxi = 0;
- for (int x = 0; x < width; x++) {
- if (heights[x] > maxi)
- maxi = heights[x];
- }
- if (maxi != getMaxHeight()) {
- throw new RuntimeException("not valid 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 result = 0; // y coordinate of (0, 0) of piece
- int curHeight = 0;
- int curResult = 0;
- int[] skirt = new int[piece.getWidth()];
- skirt = piece.getSkirt();
- for (int i = 0; i < skirt.length; i++) {
- curHeight = heights[x + i];
- curResult = curHeight - skirt[i];
- if (curResult >= result) {
- result = curResult;
- }
- }
- 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 heights[x];
- }
- /**
- * Returns the number of filled blocks in the given row.
- */
- public int getRowWidth(int y) {
- return widths[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) {
- // check their bounds
- if (x >= 0 && x < getWidth() && y >= 0 && y < getHeight()) {
- if (grid[x][y])
- return true;
- else
- return false;
- } else {
- return true;
- }
- }
- 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;
- backup();
- int result = PLACE_OK;
- TPoint[] body = new TPoint[piece.getBody().length];
- body = piece.getBody();
- int curX, curY;
- for (TPoint p : body) {
- curX = p.x + x;
- curY = p.y + y;
- if (curX < 0 || curX >= width || curY < 0 || curY >= height) {
- result = PLACE_OUT_BOUNDS;
- break;
- } else if (grid[curX][curY]) {
- result = PLACE_BAD;
- break;
- } else {
- // update grid
- grid[curX][curY] = true;
- // update widths[]
- widths[curY]++;
- // update heights[]
- if (curY + 1 > heights[curX]) {
- heights[curX] = curY + 1;
- }
- // update maxHeight
- if (curY + 1 > maxHeight) {
- maxHeight = curY + 1;
- }
- // check whether row is filled or not
- if (widths[curY] == getWidth()) {
- // row is filled
- result = PLACE_ROW_FILLED;
- }
- }
- }
- sanityCheck();
- return result;
- }
- /**
- * Deletes rows that are filled all the way across, moving things above
- * down. Returns the number of rows cleared.
- */
- public int clearRows() {
- if (committed)
- backup();
- committed = false;
- int rowsCleared = 0;
- // rows not to copy == true
- boolean[] notPickedRows = new boolean[height]; // მინიმუმ 1 უნდა იყოს
- // სიგანე
- for (int y = 0; y < height; y++) {
- if (widths[y] == width) {
- notPickedRows[y] = true;
- rowsCleared++;
- widths[y] = 0;
- }
- }
- boolean[][] newGrid = new boolean[width][height];
- int to = 0;
- for (int from = 0; from < height; from++) {
- if (!notPickedRows[from]) {
- for (int x = 0; x < width; x++) { // სტრიქონს გადაყვება
- newGrid[x][to] = grid[x][from];
- // update widths[]
- widths[to] = widths[from];
- }
- to++;
- }
- }
- for (int i = 0; i < getWidth(); i++) {
- for (int j = 0; j < getHeight(); j++) {
- grid[i][j] = newGrid[i][j];
- }
- }
- // update maxHeight
- maxHeight -= rowsCleared;
- // update heights[]
- for (int x = 0; x < width; x++) { // სტრიქონს გადაყვება
- heights[x] -= rowsCleared;
- }
- 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() {
- if (!committed) {
- System.arraycopy(xWidths, 0, widths, 0, height);
- System.arraycopy(xHeights, 0, heights, 0, width);
- maxHeight = xMaxHeight;
- for (int i = 0; i < getWidth(); i++) {
- for (int j = 0; j < getHeight(); j++) {
- grid[i][j] = xGrid[i][j];
- }
- }
- committed = true;
- }
- sanityCheck();
- }
- private void backup() {
- System.arraycopy(widths, 0, xWidths, 0, getHeight());
- System.arraycopy(heights, 0, xHeights, 0, getWidth());
- xMaxHeight = maxHeight;
- for (int i = 0; i < getWidth(); i++) {
- for (int j = 0; j < getHeight(); j++) {
- xGrid[i][j] = grid[i][j];
- }
- }
- }
- /**
- * Puts the board in the committed state.
- */
- public void commit() {
- committed = true;
- }
- /*
- * 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());
- }
- public static void main(String[] args) {
- Board b = new Board(3, 6);
- Piece pyr1 = new Piece(Piece.PYRAMID_STR);
- Piece pyr2 = pyr1.computeNextRotation();
- b.place(pyr1, 0, 0);
- b.commit();
- b.place(pyr2, 0, 1);
- b.clearRows();
- System.out.println(b.toString());
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment