Beruflich Dokumente
Kultur Dokumente
clear all
flag=1;
ini=1;
estado={};
pila={};
memorias2={};
visitado={};
anterior={};
guarda={};
memorias2(ini)={puzInicial};
memorias(ini)={puzInicial};
visitado(ini)={puzInicial};
pila(ini)={puzInicial};
anterior(ini)={puzInicial};
fin=1;
cam=1;
caminos(cam)={puzInicial};
if pila{ini}==puzFinal
puzInicial
flag=2;
end
ultimo=0;
cam = cam+1;
iter=1;
fin=fin+1;
cont=0;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%555555555
while(flag==1)
for i=1:3
for j=1:3
if (puzInicial(i,j)==0)
x=i;
y=j;
end
end
end
puzInicial1=puzInicial;
puzInicial2=puzInicial;
puzInicial3=puzInicial;
puzInicial4=puzInicial;
temp=0;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%55
%mueve a la 11 a 12
temp = puzInicial1(1,2);
puzInicial1(1,2)=puzInicial1(1,1);
puzInicial1(1,1)=temp;
estado(1)={puzInicial1};
%mueve 11 a 21
temp = puzInicial2(1,1);
puzInicial2(1,1)=puzInicial2(2,1);
puzInicial2(2,1)=temp;
estado(2)={puzInicial2};
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%55
%mueve 13 a 12
temp = puzInicial1(1,3);
puzInicial1(1,3)=puzInicial1(1,2);
puzInicial1(1,2)=temp;
estado(1)={puzInicial1};
%mueve 13 a 23
temp = puzInicial2(1,3);
puzInicial2(1,3)=puzInicial2(2,3);
puzInicial2(2,3)=temp;
estado(2)={puzInicial2};
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%55
%mueve 31 a 21
temp = puzInicial1(3,1);
puzInicial1(3,1)=puzInicial1(2,1);
puzInicial1(2,1)=temp;
estado(1)={puzInicial1};
%mueve 31 a 32
temp = puzInicial2(3,1);
puzInicial2(3,1)=puzInicial2(3,2);
puzInicial2(3,2)=temp;
estado(2)={puzInicial2};
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%55
%mueve 33 a 23
temp = puzInicial1(3,3);
puzInicial1(3,3)=puzInicial1(2,3);
puzInicial1(2,3)=temp;
estado(1)={puzInicial1};
%mueve 33 a 32
temp = puzInicial2(3,3);
puzInicial2(3,3)=puzInicial2(3,2);
puzInicial2(3,2)=temp;
estado(2)={puzInicial2};
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%55
if((x==2)&&(y==1))%medio izquierda
%mueve 21 a 11
temp = puzInicial1(2,1);
puzInicial1(2,1)=puzInicial1(1,1);
puzInicial1(1,1)=temp;
estado(1)={puzInicial1};
%mueve 21 a 31
temp = puzInicial2(2,1);
puzInicial2(2,1)=puzInicial2(3,1);
puzInicial2(3,1)=temp;
estado(2)={puzInicial2};
%mueve 21 a 22
temp = puzInicial3(2,1);
puzInicial3(2,1)=puzInicial3(2,2);
puzInicial3(2,2)=temp;
estado(3)={puzInicial3};
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%55
if((x==2)&&(y==3))%medio derecha
%mueve 23 a 13
temp = puzInicial1(2,3);
puzInicial1(2,3)=puzInicial1(1,3);
puzInicial1(1,3)=temp;
estado(1)={puzInicial1};
%mueve 23 a 22
temp = puzInicial2(2,3);
puzInicial2(2,3)=puzInicial2(2,2);
puzInicial2(2,2)=temp;
estado(2)={puzInicial2};
%mueve 23 a 33
temp = puzInicial3(2,3);
puzInicial3(2,3)=puzInicial3(3,3);
puzInicial3(3,3)=temp;
estado(3)={puzInicial3};
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%55
if((x==1)&&(y==2))%medio arriba
%mueve 12 a 11
temp = puzInicial1(1,2);
puzInicial1(1,2)=puzInicial1(1,1);
puzInicial1(1,1)=temp;
estado(1)={puzInicial1};
%mueve 12 a 12
temp = puzInicial2(1,2);
puzInicial2(1,2)=puzInicial2(2,2);
puzInicial2(2,2)=temp;
estado(2)={puzInicial2};
%mueve 12 a 13
temp = puzInicial3(1,2);
puzInicial3(1,2)=puzInicial3(1,3);
puzInicial3(1,3)=temp;
estado(3)={puzInicial3};
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%55
if((x==3)&&(y==2))%medio abajo
%mueve 32 a 22
temp = puzInicial1(3,2);
puzInicial1(3,2)=puzInicial1(2,2);
puzInicial1(2,2)=temp;
estado(1)={puzInicial1};
%mueve 32 a 31
temp = puzInicial2(3,2);
puzInicial2(3,2)=puzInicial2(3,1);
puzInicial2(3,1)=temp;
estado(2)={puzInicial2};
%mueve 32 a 33
temp = puzInicial3(3,2);
puzInicial3(3,2)=puzInicial3(3,3);
puzInicial3(3,3)=temp;
estado(3)={puzInicial3};
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%55
if((x==2)&&(y==2))%centro
%mueve 22 a 12
temp = puzInicial1(2,2);
puzInicial1(2,2)=puzInicial1(1,2);
puzInicial1(1,2)=temp;
estado(1)={puzInicial1};
%mueve 22 a 21
temp = puzInicial2(2,2);
puzInicial2(2,2)=puzInicial2(2,1);
puzInicial2(2,1)=temp;
estado(2)={puzInicial2};
%mueve 22 a 32
temp = puzInicial3(2,2);
puzInicial3(2,2)=puzInicial3(3,2);
puzInicial3(3,2)=temp;
estado(3)={puzInicial3};
%mueve 22 a 23
temp = puzInicial4(2,2);
puzInicial4(2,2)=puzInicial3(2,3);
puzInicial4(2,3)=temp;
estado(4)={puzInicial4};
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%
t=length(estado);
en=length(memorias);
if fin ~=7
if iter==1
for jj=1:length(visitado(1))
anterior(jj)={visitado{jj}};
end
else
for jj=1:length(visitado{1})
anterior(jj)={visitado{1}{jj}};
end
end
for i=1:t
x=0;
estadoMat=estado{i};
for j=1:en
memoriasMat=memorias{j};
if estadoMat==memoriasMat
x=1;
break;
end
end
if x == 0
jj=jj+1;
anterior(jj)={estado{i}};
jj=jj-1;
ultimo = ultimo+1;
pila(ultimo)={anterior};
memorias2(cam)={[memorias2{iter} estado{i}]};
cam=cam+1;
end
end
%pob(ix,n)= randperm(m)
iter=iter+1;
for i=1:t
memorias{en+1}=estado{i};
en=length(memorias);
end
estado={};
visitado={};
anterior={};
soluc=pila{ultimo}{length(pila{ultimo})};
if soluc==puzFinal
flag=2;
celldisp(pila(ultimo))
else
ini=ini+1;
visitado(1)=pila(ultimo);
puzInicial=soluc;
fin = length(pila{ultimo});
pila{ultimo}={};
ultimo=ultimo-1;
end
else
iter=iter+1;
estado={};
visitado={};
anterior={};
soluc=pila{ultimo}{length(pila{ultimo})};
if soluc==puzFinal
flag=2;
celldisp(pila(ultimo))
else
ini=ini+1;
visitado(1)=pila(ultimo);
puzInicial=soluc;
fin = length(pila{ultimo});
pila{ultimo}={};
ultimo=ultimo-1;
end
end
end
function npuzzle(cmd)
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')
% 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.\n\n'...
'Developed by Per-Anders Ekstrm, 2003-2007 Facilia AB\n'...
'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!\n\n'...
'Start time: %s\n'...
'End time: %s\n\n'...
'Elapsed time: %d seconds\n'...
'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.
moveHoleToRowColumn(row(tilePos(currentTile,board))+1,column(tilePos(curren
tTile,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
moveHole('up','up','left','down','right','down','left','up','up','right','d
own')
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.
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