diff --git a/twentyfortyeight/src/twentyfortyeight/Main.java b/twentyfortyeight/src/twentyfortyeight/Main.java index b19cc61..49bdbfc 100644 --- a/twentyfortyeight/src/twentyfortyeight/Main.java +++ b/twentyfortyeight/src/twentyfortyeight/Main.java @@ -11,7 +11,7 @@ import tester.Tester; class Examples { void testRun(Tester t) { - Game game = new Game(); + Game game = new Game(2); game.run(); } } @@ -43,10 +43,11 @@ class Util { // A game of 2048. class Game extends World { - int score; // The current score. - int sz; // The size of the grid. - int width; // The width of the image in pixels. - Board board; // The game board. + int score; // The current score. + int sz; // The size of the grid. + int width; // The width of the image in pixels. + Board board; // The game board. + boolean gameOver; // Whether the game is over Game(int score, int sz, int width, Board board) { this.score = score; @@ -61,6 +62,17 @@ class Game extends World { this.sz = Util.defaultWidth; this.width = this.sz * Util.scale; this.board = new Board(this.sz); + this.gameOver = false; + this.board.randGen(); + this.board.randGen(); + } + + Game(int w) { + this.score = 0; + this.sz = w; + this.width = this.sz * Util.scale; + this.board = new Board(this.sz); + this.gameOver = false; this.board.randGen(); this.board.randGen(); } @@ -72,12 +84,39 @@ class Game extends World { new TextImage("Score: " + this.score, 20, Color.RED), this.width / 2, 20 ); + + // Display game over message if the game is over + if (this.gameOver) { + WorldImage gameOverText = + new TextImage("Game Over!", 40, Color.RED); + WorldImage background = new RectangleImage( + this.width / 2, 50, OutlineMode.SOLID, new Color(0, 0, 0, 150) + ); + scene.placeImageXY( + new OverlayImage(gameOverText, background), this.width / 2, + this.width / 2 + ); + } + return scene; } public void onKeyEvent(String key) { System.out.println("got key" + key); + // If game is over, ignore movement keys + if (this.gameOver) { + // Optional: restart game with 'r' key + if (key.equals("r")) { + this.score = 0; + this.board = new Board(this.sz); + this.gameOver = false; + this.board.randGen(); + this.board.randGen(); + } + return; + } + int score = 0; if (key.equals("left") || key.equals("h")) @@ -91,6 +130,9 @@ class Game extends World { else return; this.score += score; + + // Check if game is over after the move + this.gameOver = this.board.isGameOver(); } void run() { this.bigBang(this.width, this.width, 0.01); } @@ -273,6 +315,51 @@ class Board { this.set(chosenSpace, new Tile(value)); } } + + // Checks if the game is over (no valid moves left) + boolean isGameOver() { + // Check if there are any empty spaces + for (int x = 0; x < this.sz; x++) { + for (int y = 0; y < this.sz; y++) { + if (this.get(new Coord(x, y)).isReplaceable()) { + return false; // There's an empty space, game not over + } + } + } + + // Check if any adjacent tiles can be combined + for (int x = 0; x < this.sz; x++) { + for (int y = 0; y < this.sz; y++) { + Cell current = this.get(new Coord(x, y)); + + // Skip if not a tile + if (!(current instanceof Tile)) { continue; } + + Tile currentTile = (Tile)current; + + // Check right neighbor + if (x < this.sz - 1) { + Cell right = this.get(new Coord(x + 1, y)); + if (right instanceof Tile && + ((Tile)right).n == currentTile.n) { + return false; // Can combine horizontally + } + } + + // Check bottom neighbor + if (y < this.sz - 1) { + Cell bottom = this.get(new Coord(x, y + 1)); + if (bottom instanceof Tile && + ((Tile)bottom).n == currentTile.n) { + return false; // Can combine vertically + } + } + } + } + + // No empty spaces and no possible combinations + return true; + } } // The possible movements.