//File: GameState.java //Name: Trai Pham //Date: 02/06/2020 //Course: CSE 8B /**This code would allow you to play the game 2048 on the command prompt. This code is goes over all elements of the game 2048. This program would allow user to move the values within the grid of the game 2048. */ //#file header: This file contains the GameState, Config, Direction, and //Game2048 code. //#class header: the GameState class is the core of movements and operation of //the 2048 game. It creates the board and allows user to move import java.util.Random; import java.util.Random.*; import java.util.*; public class GameState{ //declaring the class's variable private Random rng; private int [][] board; private int score; private int numTiles; //Constructor public GameState(int numRows, int numCols){ this.score = 0; this.board = new int[numRows][numCols]; this.rng = new Random(Config.RANDOM_SEED); } //Each element of the 2d-array should either be the value //of the tile or 0 if the tile does not exist /* Creates a deep copy of the Board */ public int[][] getBoard(){ int [][] newBoard = new int [this.board.length][this.board[0].length]; for(int i = 0; i < this.board.length; i++){ for(int j =0; j < this.board[0].length; j++){ newBoard[i][j] = this.board[i][j]; } } return newBoard; } /* @param 2d Array Sets the new board to that of the game board @return void, creates a new board */ public void setBoard(int [][] newBoard){ if( newBoard == null){ return; } else{ int [][] board2 = new int[newBoard.length][newBoard[0].length]; for(int i = 0; i< newBoard.length; i++){ for(int j =0; j < newBoard[0].length; j++){ board2[i][j] = newBoard[i][j]; } } this.board = board2; } } /*@ param none @return int Gets the score of the game */ public int getScore(){ return this.score; } /*@ param int of the updated Score @return void Gets the new score for the game */ public void setScore (int newScore){ this.score = newScore; // setting the input class variable score to called } /*@param int, bound to roll a random number @return int random number gets a random number between 0 and a bound */ protected int rollRNG(int bound){ int newBound = this.rng.nextInt(bound); return newBound; //returns a random number between 0 and bound } /*@param none @return int, number 2 or 4 random tile 2 or 4 created */ protected int randomTile (){ int num2 = 2; int num4 = 4; int newInt = this.rng.nextInt(Config.RANDOM_SEED); if(newInt <= Config.TWO_PROB){ return num2; } else{ return num4; } } /*@oaram none @return int, number of empty tiles gives you a number of how much empty squares there are */ protected int countEmptyTiles (){ int counter = 0; for(int i = 0; i < this.board.length; i++){ for(int j = 0; j < this.board[0].length; j++){ if(this.board[i][j] == 0){ counter ++; } } } return counter; } /*@param none @return int, randomly added tile, it'll be 2 or 4 adds a tile at a random empty tile on the board */ protected int addTile(){ int a = 0; int b = 0; if(this.countEmptyTiles() == 0){ return 0; } else{ boolean flag = true; while(flag){ a = rollRNG(this.board.length); b = rollRNG(this.board[0].length); if(this.board[a][b] == 0){ // empty space checks flag = false; } } this.board[a][b] = randomTile(); return(this.board[a][b]); } } //MOVEMENT METHODS //Remember to call addTiles and countEmptyTiles() after every movement /*@param none @return void rotates the board counter clockwise */ protected void rotateCounterClockwise (){ //optional //creating a deep copy of the board for(int i = 0; i < this.board.length; i++){ for(int j =0; j < this.board[0].length; j++){ int a = this.board[j][this.board[0].length-i-1]; this.board[i][j] = a; } } } /*@param none @return boolean, true if you cna slide down, false if you can't checks if the tiles can slide down */ protected boolean canSlideDown (){ //this checks if the tiles are equal to one another if(this.countEmptyTiles() > 0){ for(int i = 0; i < this.board.length; i++){ //When tile is on the last row/edge if(i == this.board.length -1){ return false; } for( int j =0 ; j < this.board[0].length; j++){ if(i +1 >= this.board.length){ return false; } //When two tiles next to each other are equal if(this.board[i][j] != 0 && this.board[i][j] == this.board[i+1][j]){ return true; } //When there is an empty space below a tile if(this.board[i][j] !=0 && this.board[i+1][j] == 0){ return true; } } } } return false; } /*@param none @return boolean, true if game is over, false if you can still move checks if the game is over or not based on restriction of movements */ public boolean isGameOver (){ int i =0; while(i != 4){ if(this.canSlideDown() == false){ this.rotateCounterClockwise(); i++; } if(this.canSlideDown() == true){ return false; } } return true; } /* @param void @return boolean true if slide is successful, false if not */ protected boolean slideDown(){ while(this.canSlideDown()==true){ for(int col = 0 ; col 0; row--){ //variable represent col before //checks that there is empty spaces below tile //moving tile down if(this.board[row][col] == 0){ this.board[row][col] = this.board[row-1][col]; this.board[row -1][col] = 0; continue; } else if(this.board[row -1][col] == this.board[row][col]){ this.board[row][col] = this.board[row -1][col]*2; this.board[row-1][col] = 0; this.score += this.board[row][col]; continue; } else{ continue; } } } } return this.countEmptyTiles() >1; } /*@param Direction object @return boolean, true if you can move in a certain direction, false if you can't This allows the user to move within the game */ public boolean move(Direction dir){ if(dir == null){ return false; } if(dir == Direction.DOWN && this.slideDown() == true){ this.addTile(); return true; } if(dir == Direction.LEFT){ this.rotateCounterClockwise(); this.slideDown(); return true; } if(dir == Direction.UP){ int i = 0; while( i != dir.getRotationCount()){ this.rotateCounterClockwise(); i++; } this.slideDown(); return true; } if(dir == Direction.RIGHT){ int b = 0; while( b != dir.getRotationCount()){ this.rotateCounterClockwise(); b++; } this.slideDown(); return true; } return false; } /*@param none @return String this converts the 2d array to that of strings so that it'll be printed instead of printing the reference/address number */ public String toString () { StringBuilder outputString = new StringBuilder(); outputString.append(String.format("Score: %d\n", getScore())); for (int row = 0; row < getBoard().length; row++) { for (int column = 0; column < getBoard()[0].length; column++) { //Something wrong with bottom code outputString.append(getBoard()[row][column] == 0 ? " -" : String.format("%5d", getBoard()[row][column])); } outputString.append("\n"); } return outputString.toString(); } }