Sie sind auf Seite 1von 20

clc

clear all

disp('Ingresa la matriz del puzzle.');

puzInicial=input('Puzzle inicial = ')

puzFinal=input('Puzzle final = ')

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

disp('La solucion es:');

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

if ((x==1)&&(y==1))%esquina izquierda superior

%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

if((x==1)&&(y==3))%esquina derecha superior

%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

if((x==3)&&(y==1))%esquina izquierda inferior

%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

if((x==3)&&(y==3))%ezquina derecha inferior

%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')

% 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.\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.

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(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

% 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','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.

% 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

Das könnte Ihnen auch gefallen