Anophoo

tetris7

Apr 13th, 2017
102
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.26 KB | None | 0 0
  1. // Board.java
  2. package tetris;
  3.  
  4. import java.util.Arrays;
  5.  
  6. import org.junit.internal.ArrayComparisonFailure;
  7.  
  8. /**
  9. * CS108 Tetris Board. Represents a Tetris board -- essentially a 2-d grid of
  10. * booleans. Supports tetris pieces and row clearing. Has an "undo" feature that
  11. * allows clients to add and remove pieces efficiently. Does not do any drawing
  12. * or have any idea of pixels. Instead, just represents the abstract 2-d board.
  13. */
  14. public class Board {
  15. // Some ivars are stubbed out for you:
  16. private int width;
  17. private int height;
  18. private boolean[][] grid;
  19. private boolean DEBUG = true;
  20. boolean committed;
  21.  
  22. private int[] widths;
  23. private int[] heights;
  24. private int maxHeight;
  25.  
  26. private int[] xWidths;
  27. private int[] xHeights;
  28. private boolean[][] xGrid;
  29. private int xMaxHeight;
  30.  
  31. // Here a few trivial methods are provided:
  32.  
  33. /**
  34. * Creates an empty board of the given width and height measured in blocks.
  35. */
  36. public Board(int width, int height) {
  37. this.width = width;
  38. this.height = height;
  39. grid = new boolean[width][height];
  40. committed = true;
  41.  
  42. widths = new int[height];
  43. heights = new int[width];
  44. maxHeight = 0;
  45.  
  46. xWidths = new int[height];
  47. xHeights = new int[width];
  48. xMaxHeight = 0;
  49. xGrid = new boolean[width][height];
  50. }
  51.  
  52. /**
  53. * Returns the width of the board in blocks.
  54. */
  55. public int getWidth() {
  56. return width;
  57. }
  58.  
  59. /**
  60. * Returns the height of the board in blocks.
  61. */
  62. public int getHeight() {
  63. return height;
  64. }
  65.  
  66. /**
  67. * Returns the max column height present in the board. For an empty board
  68. * this is 0.
  69. */
  70. public int getMaxHeight() {
  71. return maxHeight;
  72. }
  73.  
  74. /**
  75. * Checks the board for internal consistency -- used for debugging.
  76. */
  77. public void sanityCheck() {
  78. if (DEBUG) {
  79. // System.out.println("sanity checked");
  80. checkHeights();
  81. checkWidths();
  82. checkMaxi();
  83. }
  84. }
  85.  
  86. private void checkHeights() {
  87. int[] newHeights = new int[width];
  88. for (int x = 0; x < width; x++) {
  89. for (int y = height - 1; y >= 0; y--) {
  90. if (grid[x][y]) {
  91. newHeights[x] = y + 1;
  92. break;
  93. }
  94. }
  95. }
  96. if (!Arrays.equals(newHeights, heights)) {
  97. throw new RuntimeException("not valid heights");
  98. // System.out.println(toString());
  99. }
  100. }
  101.  
  102. private void checkWidths() {
  103. int[] newWidths = new int[height];
  104.  
  105. for (int y = 0; y < height; y++) {
  106. int curRow = 0;
  107. for (int x = 0; x < width; x++) {
  108. if (grid[x][y]) {
  109. curRow++;
  110. }
  111. }
  112. newWidths[y] = curRow;
  113. }
  114. if (!Arrays.equals(newWidths, widths))
  115. throw new RuntimeException("not valid widths");
  116. }
  117.  
  118. private void checkMaxi() {
  119. int maxi = 0;
  120. for (int x = 0; x < width; x++) {
  121. if (heights[x] > maxi)
  122. maxi = heights[x];
  123. }
  124.  
  125. if (maxi != getMaxHeight()) {
  126. throw new RuntimeException("not valid maxHeight");
  127. }
  128. }
  129.  
  130. /**
  131. * Given a piece and an x, returns the y value where the piece would come to
  132. * rest if it were dropped straight down at that x.
  133. *
  134. * <p>
  135. * Implementation: use the skirt and the col heights to compute this fast --
  136. * O(skirt length).
  137. */
  138. public int dropHeight(Piece piece, int x) {
  139. int result = 0; // y coordinate of (0, 0) of piece
  140. int curHeight = 0;
  141. int curResult = 0;
  142. int[] skirt = new int[piece.getWidth()];
  143. skirt = piece.getSkirt();
  144. for (int i = 0; i < skirt.length; i++) {
  145. curHeight = heights[x + i];
  146. curResult = curHeight - skirt[i];
  147. if (curResult >= result) {
  148. result = curResult;
  149. }
  150. }
  151. return result;
  152. }
  153.  
  154. /**
  155. * Returns the height of the given column -- i.e. the y value of the highest
  156. * block + 1. The height is 0 if the column contains no blocks.
  157. */
  158. public int getColumnHeight(int x) {
  159. return heights[x];
  160. }
  161.  
  162. /**
  163. * Returns the number of filled blocks in the given row.
  164. */
  165. public int getRowWidth(int y) {
  166. return widths[y];
  167. }
  168.  
  169. /**
  170. * Returns true if the given block is filled in the board. Blocks outside of
  171. * the valid width/height area always return true.
  172. */
  173. public boolean getGrid(int x, int y) {
  174. // check their bounds
  175. if (x >= 0 && x < getWidth() && y >= 0 && y < getHeight()) {
  176. if (grid[x][y])
  177. return true;
  178. else
  179. return false;
  180. } else {
  181. return true;
  182. }
  183. }
  184.  
  185. public static final int PLACE_OK = 0;
  186. public static final int PLACE_ROW_FILLED = 1;
  187. public static final int PLACE_OUT_BOUNDS = 2;
  188. public static final int PLACE_BAD = 3;
  189.  
  190. /**
  191. * Attempts to add the body of a piece to the board. Copies the piece blocks
  192. * into the board grid. Returns PLACE_OK for a regular placement, or
  193. * PLACE_ROW_FILLED for a regular placement that causes at least one row to
  194. * be filled.
  195. *
  196. * <p>
  197. * Error cases: A placement may fail in two ways. First, if part of the
  198. * piece may falls out of bounds of the board, PLACE_OUT_BOUNDS is returned.
  199. * Or the placement may collide with existing blocks in the grid in which
  200. * case PLACE_BAD is returned. In both error cases, the board may be left in
  201. * an invalid state. The client can use undo(), to recover the valid,
  202. * pre-place state.
  203. */
  204. public int place(Piece piece, int x, int y) {
  205. // flag !committed problem
  206. if (!committed)
  207. throw new RuntimeException("place commit problem");
  208. committed = false;
  209. backup();
  210. int result = PLACE_OK;
  211.  
  212. TPoint[] body = new TPoint[piece.getBody().length];
  213. body = piece.getBody();
  214. int curX, curY;
  215. for (TPoint p : body) {
  216. curX = p.x + x;
  217. curY = p.y + y;
  218. if (curX < 0 || curX >= width || curY < 0 || curY >= height) {
  219. result = PLACE_OUT_BOUNDS;
  220. break;
  221. } else if (grid[curX][curY]) {
  222. result = PLACE_BAD;
  223. break;
  224. } else {
  225. // update grid
  226. grid[curX][curY] = true;
  227.  
  228. // update widths[]
  229. widths[curY]++;
  230.  
  231. // update heights[]
  232. if (curY + 1 > heights[curX]) {
  233. heights[curX] = curY + 1;
  234. }
  235.  
  236. // update maxHeight
  237. if (curY + 1 > maxHeight) {
  238. maxHeight = curY + 1;
  239. }
  240.  
  241. // check whether row is filled or not
  242. if (widths[curY] == getWidth()) {
  243. // row is filled
  244. result = PLACE_ROW_FILLED;
  245. }
  246. }
  247. }
  248. sanityCheck();
  249. return result;
  250. }
  251.  
  252. /**
  253. * Deletes rows that are filled all the way across, moving things above
  254. * down. Returns the number of rows cleared.
  255. */
  256. public int clearRows() {
  257. if (committed)
  258. backup();
  259. committed = false;
  260.  
  261. int rowsCleared = 0;
  262.  
  263. // rows not to copy == true
  264. boolean[] notPickedRows = new boolean[height]; // მინიმუმ 1 უნდა იყოს
  265. // სიგანე
  266.  
  267. for (int y = 0; y < height; y++) {
  268. if (widths[y] == width) {
  269. notPickedRows[y] = true;
  270. rowsCleared++;
  271. widths[y] = 0;
  272. }
  273. }
  274.  
  275. boolean[][] newGrid = new boolean[width][height];
  276. int to = 0;
  277. for (int from = 0; from < height; from++) {
  278. if (!notPickedRows[from]) {
  279. for (int x = 0; x < width; x++) { // სტრიქონს გადაყვება
  280. newGrid[x][to] = grid[x][from];
  281. // update widths[]
  282. widths[to] = widths[from];
  283. }
  284. to++;
  285. }
  286. }
  287.  
  288. for (int i = 0; i < getWidth(); i++) {
  289. for (int j = 0; j < getHeight(); j++) {
  290. grid[i][j] = newGrid[i][j];
  291. }
  292. }
  293. // update maxHeight
  294. maxHeight -= rowsCleared;
  295.  
  296. // update heights[]
  297. for (int x = 0; x < width; x++) { // სტრიქონს გადაყვება
  298. heights[x] -= rowsCleared;
  299. }
  300. sanityCheck();
  301. return rowsCleared;
  302. }
  303.  
  304. /**
  305. * Reverts the board to its state before up to one place and one
  306. * clearRows(); If the conditions for undo() are not met, such as calling
  307. * undo() twice in a row, then the second undo() does nothing. See the
  308. * overview docs.
  309. */
  310. public void undo() {
  311. if (!committed) {
  312. System.arraycopy(xWidths, 0, widths, 0, height);
  313. System.arraycopy(xHeights, 0, heights, 0, width);
  314.  
  315. maxHeight = xMaxHeight;
  316. for (int i = 0; i < getWidth(); i++) {
  317. for (int j = 0; j < getHeight(); j++) {
  318. grid[i][j] = xGrid[i][j];
  319. }
  320. }
  321. committed = true;
  322. }
  323. sanityCheck();
  324. }
  325.  
  326. private void backup() {
  327. System.arraycopy(widths, 0, xWidths, 0, getHeight());
  328. System.arraycopy(heights, 0, xHeights, 0, getWidth());
  329. xMaxHeight = maxHeight;
  330. for (int i = 0; i < getWidth(); i++) {
  331. for (int j = 0; j < getHeight(); j++) {
  332. xGrid[i][j] = grid[i][j];
  333. }
  334. }
  335. }
  336.  
  337. /**
  338. * Puts the board in the committed state.
  339. */
  340. public void commit() {
  341. committed = true;
  342. }
  343.  
  344. /*
  345. * Renders the board state as a big String, suitable for printing. This is
  346. * the sort of print-obj-state utility that can help see complex state
  347. * change over time. (provided debugging utility)
  348. */
  349. public String toString() {
  350. StringBuilder buff = new StringBuilder();
  351. for (int y = height - 1; y >= 0; y--) {
  352. buff.append('|');
  353. for (int x = 0; x < width; x++) {
  354. if (getGrid(x, y))
  355. buff.append('+');
  356. else
  357. buff.append(' ');
  358. }
  359. buff.append("|\n");
  360. }
  361. for (int x = 0; x < width + 2; x++)
  362. buff.append('-');
  363. return (buff.toString());
  364. }
  365.  
  366. public static void main(String[] args) {
  367. Board b = new Board(3, 6);
  368. Piece pyr1 = new Piece(Piece.PYRAMID_STR);
  369. Piece pyr2 = pyr1.computeNextRotation();
  370. b.place(pyr1, 0, 0);
  371. b.commit();
  372. b.place(pyr2, 0, 1);
  373. b.clearRows();
  374. System.out.println(b.toString());
  375. }
  376. }
Advertisement
Add Comment
Please, Sign In to add comment