Skip to content

Commit

Permalink
finish 2048
Browse files Browse the repository at this point in the history
  • Loading branch information
wang-jiahao committed Dec 4, 2024
1 parent 777818d commit 758257f
Showing 1 changed file with 148 additions and 41 deletions.
189 changes: 148 additions & 41 deletions proj0/game2048/Model.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,38 +4,54 @@
import java.util.Observable;


/** The state of a game of 2048.
* @author TODO: YOUR NAME HERE
/**
* The state of a game of 2048.
*
* @author TODO: YOUR NAME HERE
*/
public class Model extends Observable {
/** Current contents of the board. */
/**
* Current contents of the board.
*/
private Board board;
/** Current score. */
/**
* Current score.
*/
private int score;
/** Maximum score so far. Updated when game ends. */
/**
* Maximum score so far. Updated when game ends.
*/
private int maxScore;
/** True iff game is ended. */
/**
* True iff game is ended.
*/
private boolean gameOver;

/* Coordinate System: column C, row R of the board (where row 0,
* column 0 is the lower-left corner of the board) will correspond
* to board.tile(c, r). Be careful! It works like (x, y) coordinates.
*/

/** Largest piece value. */
/**
* Largest piece value.
*/
public static final int MAX_PIECE = 2048;

/** A new 2048 game on a board of size SIZE with no pieces
* and score 0. */
/**
* A new 2048 game on a board of size SIZE with no pieces
* and score 0.
*/
public Model(int size) {
board = new Board(size);
score = maxScore = 0;
gameOver = false;
}

/** A new 2048 game where RAWVALUES contain the values of the tiles
/**
* A new 2048 game where RAWVALUES contain the values of the tiles
* (0 if null). VALUES is indexed by (row, col) with (0, 0) corresponding
* to the bottom-left corner. Used for testing purposes. */
* to the bottom-left corner. Used for testing purposes.
*/
public Model(int[][] rawValues, int score, int maxScore, boolean gameOver) {
int size = rawValues.length;
board = new Board(rawValues, score);
Expand All @@ -44,22 +60,27 @@ public Model(int[][] rawValues, int score, int maxScore, boolean gameOver) {
this.gameOver = gameOver;
}

/** Return the current Tile at (COL, ROW), where 0 <= ROW < size(),
* 0 <= COL < size(). Returns null if there is no tile there.
* Used for testing. Should be deprecated and removed.
* */
/**
* Return the current Tile at (COL, ROW), where 0 <= ROW < size(),
* 0 <= COL < size(). Returns null if there is no tile there.
* Used for testing. Should be deprecated and removed.
*/
public Tile tile(int col, int row) {
return board.tile(col, row);
}

/** Return the number of squares on one side of the board.
* Used for testing. Should be deprecated and removed. */
/**
* Return the number of squares on one side of the board.
* Used for testing. Should be deprecated and removed.
*/
public int size() {
return board.size();
}

/** Return true iff the game is over (there are no moves, or
* there is a tile with value 2048 on the board). */
/**
* Return true iff the game is over (there are no moves, or
* there is a tile with value 2048 on the board).
*/
public boolean gameOver() {
checkGameOver();
if (gameOver) {
Expand All @@ -68,49 +89,94 @@ public boolean gameOver() {
return gameOver;
}

/** Return the current score. */
/**
* Return the current score.
*/
public int score() {
return score;
}

/** Return the current maximum game score (updated at end of game). */
/**
* Return the current maximum game score (updated at end of game).
*/
public int maxScore() {
return maxScore;
}

/** Clear the board to empty and reset the score. */
/**
* Clear the board to empty and reset the score.
*/
public void clear() {
score = 0;
gameOver = false;
board.clear();
setChanged();
}

/** Add TILE to the board. There must be no Tile currently at the
* same position. */
/**
* Add TILE to the board. There must be no Tile currently at the
* same position.
*/
public void addTile(Tile tile) {
board.addTile(tile);
checkGameOver();
setChanged();
}

/** Tilt the board toward SIDE. Return true iff this changes the board.
*
/**
* Tilt the board toward SIDE. Return true iff this changes the board.
* <p>
* 1. If two Tile objects are adjacent in the direction of motion and have
* the same value, they are merged into one Tile of twice the original
* value and that new value is added to the score instance variable
* the same value, they are merged into one Tile of twice the original
* value and that new value is added to the score instance variable
* 2. A tile that is the result of a merge will not merge again on that
* tilt. So each move, every tile will only ever be part of at most one
* merge (perhaps zero).
* tilt. So each move, every tile will only ever be part of at most one
* merge (perhaps zero).
* 3. When three adjacent tiles in the direction of motion have the same
* value, then the leading two tiles in the direction of motion merge,
* and the trailing tile does not.
* */
* value, then the leading two tiles in the direction of motion merge,
* and the trailing tile does not.
*/
public boolean tilt(Side side) {
boolean changed;
changed = false;

// TODO: Modify this.board (and perhaps this.score) to account
board.setViewingPerspective(side);
int[][] is_merged = new int[board.size()][board.size()];
for (int i = 0; i < board.size(); i++) {
for (int j = 0; j < board.size(); j++) {
is_merged[i][j] = 0;
}
}
for (int c = 0; c < board.size(); c++) {
for (int r = board.size() - 2; r >= 0; r--) {
Tile t = board.tile(c, r);
if (t != null) {
for (int row = r + 1; row < board.size(); row++) {
Tile t2 = board.tile(c, row);
if (t2 == null) {
if (row == board.size() - 1) {
board.move(c, row, t);
changed = true;
}
continue;
}
if (t2.value() != t.value() || is_merged[c][row] == 1) {
if (r != row - 1) {
board.move(c, row - 1, t);
changed = true;
}
break;
}
int value = t.value();
board.move(c, row, t);
is_merged[c][row] = 1;
changed = true;
score += 2 * value;
}
}
}
}
board.setViewingPerspective(Side.NORTH);
// for the tilt to the Side SIDE. If the board changed, set the
// changed local variable to true.

Expand All @@ -121,23 +187,34 @@ public boolean tilt(Side side) {
return changed;
}

/** Checks if the game is over and sets the gameOver variable
* appropriately.
/**
* Checks if the game is over and sets the gameOver variable
* appropriately.
*/
private void checkGameOver() {
gameOver = checkGameOver(board);
}

/** Determine whether game is over. */
/**
* Determine whether game is over.
*/
private static boolean checkGameOver(Board b) {
return maxTileExists(b) || !atLeastOneMoveExists(b);
}

/** Returns true if at least one space on the Board is empty.
* Empty spaces are stored as null.
* */
/**
* Returns true if at least one space on the Board is empty.
* Empty spaces are stored as null.
*/
public static boolean emptySpaceExists(Board b) {
// TODO: Fill in this function.
for (int i = 0; i < b.size(); i++) {
for (int j = 0; j < b.size(); j++) {
if (b.tile(i, j) == null) {
return true;
}
}
}
return false;
}

Expand All @@ -148,6 +225,13 @@ public static boolean emptySpaceExists(Board b) {
*/
public static boolean maxTileExists(Board b) {
// TODO: Fill in this function.
for (int i = 0; i < b.size(); i++) {
for (int j = 0; j < b.size(); j++) {
if (b.tile(i, j) != null && b.tile(i, j).value() == MAX_PIECE) {
return true;
}
}
}
return false;
}

Expand All @@ -159,12 +243,35 @@ public static boolean maxTileExists(Board b) {
*/
public static boolean atLeastOneMoveExists(Board b) {
// TODO: Fill in this function.
if (emptySpaceExists(b)) {
return true;
}
for (int i = 0; i < b.size(); i++) {
for (int j = 0; j < b.size(); j++) {
if (i == b.size() - 1 && j == b.size() - 1) {
continue;
}
if (j == b.size() - 1) {
if (b.tile(i, j).value() == b.tile(i + 1, j).value()) {
return true;
}
} else if (i == b.size() - 1) {
if (b.tile(i, j).value() == b.tile(i, j + 1).value()) {
return true;
}
} else {
if (b.tile(i, j).value() == b.tile(i + 1, j).value() || b.tile(i, j).value() == b.tile(i, j + 1).value()) {
return true;
}
}
}
}
return false;
}


@Override
/** Returns the model as a string, used for debugging. */
/** Returns the model as a string, used for debugging. */
public String toString() {
Formatter out = new Formatter();
out.format("%n[%n");
Expand Down

0 comments on commit 758257f

Please sign in to comment.