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

USING MATLAB For the game 2048, develop code (MATLAB) to move the tiles in eithe

ID: 3865653 • Letter: U

Question

USING MATLAB

For the game 2048, develop code (MATLAB) to move the tiles in either the up, down, left, or right direction.

Given the location of the tiles, calculate how the tiles and score will change for each move.

Create the following two functions (MATLAB):

•MoveLeftRight

–Summary: Given the board as a 4x4 matrix, determine the new board after moving left or right

–Inputs: board (4x4 matrix), current score (numeric value), left (boolean value)

–Outputs: new board (4x4 matrix), new score (numeric value)

–Example to move left: [newBoard,newScore] = MoveLeftRight(board,score,true);

–Example to move right: [newBoard,newScore] = MoveLeftRight(board,score,false);

•MoveUpDown

–Summary: Given the board as a 4x4 matrix, determine how the new board after moving up or down

–Inputs: board (4x4 matrix), current score (numeric value), up (boolean value)

–Outputs: new board (4x4 matrix), new score (numeric value)

–Example to move up: [newBoard,newScore] = MoveUpDown(board,score,true);

–Example to move down: [newBoard,newScore] = MoveUpDown(board,score,false);

Explanation / Answer

function npuzzle(cmd)
%       npuzzle             % Start Main N-Puzzle Interface
%       npuzzle('fifteen') % Start new 15-Puzzle w/o Main Interface

%   Developed by Per-Anders Ekstrm, 2003-2007 Facilia AB.

if ~nargin
   npuzzle('init')
   return;
end

if ~(ischar(cmd)||isscalar(cmd))
   return;
end

