Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

I need to write a java program that plays a \'game of Threes\': The game consist

ID: 3739242 • Letter: I

Question

I need to write a java program that plays a 'game of Threes': The game consists of a grid of moveable tiles. Each tile contains a number 1, 2, 3, or a value that results from starting with a 3 and doubling a bunch of times. We will think of the grid as a 2D array of integer values, where the value 0 means there is no tile in that cell. There are only four possible operations: to "shift" the grid up, down, left, or right. What this means is that the tiles are shifted in the indicated direction, and certain combinations of tiles may be merged if "pushed" together against one of the boundaries. The exact rules for merging are discussed in a later section. The screenshot on the right shows the result of shifting in the "up" direction. The two 12's are "pushed" against the top and merge to make 24. In addition, the 1 and 2 in the second column are merged to make a 3. All other tiles that can move (the two 2's in this case) are shifted up as well. Whenever the grid is shifted in some direction, a new tile appears on the opposite side. The game ends when the grid can't be shifted in any direction because there are no empty cells and no merges are possible. The object of the game is to get the highest possible score. The score is the sum, for all tiles on the grid, of a predetermined number associated with each individual tile value. I need help with the class Game.java, these are the methods, along with the descriptions of what they are supposed to do: package hw3; import java.util.ArrayList; import java.util.Random; import api.Direction; import api.Move; import api.TilePosition; /** * The Game class contains the state and logic for an implementation of a video * game such as "Threes". The basic underlying state is an n by n grid of tiles, * represented by integer values. A zero in a cell is considered to be * * "empty". To play the game, a client calls the method * shiftGrid(), selecting one of the four directions (LEFT, RIGHT, * UP, DOWN). Each row or column is then shifted according to the rules * encapsulated in the associated GameUtil object. The move is * completed by calling newTile, which makes a new tile appear in * the grid in preparation for the next move. *

* In between the call to shiftGrid() and the call to * newTile, the client may also call undo(), which * reverts the grid to its state before the shift. *

* The game uses an instance of java.util.Random to generate new tile values and * to select the location for a new tile to appear. The new values are generated * by the associated GameUtil's * generateRandomTileValue method, and the new positions are * generated by the GameUtil's * generateRandomTilePosition method. The values are always * generated one move ahead and stored, in order to support the ability for a UI * to provide a preview of the next tile value. *

