/** Return the current Tile at (COL, ROW), where 0 <= ROW < size(), * 0 <= COL < size(). Returns null if there is no tile there. */publicTiletile(intcol,introw){returnvtile(col,row,viewPerspective);}/** Returns the size of the board. */publicintsize(){returnvalues.length;}
/** Returns true if at least one space on the Board is empty. * Empty spaces are stored as null. * */publicstaticbooleanemptySpaceExists(Boardb){// TODO: Fill in this function. for(inti=0;i<b.size();++i){for(intj=0;j<b.size();++j){if(b.tile(i,j)==null){returntrue;}}}returnfalse;}
/** * Returns true if any tile is equal to the maximum valid value. * Maximum valid value is given by MAX_PIECE. Note that * given a Tile object t, we get its value with t.value(). */publicstaticbooleanmaxTileExists(Boardb){// TODO: Fill in this function. for(inti=0;i<b.size();++i){for(intj=0;j<b.size();++j){Tilenum=b.tile(i,j);if(num!=null&&num.value()==MAX_PIECE){returntrue;}}}returnfalse;}
/** * Returns true if there are any valid moves on the board. * There are two ways that there can be valid moves: * 1. There is at least one empty space on the board. * 2. There are two adjacent tiles with the same value. */publicstaticbooleanatLeastOneMoveExists(Boardb){// TODO: Fill in this function. if(emptySpaceExists(b)){returntrue;}intbSize=b.size();for(inti=0;i<bSize-1;++i){for(intj=0;j<bSize-1;++j){if(b.tile(i,j).value()==b.tile(i,j+1).value()||b.tile(i,j).value()==b.tile(i+1,j).value()){returntrue;}}}// Analyze the bottom right corner separately if(b.tile(bSize-1,bSize-1).value()==b.tile(bSize-2,bSize-1).value()||b.tile(bSize-1,bSize-1).value()==b.tile(bSize-1,bSize-2).value()){returntrue;}returnfalse;}
for(intj=0;j<size;++j){// Outer loop: Iterate through each column independentlyfor(inti=0;i<size;++i){// Inner loop: Process rows from top to bottom (target direction)// Part 1: Fill the current empty cell (if any)if(b[i][j]==null){// Look for the next available tile below the current empty spotfor(intk=i+1;k<size;++k){if(b[k][j]!=null){// Pull the found tile up to the current empty positionmove(i,j,tile(k,j));break;// Move only the first tile found}}// If the cell is still null, no more tiles exist in this column to move upif(b[i][j]==null){break;}}// Part 2: Merge logic// Look for the next tile below the current (now non-empty) cell to check for a mergefor(intk=i+1;k<size;++k){if(b[k][j]!=null){// If values match, merge the lower tile into the current oneif(b[k][j].val()==b[i][j].val()){move(i,j,tile(k,j));}// Stop searching after encountering the first tile (whether merged or blocked)break;}}}}
/** Tilt the board toward SIDE. Return true if this changes the board. * * 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 * 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). * 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. * */publicbooleantilt(Sideside){booleanchanged;changed=false;// TODO: Modify this.board (and perhaps this.score) to account // for the tilt to the Side SIDE. If the board changed, set the // changed local variable to true. if(side==Side.NORTH){for(intj=0;j<size();++j){for(inti=size()-1;i>=0;--i){if(board.tile(j,i)==null){for(intk=i-1;k>=0;--k){if(board.tile(j,k)!=null){board.move(j,i,board.tile(j,k));changed=true;break;}}if(board.tile(j,i)==null){break;}}for(intk=i-1;k>=0;--k){if(board.tile(j,k)!=null){if(board.tile(j,k).value()==board.tile(j,i).value()){score+=2*board.tile(j,k).value();board.move(j,i,board.tile(j,k));changed=true;}break;}}}}}checkGameOver();if(changed){setChanged();}returnchanged;}
/** Tilt the board toward SIDE. Return true if this changes the board. * * 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 * 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). * 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. * */publicbooleantilt(Sideside){booleanchanged;changed=false;// TODO: Modify this.board (and perhaps this.score) to account// for the tilt to the Side SIDE. If the board changed, set the// changed local variable to true.if(side==Side.NORTH){board.setViewingPerspective(Side.NORTH);}elseif(side==Side.SOUTH){board.setViewingPerspective(Side.SOUTH);}elseif(side==Side.EAST){board.setViewingPerspective(Side.EAST);}elseif(side==Side.WEST){board.setViewingPerspective(Side.WEST);}for(intj=0;j<size();++j){for(inti=size()-1;i>=0;--i){if(board.tile(j,i)==null){for(intk=i-1;k>=0;--k){if(board.tile(j,k)!=null){board.move(j,i,board.tile(j,k));changed=true;break;}}if(board.tile(j,i)==null){break;}}for(intk=i-1;k>=0;--k){if(board.tile(j,k)!=null){if(board.tile(j,k).value()==board.tile(j,i).value()){score+=2*board.tile(j,k).value();board.move(j,i,board.tile(j,k));changed=true;}break;}}}}board.setViewingPerspective(Side.NORTH);checkGameOver();if(changed){setChanged();}returnchanged;}