switch cmd
   %------------------------------------------------------------------
   case 'init'

       % MAIN FIGURE
       scrsz = get(0,'ScreenSize');
       hFigure = figure( ...
           'Name','N-Puzzle', ...
           'Menubar','none',...
           'NumberTitle','off', ...
           'KeyPressFcn','npuzzle(double(get(gcbf,''Currentcharacter'')))', ...
           'Units','pixels', ...
           'Tag','npuzzle', ...
           'Position',[(scrsz(3)-510)/2 (scrsz(4)-500)/2 510 500], ...
           'Color',[.95 .95 .95], ...
           'Colormap',[1 1 1;.93 .97 .93;1 1 .6;.6 .8 1;.6 1 .6;1 .6 .6], ...
           'Visible','on');

       % MENU
       FileMenu = uimenu(hFigure,'Label','File');
       uimenu(FileMenu,'Label','New Game','Accelerator','N','Callback','npuzzle(''NewGame'')');
       NewBoard = uimenu(FileMenu,'Label','New Board');
       uimenu(NewBoard,'Label','3 (2x2)','Callback','npuzzle(''three'')');
       uimenu(NewBoard,'Label','8 (3x3)','Callback','npuzzle(''eight'')');
       uimenu(NewBoard,'Label','15 (4x4)','Callback','npuzzle(''fifteen'')');
       uimenu(NewBoard,'Label','24 (5x5)','Callback','npuzzle(''twentyfour'')');
       uimenu(NewBoard,'Label','35 (6x6)','Callback','npuzzle(''thirtyfive'')');
       uimenu(NewBoard,'Label','48 (7x7)','Callback','npuzzle(''fourtyeight'')');
       uimenu(NewBoard,'Label','Custom ...','Separator','on','Callback','npuzzle(''CustomBoard'')');
       uimenu(FileMenu,'Label','Import Game ...','Callback','npuzzle(''ImportGame'')');
       uimenu(FileMenu,'Label','Solve Game','Separator','on','Callback','npuzzle(''Solve'')');
       uimenu(FileMenu,'Label','Exit','Accelerator','Q','Separator','on','Callback','delete(gcf)');
       EditMenu = uimenu(hFigure,'Label','Edit');
       uimenu(EditMenu,'Label','Undo','Accelerator','Z','Callback','npuzzle(''Undo'')','Tag','Undo');
       uimenu(EditMenu,'Label','Redo','Accelerator','R','Callback','npuzzle(''Redo'')','Tag','Redo');
       HelpMenu = uimenu(hFigure,'Label','Help');
       uimenu(HelpMenu,'Label','Help','Accelerator','H','Callback','helpwin npuzzle');
       uimenu(HelpMenu,'Label','Simulate History','Callback','npuzzle(''SimulateHistory'')','Separator','on');
       uimenu(HelpMenu,'Label','About','Callback','npuzzle(''About'')','Separator','on');

       % MATRIX AXES
       axes( ...
           'Parent',hFigure, ...
           'Units','normalized', ...
           'Clipping','on', ...
           'Position',[0.02 0.02 0.96 0.96]);
       axis('square')

       % Start a new board with N=16
       startgame(16)
       %------------------------------------------------------------------
   case 'Surface'
       ud = get(gca,'UserData');
       set(gcf,'Name',[num2str(ud.N-1) '-Puzzle'])
       EdgeColor = [.6 .6 .6];
       FaceColor = [1 1 1];
       FontSize = .5/ud.n;
       HoleColor = [.3 .3 .3];
       delete(findobj(gca,'Tag','Surface'))
       delete(findobj(gca,'Tag','Hole'))
       arrayfun(@(x)delete(findobj(gca,'Tag',num2str(x))),1:1000)

       % MATRIX SURFACE
       CData = zeros(ud.n+1,ud.n+1);
       surface( ...
           zeros(size(CData)),CData, ...
           'Parent',gca, ...
           'ButtonDownFcn','npuzzle(''ButtonDown'');', ...
           'EdgeColor',EdgeColor, ...
           'FaceColor',FaceColor, ...
           'LineWidth',1,...
           'Tag','Surface')
       axis off
       hold on

       % TEXT FIELDS
       arrayfun(@(x)text( ...
           'Position',[mod(x-1,ud.n)+1 ud.n+1-ceil(x/ud.n)]+.5, ...
           'String','', ...
           'FontUnits','normalized', ...
           'FontSize',FontSize, ...
           'Tag',num2str(x), ...
           'ButtonDownFcn','npuzzle(''ButtonDown'');', ...
           'HorizontalAlignment','center'), ...
           1:ud.N)

       % EMPTY FIELD
       fill(1,1,HoleColor, ...
           'ButtonDownFcn','npuzzle(''ButtonDown'');', ...
           'Tag','Hole')
       %------------------------------------------------------------------
   case 'three'
       startgame(4)
       %------------------------------------------------------------------
   case 'eight'
       startgame(9)
       %------------------------------------------------------------------
   case 'fifteen'
       startgame(16)
       %------------------------------------------------------------------
   case 'twentyfour'
       startgame(25)
       %------------------------------------------------------------------
   case 'thirtyfive'
       startgame(36)
       %------------------------------------------------------------------
   case 'fourtyeight'
       startgame(49)
       %------------------------------------------------------------------
   case 'CustomBoard'
       prompt = {'Input Size of Board (N):'};
       name = 'Custom Board Size';
       options.Resize = 'on';
       answer = inputdlg(prompt,name,1,{'15'},options);
       if ~isempty(answer)
           N = str2double(answer{1})+1;
           n = round(sqrt(N));
           if n^2==N
               startgame(N)
           else
               errordlg('Input Size (N) Not Accepted','Custom Board Size')
           end
       end
       %------------------------------------------------------------------
   case 'NewGame'
       ud = get(gca,'UserData');
       board = shuffleboard(1:ud.N,10000); % Shuffle the board
       ud.board = board;
       ud.boardhistory = ud.board;
       ud.histpos = 1;
       ud.starttime = clock;
       ud.endtime = [];
       set(gca,'UserData',ud);
       set(findobj(gcf,'Tag','Undo'),'Enable','off')
       set(findobj(gcf,'Tag','Redo'),'Enable','off')
       drawboard()
       drawpos()
       %------------------------------------------------------------------
   case 'ImportGame'
       prompt = {'Input Game as a Vector or a Matrix:'};
       name = 'Import Game';
       options.Resize = 'on';
       answer = inputdlg(prompt,name,1,{''},options);
       if ~isempty(answer)&&~isempty(answer{1})
           board = str2num(answer{1})';
           board = board(:)';
           N = length(board);
           n = round(sqrt(N));
           if ~isempty(board)&&n^2==N&&~ismember(0,ismember(1:N,board))
               ud = get(gca,'UserData');
               ud.board = board;
               ud.N = N;
               ud.n = n;
               ud.currpos = 1;
               ud.boardhistory = ud.board;
               ud.histpos = 1;
               ud.starttime = clock;
               ud.endtime = [];
               set(gca,'UserData',ud);
               set(findobj(gcf,'Tag','Undo'),'Enable','off')
               set(findobj(gcf,'Tag','Redo'),'Enable','off')
               npuzzle('Surface')
               drawboard()
               drawpos()
           else
               errordlg('Input Game Not Accepted','Import Game')
           end
       end
       %------------------------------------------------------------------
   case 'SimulateHistory'          
       set(gcf,'Color',[.7 0 0],'Pointer','watch','CloseRequestFcn','','KeyPressFcn','')
       ud = get(gca,'UserData');
       for i=1:ud.histpos
           hole = find(ud.boardhistory(i,:)==ud.N);
           x = mod(hole-1,ud.n)+1;
           y = ud.n+1-ceil(hole/ud.n);
           delete(findobj(gca,'tag','currpos'))
           plot(x+[0 .995 .995 0 0]+0.005,y+[0 0 .995 .995 0],'r', ...
               'LineWidth',2, ...
               'Tag','currpos')
           pause(.2)
           arrayfun(@(x)set(findobj(gca,'tag',num2str(x)), ...
               'String',num2str(ud.boardhistory(i,x))), ...
               1:ud.N)
           set(findobj(gca,'tag','Hole'), ...
               'XData',x+[0 .99 .99 0 0]+0.005,...
               'YData',y+[0 0 .99 .99 0]+0.005)
           pause(.3)
       end
       set(gcf,'Color',[.95 .95 .95],'Pointer','arrow','CloseRequestFcn','closereq','KeyPressFcn','npuzzle(double(get(gcbf,''Currentcharacter'')))')
       drawpos()
       %------------------------------------------------------------------
   case 'Solve'
       ud = get(gca,'UserData');
       if sum(ud.board(:)'==1:ud.N)~=ud.N % if not solved
           set(gcf,'Color',[.7 0 0],'Pointer','watch','CloseRequestFcn','','KeyPressFcn','')
           pause(.2)
           boardhistory = solve(ud.board);
           ud.boardhistory = [ud.boardhistory(1:ud.histpos,:);boardhistory];
           ud.board = 1:ud.N;
           set(gca,'UserData',ud);
           set(findobj(gcf,'Tag','Redo'),'Enable','off')
           set(findobj(gcf,'Tag','Undo'),'Enable','on')
           ud = get(gca,'UserData');
           for i=ud.histpos:size(ud.boardhistory,1)
               hole = find(ud.boardhistory(i,:)==ud.N);
               x = mod(hole-1,ud.n)+1;
               y = ud.n+1-ceil(hole/ud.n);
               delete(findobj(gca,'tag','currpos'))
               plot(x+[0 .995 .995 0 0]+0.005,y+[0 0 .995 .995 0],'r', ...
                   'LineWidth',2, ...
                   'Tag','currpos')
               pause(.01)
               arrayfun(@(x)set(findobj(gca,'tag',num2str(x)), ...
                   'String',num2str(ud.boardhistory(i,x))), ...
                   1:ud.N)
               set(findobj(gca,'tag','Hole'), ...
                   'XData',x+[0 .99 .99 0 0]+0.005,...
                   'YData',y+[0 0 .99 .99 0]+0.005)
               pause(.03)
           end
           ud.histpos = size(ud.boardhistory,1);
           set(gca,'UserData',ud);
           pause(.2)
           set(gcf,'Color',[.95 .95 .95],'Pointer','arrow','CloseRequestFcn','closereq','KeyPressFcn','npuzzle(double(get(gcbf,''Currentcharacter'')))')
           drawpos()
       end
       %------------------------------------------------------------------
   case 'Undo'
       ud = get(gca,'UserData');
       if ud.histpos>1
           ud.histpos = ud.histpos-1;
           ud.board = ud.boardhistory(ud.histpos,:);
           set(gca,'UserData',ud);
           drawboard()
           set(findobj(gcf,'Tag','Redo'),'Enable','on')
       end
       if ud.histpos<=1
           set(findobj(gcf,'Tag','Undo'),'Enable','off')
       end
       %------------------------------------------------------------------
   case 'Redo'
       ud = get(gca,'UserData');
       if ud.histpos<size(ud.boardhistory,1)
           ud.histpos = ud.histpos+1;
           ud.board = ud.boardhistory(ud.histpos,:);
           set(gca,'UserData',ud);
           drawboard()
           set(findobj(gcf,'Tag','Undo'),'Enable','on')
       end
       if size(ud.boardhistory,1)<=ud.histpos
           set(findobj(gcf,'Tag','Redo'),'Enable','off')
       end
       %------------------------------------------------------------------
   case 'ButtonDown' % MouseClick
       ud = get(gca,'UserData');
       n = sqrt(ud.N);
       pos = get(gca,'CurrentPoint');
       ud.currpos = sub2ind([n n],floor(pos(1,1)),ud.n+1-floor(pos(1,2)));
       set(gca,'UserData',ud);
       drawpos()
       % If not left-click, treat as space
       if ~strcmpi('normal',get(gcf,'SelectionType'))
           npuzzle(32)
       end
       %------------------------------------------------------------------
   case 28 % left
       ud = get(gca,'UserData');
       if ud.currpos~=1
           ud.currpos = ud.currpos-1;
           set(gca,'UserData',ud);
           drawpos()
       end
       %------------------------------------------------------------------
   case 29 % right
       ud = get(gca,'UserData');
       if ud.currpos~=ud.N
           ud.currpos = ud.currpos+1;
           set(gca,'UserData',ud);
           drawpos()
       end
       %------------------------------------------------------------------
   case 30 % up
       ud = get(gca,'UserData');
       if ud.currpos>ud.n
           ud.currpos = ud.currpos-ud.n;
           set(gca,'UserData',ud);
           drawpos()
       end
       %------------------------------------------------------------------
   case 31 % down
       ud = get(gca,'UserData');
       if ud.currpos<=ud.N-ud.n
           ud.currpos = ud.currpos+ud.n;
           set(gca,'UserData',ud);
           drawpos()
       end
       %------------------------------------------------------------------
   case 32 % space
       ud = get(gca,'UserData');
       n = sqrt(ud.N);
       hole = find(ud.board==ud.N);
       bx = mod(hole-1,n)+1;
       by = ud.n+1-ceil(hole/n);
       cx = mod(ud.currpos-1,n)+1;
       cy = ud.n+1-ceil(ud.currpos/n);
       if (bx==cx&&abs(by-cy)==1)||(by==cy&&abs(bx-cx)==1)
           ud.board(hole) = ud.board(ud.currpos);
           ud.board(ud.currpos) = ud.N;
           ud.histpos = ud.histpos+1;
           ud.boardhistory(ud.histpos,:) = ud.board;
           if size(ud.boardhistory,1)>ud.histpos
               ud.boardhistory(ud.histpos+1:end,:) = [];
           end
           set(findobj(gcf,'Tag','Redo'),'Enable','off')
           set(findobj(gcf,'Tag','Undo'),'Enable','on')
           ud.currpos = hole;
           set(gca,'UserData',ud);
           drawboard()
           drawpos()
           if isempty(ud.endtime)
               checksolution()
           end
       end
       %------------------------------------------------------------------
   case 'About'
       ico = ones(13)*3; % create simple icon matrix
       ico(:,1:4:13) = 1;
       ico(1:4:13,:) = 1;
       ico(10:12,10:12) = 2;
       map = [0 0 0;.5 .5 .6;1 1 1];
       msgbox(sprintf([...
           'Graphical User Interface for playing the N-Puzzle. '...
           'Developed by Per-Anders Ekstrm, 2003-2007 Facilia AB '...
           'E-mail: peranders.ekstrom@facilia.se']),...
           'About N-Puzzle','custom',ico,map)
end
end
%% FUNCTION: DRAWBOARD
function drawboard()
ud = get(gca,'UserData');
arrayfun(@(x)set(findobj(gca,'tag',num2str(x)), ...
   'String',num2str(ud.board(x))), ...
   1:ud.N)
hole = find(ud.board==ud.N);
x = mod(hole-1,ud.n)+1;
y = ud.n+1-ceil(hole/ud.n);
set(findobj(gca,'Tag','Hole'), ...
   'XData',x+[0 .99 .99 0 0]+0.005,...
   'YData',y+[0 0 .99 .99 0]+0.005)
end

%% FUNCTION: DRAWPOS
function drawpos()
ud = get(gca,'UserData');
delete(findobj(gca,'tag','currpos'))
x = mod(ud.currpos-1,ud.n)+1;
y = ud.n+1-ceil(ud.currpos/ud.n);
plot(x+[0 .995 .995 0 0]+0.005,y+[0 0 .995 .995 0],'r', ...
   'LineWidth',2, ...
   'Tag','currpos')
end

%% FUNCTION: SHUFFLEBOARD
function board = shuffleboard(board,times)
N = length(board);
n = sqrt(N);
hole = find(board==N);
for i=1:times
   move = [1 -1 n -n];
   x = mod(hole-1,n)+1;
   y = ceil(hole/n);
   switch x
       case 1
           move(2) = 1;
       case n
           move(1) = -1;
   end
   switch y
       case 1
           move(4) = n;
       case n
           move(3) = -n;
   end
   newhole = hole + move(ceil(rand*4));
   board(hole) = board(newhole);
   hole = newhole;
end
board(newhole) = N;
end

%% FUNCTION: CHECKSOLUTION
function checksolution()
ud = get(gca,'UserData');
if ~ismember(0,ud.board==1:ud.N)
   ud.endtime = clock;
   set(gca,'UserData',ud);
   ico = ones(13)*3; % create simple icon matrix
   ico(:,1:4:13) = 1;
   ico(1:4:13,:) = 1;
   ico(10:12,10:12) = 2;
   map = [0 0 0;.5 .5 .6;1 1 1];
   msgbox(sprintf([...
       'CONGRATULATIONS! '...
       'Start time: %s '...
       'End time: %s '...
       'Elapsed time: %d seconds '...
       'Number of moves: %d'],...
       datestr(ud.starttime,13),...
       datestr(ud.endtime,13),...
       round(etime(ud.endtime,ud.starttime)),...
       ud.histpos),...
       'Finished N-Puzzle','custom',ico,map)
end
end

%% FUNCTION: STARTGAME
function startgame(N)
ud = get(gca,'UserData');
ud.N = N;
ud.n = sqrt(N);
ud.currpos = 1;
set(gca,'UserData',ud);
npuzzle('Surface')
npuzzle('NewGame')
end

%% FUNCTION: SOLVE
function solution = solve(board)
board = board(:)';
solution = [];
N = length(board);
n = sqrt(N);
tilePos = @(tile,board)find(board==tile);
holePos = @(board)tilePos(N,board);
column = @(pos)mod(pos-1,n)+1;
row = @(pos)ceil(pos/n);

%% PHASE 1
% 1. Find the next tile you want to place in position in the top row.
% 2. If it is not the last tile of the row, it is fairly easy to place
%     correctly, simply keep the following points in mind:
%      1. Never disturb any previously placed pieces.
%      2. To move the tile in a certain direction, move the other tiles
%         around until the space is next to your tile on the side you want
%         to move it to. Then you can move the tile.
% 3. If the last tile is not already in position, bring it to the position
%     directly below its correct spot, with the space directly below that.
%     Then move tiles in the following directions:
%       Down, down, right, up, left, up, right, down, down, left, up.
%     This should place the piece in position.
%     Note it does temporarily disturb the previously placed tile.

for cr=1:n-2        % for all rows except last two rows
   for cc=1:n-1    % for all columns except last column
       currentTile = cc+(cr-1)*n;
       % if tile not at correct position
       if tilePos(currentTile,board)~=currentTile %
           % if current tile is at bottom row, move it up one step
           if row(tilePos(currentTile,board)) == n
               % move hole to position above it
               moveHoleToRowColumn(n-1,column(tilePos(currentTile,board)))
               % pop the position up one step by moving hole down
               moveHole('down')
           end
           % move hole to bottom or side of current tile
           while row(holePos(board))<n && row(holePos(board))<row(tilePos(currentTile,board))
               moveHole('down');
           end
           if tilePos(currentTile,board)==currentTile
               continue
           end
           % if current tile is not at correct column
           while column(tilePos(currentTile,board)) ~= cc
               % move hole to bottom or under tile
               while row(holePos(board))<n && row(holePos(board))<=row(tilePos(currentTile,board))
                   moveHole('down');
               end
               if tilePos(currentTile,board)==currentTile
                   continue
               end
               % move hole to left/right of current tile
               if column(tilePos(currentTile,board)) <= cc
                   while column(holePos(board))<column(tilePos(currentTile,board))+1
                       moveHole('right');
                   end
                   while column(holePos(board))>column(tilePos(currentTile,board))+1
                       moveHole('left');
                   end
               elseif column(tilePos(currentTile,board)) > cc
                   while column(holePos(board))>column(tilePos(currentTile,board))-1
                       moveHole('left');
                   end
                   while column(holePos(board))<column(tilePos(currentTile,board))-1
                       moveHole('right');
                   end
               end
               % move hole up to same row of current tile
               if row(holePos(board)) > row(tilePos(currentTile,board))
                   while row(holePos(board)) > row(tilePos(currentTile,board))
                       moveHole('up');
                   end
               end
               if column(holePos(board)) > column(tilePos(currentTile,board))
                   moveHole('left');
               else
                   moveHole('right');
               end
           end
           % now tile is supposed to be at correct column

           % if current tile is not at correct row
           while row(tilePos(currentTile,board)) ~= cr
               moveHoleToRowColumn(row(tilePos(currentTile,board))+1,column(tilePos(currentTile,board))+1)
               moveHole('up','up','left','down')
           end
       end
   end

   currentTile = cr*n;
   % if tile not at correct position
   if tilePos(currentTile,board)~=currentTile
       % if current tile is at bottom row
       if row(tilePos(currentTile,board)) == n
           % move hole to position above it
           moveHoleToRowColumn(n-1,column(tilePos(currentTile,board)))
           % pop the position up one step
           moveHole('down')
       end
       % move hole to bottom or side of current tile
       if row(holePos(board))~=n && row(holePos(board))<=row(tilePos(currentTile,board))
           while row(holePos(board))<n && row(holePos(board))<row(tilePos(currentTile,board))
               moveHole('down');
           end
       end
       if tilePos(currentTile,board)==currentTile
           continue
       end

       % if current tile is not at correct column
       while column(tilePos(currentTile,board)) ~= n
           % move hole to bottom or under tile
           while row(holePos(board))<n && row(holePos(board))<=row(tilePos(currentTile,board))
               moveHole('down');
           end
           if tilePos(currentTile,board)==currentTile
               continue
           end
           % move hole to left/right of current tile
           if column(tilePos(currentTile,board)) <= cc
               while column(holePos(board))<column(tilePos(currentTile,board))+1
                   moveHole('right');
               end
               while column(holePos(board))>column(tilePos(currentTile,board))+1
                   moveHole('left');
               end
           elseif column(tilePos(currentTile,board)) > cc
               while column(holePos(board))>column(tilePos(currentTile,board))-1
                   moveHole('left');
               end
               while column(holePos(board))<column(tilePos(currentTile,board))-1
                   moveHole('right');
               end
           end
           % move hole up to same row of current tile
           while row(holePos(board)) > row(tilePos(currentTile,board))
                   moveHole('up');
           end         
           if column(holePos(board)) > column(tilePos(currentTile,board))
               moveHole('left');
           else
               moveHole('right');
           end
       end
       % move last tile to under its position
       while row(tilePos(currentTile,board)) > cr+1
           moveHoleToRowColumn(row(tilePos(currentTile,board))+1,n-1)
           moveHole('up','up','right','down')
       end
       % move hole to underneath it
       moveHoleToRowColumn(cr+2,n)
       moveHole('up','up','left','down','right','down','left','up','up','right','down')
   end
end

%% PHASE 2
% 1. Use the technique in phase 1 to solve each row in turn, until there
%     are only two rows left.
% 2. Rotate the puzzle a quarter turn to the right. The left column of the
%     two rows becomes the top row now.
% 3. Use the technique in phase 1 to solve each row in turn, until there
%     are only two rows left. This means there is only a 2x2 square left to
%     solve.
% 4. Move the pieces in the remaining 2x2 square around until one piece is
%     positioned correctly, and the space is in the correct spot. The other
%     two tiles should automatically be correctly positioned as well.
% 5. If there are two tiles that need to be swapped, then this cannot be
%     done unless two other tiles are swapped as well. If there are two
%     identical tiles somewhere in the puzzle, then you will have to swap
%     them and solve the rest again.

% turn the board
for cc=1:n-2        % for all columns except last two columns
   cr = n;         % last row
   currentTile = cc+(cr-1)*n;
   % if tile not at correct position
   if tilePos(currentTile,board)~=currentTile %
       % if tile is not at last row, make it
       if row(tilePos(currentTile,board)) ~= n
           moveHoleToRowColumn(n,column(tilePos(currentTile,board)))
           moveHole('up')
       end
       while column(tilePos(currentTile,board)) ~= cc
           moveHoleToRowColumn(n-1,column(tilePos(currentTile,board)))
           moveHole('left','down','right')
       end
   end
   currentTile = cc+(cr-2)*n;
   % if tile not at correct position
   if tilePos(currentTile,board)~=currentTile
       % move hole toright if it might disturb other pieces
       if column(holePos(board))==cc
           moveHole('right');
       end
       if tilePos(currentTile,board)==currentTile
           continue
       end
       % tile is not at row n-1, make it
       if row(tilePos(currentTile,board)) ~= n-1
           moveHoleToRowColumn(n-1,column(tilePos(currentTile,board)))
           moveHole('down')
       end
       % move last tile to under its position
       while column(tilePos(currentTile,board)) ~= cc+1
           moveHoleToRowColumn(n,column(tilePos(currentTile,board)))
           moveHole('left','up','right')
       end
       % move hole to right side of it
       moveHoleToRowColumn(n,cc+2);moveHole('up')
       moveHole('left','left','down','right','up','right','down','left','left','up','right')
   end
end
% Last 2x2 square
count = 0;
while holePos(board)~=n*n || tilePos((n-1)*n,board)~=(n-1)*n
   if row(holePos(board))==n
       if column(holePos(board))==n
           moveHole('up')
       else
           moveHole('right')
       end
   else
       if column(holePos(board))==n
           moveHole('left')
       else
           moveHole('down')
       end
   end
   count = count+1;
   if count>10 % unsolvable
      break
   end
end
   function swap(x,y)
       xp = (board==x);
       yp = (board==y);
       board(xp) = y;
       board(yp) = x;
   end
   function moveHole(varargin)
       hp = find(board==N);
       for ii=1:nargin
           switch varargin{ii}
               case 'left'
                   hp = hp-1;
               case 'right'
                   hp = hp+1;
               case 'up'
                   hp = hp-n;
               case 'down'
                   hp = hp+n;
           end
           swap(N,board(hp))
           solution = [solution;board];
       end
   end
   function moveHoleToRowColumn(x,y)
       while row(holePos(board)) < x
           moveHole('down')
       end
       while row(holePos(board)) > x
           moveHole('up')
       end
       while column(holePos(board)) < y
           moveHole('right')
       end
       while column(holePos(board)) > y
           moveHole('left')
       end
   end
end