* The score is the sum over all cells of the individual scores returned by the * GameUtil's getScoreForValue() method. */ public class Game { /** * Constructs a game with a grid of the given size, using a default random * number generator. The initial grid is produced by the * initializeNewGrid method of the given GameUtil * object. * * @param givenSize * size of the grid for this game * @param givenConfig * given instance of GameUtil */ public Game(int givenSize, GameUtil givenConfig) { // just call the other constructor this(givenSize, givenConfig, new Random()); } /** * Constructs a game with a grid of the given size, using the given instance of * Random for the random number generator. The initial grid is * produced by the initializeNewGrid method of the given * GameUtil object. * * @param givenSize * size of the grid for this game * @param givenConfig * given instance of GameUtil * @param givenRandom * given instance of Random */ public Game(int givenSize, GameUtil givenConfig, Random givenRandom) { // TODO } /** * Returns the value in the cell at the given row and column. * * @param row * given row * @param col * given column * @return value in the cell at the given row and column */ public int getCell(int row, int col) { // TODO return 0; } /** * Sets the value of the cell at the given row and column. NOTE: This method * should not be used by clients outside of a testing environment. * * @param row * given row * @param col * given col * @param value * value to be set */ public void setCell(int row, int col, int value) { // TODO } /** * Returns the size of this game's grid. * * @return size of the grid */ public int getSize() { // TODO return 0; } /** * Returns the current score. * * @return score for this game */ public int getScore() { // TODO return 0; } /** * Copy a row or column from the grid into a new one-dimensional array. There * are four possible actions depending on the given direction: *

*

LEFT - the row indicated by the index rowOrColumn is copied * into the new array from left to right *

RIGHT - the row indicated by the index rowOrColumn is copied * into the new array in reverse (from right to left) *

UP - the column indicated by the index rowOrColumn is copied * into the new array from top to bottom *

DOWN - the row indicated by the index rowOrColumn is copied * into the new array in reverse (from bottom to top) *

* * @param rowOrColumn * index of the row or column * @param dir * direction from which to begin copying * @return array containing the row or column */ public int[] copyRowOrColumn(int rowOrColumn, Direction dir) { // TODO return null; } /** * Updates the grid by copying the given one-dimensional array into a row or * column of the grid. There are four possible actions depending on the given * direction: *

*

LEFT - the given array is copied into the the row indicated by the index * rowOrColumn from left to right *

RIGHT - the given array is copied into the the row indicated by the index * rowOrColumn in reverse (from right to left) *

UP - the given array is copied into the column indicated by the index * rowOrColumn from top to bottom *

DOWN - the given array is copied into the column indicated by the index * rowOrColumn in reverse (from bottom to top) *

* * @param arr * the array from which to copy * @param rowOrColumn * index of the row or column * @param dir * direction from which to begin copying */ public void updateRowOrColumn(int[] arr, int rowOrColumn, Direction dir) { // TODO } /** * Plays one step of the game by shifting the grid in the given direction. * Returns a list of Move objects describing all moves performed. All Move * objects must include a valid value for getRowOrColumn() and * getDirection(). If no cells are moved, the method returns an * empty list. *

* The shift of an individual row or column is performed by the method * shiftArray of GameUtil. *

* The score is not updated. * * @param dir * direction in which to shift the grid * @return list of moved or merged tiles */ public ArrayList shiftGrid(Direction dir) { // TODO return null; } /** * Reverts the shift performed in a previous call to shiftGrid(), * provided that neither newTile() nor undo() has been * called. If there was no previous call to shiftGrid() without a * newTile() or undo(), this method does nothing and * returns false; otherwise returns true. * * @return true if the previous shift was undone, false otherwise */ public boolean undo() { // TODO return false; } /** * Generates a new tile and places its value in the grid, provided that there * was a previous call to shiftGrid without a corresponding call to * undo or newTile. The tile's position is determined * according to the generateRandomTilePosition of this game's * associated GameUtil object. If there was no previous call to * shiftGrid without an undo or newTile, * this method does nothing and returns null; otherwise returns a * TilePosition object with the new tiles's position and value. * Note that the returned tile's value should match the current value * returned by getNextTileValue, and if this method returns a * non-null value the upcoming tile value should be updated according to * generateRandomTileValue(). This method should update the total * score and the score should include the newly generated tile. * * @return TilePosition containing the new tile's position and value, or null if * no new tile is created */ public TilePosition newTile() { // TODO return null; } /** * Returns the value that will appear on the next tile generated in a call to * newTile. This is an accessor method that does not modify the * game state. * * @return value to appear on the next generated tile */ public int getNextTileValue() { // TODO return 0; } } I ALREADY HAVE THE GAMEUTIL.JAVA CLASS, I NEED HELP WITH GAME.JAVA

Explanation / Answer

Please find my implementation:

GameUtil.java:

package gameofthrees;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Random;

/**
* GameUtil class
*
*/
public class GameUtil {
   enum Direction {UP,DOWN,LEFT,RIGHT};
   class TilePosition
   {
       int row; //row in grid
       int col; //column in grid
       /**
       * @param row
       * @param col
       */
       TilePosition(int row, int col) {
           this.row = row;
           this.col = col;
       }
       /**
       * @return the row
       */
       int getRow() {
           return row;
       }
       /**
       * @param row the row to set
       */
       void setRow(int row) {
           this.row = row;
       }
       /**
       * @return the col
       */
       int getCol() {
           return col;
       }
       /**
       * @param col the col to set
       */
       void setCol(int col) {
           this.col = col;
       }
      
   }
   /**
       * Returns the result of merging the two given tile values, or zero
       * if they can't be merged. The rules are: a 1 can be merged with a 2,
       * and two values greater than 2 can be merged if they match. The
       * result of a merge is always the sum of the tile values.
       * @param a
       *   given tile value
       * @param b
       *   given tile value
       * @return
       *   result of merging the two values, or zero if no merge is possible
       */
   public int mergeValues(int a, int b)
   {
        if (a > 0 && b > 0 &&
            (a + b == 3) ||
            (a >= 3 && b == a))
        {
          return a + b;
        }
        else
        {
          return 0;
        }
   }?

   /**
       * Returns a new size x size array with two nonzero cells.
       * The nonzero cells consist of a 1 and a 2, placed randomly
       * in the grid using the given Random instance.
       * @param size
       *   width and height of the new array
       * @param rand
       *   random number generator to use for positioning the nonzero cells
       * @return
       *   new size x size array
       */
   public int[][] initializeNewGrid(int size, Random rand)
   {
        int[][] grid = new int[size][size];
        int numCells = size * size;
     
        // To select two distinct cells, think of the numCells cells as ordered
        // left to right within rows, with the rows ordered top to bottom.
        // First select two distinct integers between 0 and numCells
        int first = rand.nextInt(numCells);
        int second = rand.nextInt(numCells - 1);
        if (second >= first)
        {
          second += 1;
        }
     
        // Then, divide by size to get the row, mod by size to get column,
        // put a 1 in the first and a 2 in the other
        grid[first / size][first % size] = 1;
        grid[second / size][second % size] = 2;
     
        return grid;
   }?

   /**
   * Returns the total score for the given grid. The grid is not modified.
   *
   * @param grid
   *            given grid
   * @return sum of scores for the values in the grid
   */
   public int calculateTotalScore(int[][] grid) {
       int total = 0;
       for (int row = 0; row < grid.length; ++row) {
           for (int col = 0; col < grid[0].length; ++col) {
               total += getScoreForValue(grid[row][col]);
           }
       }
       return total;
   }

   public int getScoreForValue(int value) {
       // TODO Auto-generated method stub
       return value;
   }

   /**
   * Makes a copy of the given 2D array. The array must be nonempty and
   * rectangular.
   *
   * @param grid
   *            given 2D array to copy
   * @return copy of the given array
   */
   public int[][] copyGrid(int[][] grid) {
       int[][] ret = new int[grid.length][grid[0].length];
       for (int row = 0; row < grid.length; ++row) {
           for (int col = 0; col < grid[0].length; ++col) {
               ret[row][col] = grid[row][col];
           }
       }
       return ret;
   }
  
   //generate random tile value
   public int generateRandomTileValue(Random rand)
   {
       return rand.nextInt();
   }
  
   //generates the random tile position
   TilePosition generateRandomTilePosition(int[] grid, Random rand, Direction lastMove)
   {
       int row,col;
       switch(lastMove){
       case UP:
           row = grid.length;
           col = rand.nextInt(grid.length);
           break;
       case DOWN:
           row = 0;
           col = rand.nextInt(grid.length);
           break;
       case RIGHT:
           row = rand.nextInt(grid.length);
           col = 0;
           break;
       case LEFT:
           row = rand.nextInt(grid.length);
           col = grid.length;
           break;
       }      
       return new TilePosition(row, col);      
   }
  
   //shiftArray method
   @SuppressWarnings("rawtypes")
   ArrayList shiftArray(int[] arr)
   {
       ArrayList list = new ArrayList<Integer>();
       //locate empty cell
       boolean emptyCell = false;
       int i;
       for(i=arr.length-1;i>=0;i--)
       {
           if(arr[i]==0)
           {
               emptyCell = false;
               break;
           }
       }
       //in case of empty cell, shift all elements on right of empty cell one place on left.
       if(emptyCell)
       {
           int j;
           for(j = i+1;j<arr.length;j++)
           {
               arr[j-1]=arr[j];
           }
           arr[j]=0;
       }
       list = (ArrayList) Arrays.asList(arr);
       return list;
   }
}