漢諾塔遊戲玩法介紹(攻略和編程實現)

漢諾塔遊戲玩法介紹(攻略和編程實現)

漢諾塔遊戲介紹

漢諾塔是根據一個傳說形成的數學問題。描述如下:有三根杆子 A、B、C 。 A 杆上 N 個 穿孔圓盤,盤的尺寸由下到上依次變小。要求按下列規則將所有圓盤移至 C 杆:

  • 每次只能移動一個圓盤
  • 大盤不能疊在小盤上面

可將圓盤臨時置於 B 杆,也可將從 A 杆移出的圓盤重新移回 A 杆,但都必須遵循上述兩條規則。問:如何移?最少要移動多少次?

最早發明這個問題的人是法國數學家愛德華·盧卡斯。傳說越南河內某間寺院有三根銀棒,上串 64 個金盤。寺院裏的僧侶依照一個古老的預言,以上述規則移動這些盤子。預言說當這些盤子移動完畢,世界就會滅亡。這個傳說叫做梵天寺之塔問題。但不知道是盧卡斯自創的這個傳說,還是他受他人啓發。

若傳說屬實,僧侶們需要 26412^{64}-1步才能完成這個任務,若他們每秒可完成一個盤子的移動,就需要 5849 億年才能完成。整個宇宙現在也不過 137 億年。

這個傳說有若干變體:寺院換成修道院、僧侶換成修士等等。寺院的地點衆說紛紜,其中一說是位於越南的河內,所以被命名爲“河內塔”。另外亦有“金盤是創世時所造”、“僧侶們每天移動一盤”之類的背景設定。

在這裏插入圖片描述

遞歸解法

這個遊戲,只要手機上下個 APP ,N 從小到大玩一會,也就知道其中的套路了。如果有一個盤,那麼直接將這個盤從 A 挪到 C即可。如果有兩個盤,需要先將小盤挪到 B,大盤挪到 C,再將小盤挪到 C,以此類推……

可以看到,解法的基本思想是遞歸。假設有 A、B、C 三個塔,A 塔有 N 塊盤,目標是把這些盤全部移到 C 塔。那麼先把 A 塔頂部的 N-1 塊盤移動到 B 塔,再把 A 塔剩下的大盤移到 C,最後把 B 塔的 N-1 塊盤移到 C。要先把 N-1 塊盤挪到B,就需要先把 N-2 塊盤挪到 C……如此遞歸地使用下去, 就可以求解。從這也可以看到需要總的步數爲 2N12^N-1

一個簡單的 MATLAB 代碼如下:

function hanoi2(n)
%a上原有盤數爲n的漢諾塔。
han(n,'a','b','c')
function han(n,a,b,c)
if n==1
ex(a,c)
else
han(n-1,a,c,b)
ex(a,c)
han(n-1,b,a,c)
end
function ex(a,b)
disp ([a '-->' b])

非遞歸算法

事實情況是,在現實生活中,給你這個遊戲,你總不能老想着遞歸的事情,來完成這個遊戲吧,對於腦子不靈光的同學,容易搞迷糊。所以,我們當遇到這個遊戲的時候,需要一條“黃金準則”,來指導我們完成這個遊戲。

我玩了兩個小時這個遊戲,琢磨出來一個準則,能夠在現實生活中指導我們完成這個遊戲,本質上還是遞歸,只不過有一些更好的理解方式。

方法如下,爲了描述的方便,我將盤從小到大從 1 開始依次編號。
[
在這裏插入圖片描述

  • 第一步:初始化。先判斷 N 是奇數還是偶數,如果是奇數,先挪一個盤到 C,如果是偶數,先挪一個盤到B。
  • 第二步:找 1 所在杆子,數出和 1 的連號數目(例: 123467 ,前 4 個和 1 依次相連,那麼連號爲 4),假設連號數目爲 k。
  • 第三步:找到 k+1 號盤所在的杆,把它挪到除 1 所在的杆之外的另外一個槓(不妨稱爲其他杆)。
  • 第四步,若 k+1 爲奇數,那麼將 1 挪到原 k+1 號盤所在的杆,否則,挪到現 k+1 號盤所在的杆(其它杆)。
  • 判斷是否結束,沒結束,回到第二步。

看起來比較麻煩,順幾遍就知道其中的奧妙了。根據我琢磨出來的這個算法,我也寫了個 MATLAB 程序如下:

%% 漢諾塔遊戲編程
function Hanoi()
clc
clear
close all
%% 參數設定和初始化
N = 3;
A = N:-1:1;
B = [];
C = [];
State = {A,B,C};
State_desc = {'A','B','C'};
%% 執行第一步
steps = 1;
if mod(N,2)==0
    State{2} = State{1}(end);
    disp(['Step' num2str(steps) ':' State_desc{1} '->' State_desc{2}]);
else
    State{3} = State{1}(end);
    disp(['Step' num2str(steps) ':' State_desc{1} '->' State_desc{3}]);
end
State{1}(end) = [];
show_state();


%%
while length(State{3})~=N %這是結束的標誌
    steps  = steps + 1;
    set_ind_contain_one = find_element(1,State{1},State{2},State{3});
    num_adj = num_adjacent(State{set_ind_contain_one});
    ele_move = num_adj+1;
    set_ind_contain_ele_move = find_element(ele_move,State{1},State{2},State{3});
    left_set_ind = setdiff(1:3, [set_ind_contain_one set_ind_contain_ele_move]) ;
    State{left_set_ind}(end+1) = State{set_ind_contain_ele_move}(end);
    State{set_ind_contain_ele_move}(end) = [];
    disp(['Step' num2str(steps) ':' State_desc{set_ind_contain_ele_move} '->' State_desc{left_set_ind}]);
    show_state();
    steps  = steps + 1;
    if mod(ele_move,2)==1
        State{set_ind_contain_ele_move}(end+1) = State{set_ind_contain_one}(end);
        State{set_ind_contain_one}(end) = [];
        disp(['Step' num2str(steps) ':' State_desc{set_ind_contain_one} '->' State_desc{set_ind_contain_ele_move}]);
        show_state();
    else 
        State{left_set_ind}(end+1) = State{set_ind_contain_one}(end);
        State{set_ind_contain_one}(end) = [];
        disp(['Step' num2str(steps) ':' State_desc{set_ind_contain_one} '->' State_desc{left_set_ind}]);
        show_state();
    end
    
end

    function show_state()
        disp(['      A=[' num2str(State{1}) ']']);
        disp(['      B=[' num2str(State{2}) ']']);
        disp(['      C=[' num2str(State{3})  ']']);
    end

end

function num = num_adjacent(S)
len = length(S);
diffS = S - (len:-1:1);
num = length(find(diffS==0));
end


function Set_ind = find_element(ele,A,B,C)
if ismember(ele,A)
    Set_ind = 1;
elseif ismember(ele,B)
    Set_ind = 2;
else
    Set_ind = 3;   
end

end




在這裏插入圖片描述

仿真和可視化界面

別人還做了這個遊戲的仿真和可視化界面,可以用來學習 MATLAB 的GUI。

在這裏插入圖片描述

對於的程序如下:

hf=figure('name','汗諾塔遊戲仿真');    %加標題
axis([0,12,0,12]);     %畫座標
set(hf,'color','w');       %填充背景
hold on;       %保持圖形
axis('off');       %隱藏網絡線
rectangle('position',[0,0,12,0.5],'FaceColor',[0,1.0,0]);    %畫底版
line([3;3],[0.5,8],'color','r','linestyle','-','linewidth',1.5);
line([6;6],[0.5,8],'color','r','linestyle','-','linewidth',1.5);
line([9;9],[0.5,8],'color','r','linestyle','-','linewidth',1.5);    %畫出三條路線
a=line([3;3],[0.5,1.0],'color','c','linestyle','-','linewidth',65); %畫出一號長方體木塊
b=line([3;3],[1.0,1.5],'color','b','linestyle','-','linewidth',45);%畫出二號長方體木塊
c=line([3;3],[1.5,2.0],'color','k','linestyle','-','linewidth',30); %畫出三號長方體木塊 
d=line([3;3],[2.0,2.5],'color','y','linestyle','-','linewidth',25);%畫出四號長方體木塊
 e=line([3;3],[2.5,3.0],'color','m','linestyle','-','linewidth',15);%畫出五號長方體木塊
   %設置五木板的運動
%設置五號長方體木塊的運動,豎直向上運動到第一條路線的最上方
t1=2.5;  dt=0.05;
while t1<=8
    t1=t1+dt;
    set(e,'xdata',[3;3],'ydata',[t1;t1+0.5]);
    drawnow;    
set(gcf,'doublebuffer','on');    %消除震動
end    
%設置五號長方體木塊的運動,水平運動到第三條路線的最上方
t2=3;   dt=0.05;
while t2<=9
    t2=t2+dt;
    set(e,'xdata',[t2;t2],'ydata',[t1;t1+0.5]);
    drawnow;     set(gcf,'doublebuffer','on');    %消除震動
end        
% 設置五號長方體木塊的運動,豎直向下運動到第三條路線的下方     
t3=8;   dt=0.05;
while t3>=0.5
    t3=t3-dt;
    set(e,'xdata',[9;9],'ydata',[t3;t3+0.5]);
    drawnow;     
set(gcf,'doublebuffer','on');    %消除震動
end           
%設置四號長方體木塊的運動,豎直向上運動到第一條路線的最上方
t4=2.0;   dt=0.05;
while t4<=8
    t4=t4+dt;
    set(d,'xdata',[3;3],'ydata',[t4;t4+0.5]);
    drawnow;    
set(gcf,'doublebuffer','on');    %消除震動
end           
 % 設置四號長方體木塊的運動,水平運動到第二條路線的最上方
t5=3;   dt=0.05;
while t5<=6
    t5=t5+dt;
    set(d,'xdata',[t5;t5],'ydata',[t4;t4+0.5]);
    drawnow;    set(gcf,'doublebuffer','on');    %消除震動
end     
 % 設置四號長方體木塊的運動,豎直向下運動到第二條路線的最下方       
t6=8;   dt=0.05;
while t6>=0.5
    t6=t6-dt;
    set(d,'xdata',[6;6],'ydata',[t6;t6+0.5]);
    drawnow;  
 set(gcf,'doublebuffer','on');    %消除震動
end        
 %設置五號長方體木塊的運動,豎直向上運動到第三條路線的最上方
t7=0.5;   dt=0.05;
while t7<=8
    t7=t7+dt;
    set(e,'xdata',[9;9],'ydata',[t7;t7+0.5]);
    drawnow;    
 set(gcf,'doublebuffer','on');    %消除震動
end        
% 設置五號長方體木塊的運動,水平運動到第二條路線的最上方   
t8=9;   dt=0.05;
while t8>=6
    t8=t8-dt;
    set(e,'xdata',[t8;t8],'ydata',[t7;t7+0.5]);
    drawnow;      
set(gcf,'doublebuffer','on');    %消除震動
end         
% 設置五號長方體木塊的運動,豎直向下運動到第二條路線的下方   
t9=8;    dt=0.05;
while t9>=1.0
    t9=t9-dt;
    set(e,'xdata',[6;6],'ydata',[t9;t9+0.5]);
    drawnow;   
set(gcf,'doublebuffer','on');    %消除震動
end           
 % 設置三號長方體木塊的運動,豎直向上運動到第一條路線的上方
t10=1.5;    dt=0.05;
while t10<=8
    t10=t10+dt;
    set(c,'xdata',[3;3],'ydata',[t10;t10+0.5]);
    drawnow;     
set(gcf,'doublebuffer','on');    %消除震動
end         
% 設置三號長方體木塊的運動,水平運動到第三條路線的上方
t11=3;    dt=0.05;
while t11<=9
    t11=t11+dt;
    set(c,'xdata',[t11;t11],'ydata',[t10;t10+0.5]);
    drawnow;    
set(gcf,'doublebuffer','on');    %消除震動
end         
  % 設置三號長方體木塊的運動,豎直向下運動到第三條路線的下方
t12=8;    dt=0.05;
while t12>=0.5
    t12=t12-dt;
    set(c,'xdata',[9;9],'ydata',[t12;t12+0.5]);
    drawnow;    
set(gcf,'doublebuffer','on');    %消除震動
end     
 % 設置五號長方體木塊的運動,豎直向上運動到第二條路線的上方    
t13=1;   dt=0.05;
while t13<=8
    t13=t13+dt;
    set(e,'xdata',[6;6],'ydata',[t13;t13+0.5]);
    drawnow;    
set(gcf,'doublebuffer','on');    %消除震動
end      
% 設置五號長方體木塊的運動,水平運動到第一條路線的最上方    
t14=6;   dt=0.05;
while t14>=3
    t14=t14-dt;
    set(e,'xdata',[t14;t14],'ydata',[8;8+0.5]);
    drawnow;
   set(gcf,'doublebuffer','on');    %消除震動
end           
% 設置五號長方體木塊的運動,豎直向下運動到第一條路線的下方
t15=8;   dt=0.05;
while t15>=1.5
    t15=t15-dt;
    set(e,'xdata',[3;3],'ydata',[t15;t15+0.5]);
    drawnow; 
  set(gcf,'doublebuffer','on');    %消除震動
end      
% 設置四號長方體木塊的運動,豎直向上運動到第二條路線的上方     
t16=0.5;  dt=0.05;
while t16<=8
    t16=t16+dt;
    set(d,'xdata',[6;6],'ydata',[t16;t16+0.5]);
    drawnow;   
 set(gcf,'doublebuffer','on');    %消除震動
end           
% 設置四號長方體木塊的運動,水平運動到第三條路線的上方
t17=6;   dt=0.05;
while t17<=9
    t17=t17+dt;
    set(d,'xdata',[t17;t17],'ydata',[8;8.5]);
    drawnow;
    set(gcf,'doublebuffer','on');    %消除震動
end     
% 設置四號長方體木塊的運動,豎直向下運動到第三條路線的下方     
t18=8;dt=0.05;
while t18>=1
    t18=t18-dt;
    set(d,'xdata',[9;9],'ydata',[t18;t18+0.5]);
    drawnow; 
set(gcf,'doublebuffer','on');    %消除震動
end          
% 設置五號長方體木塊的運動,豎直向上運動到第一條路線的上方
t19=1.0;dt=0.05;
while t19<=8
    t19=t19+dt;
    set(e,'xdata',[3;3],'ydata',[t19;t19+0.5]);
    drawnow;
set(gcf,'doublebuffer','on');    %消除震動
end          
  % 設置五號長方體木塊的運動,水平運動到第三條路線的上方
t20=3;dt=0.05;
while t20<=9
    t20=t20+dt;
    set(e,'xdata',[t20;t20],'ydata',[8;8.5]);
    drawnow; 
set(gcf,'doublebuffer','on');    %消除震動
end     
% 設置五號長方體木塊的運動,豎直向下運動到第三條路線的下方
t21=8; dt=0.05;
while t21>=1.5
    t21=t21-dt;
    set(e,'xdata',[9;9],'ydata',[t21;t21+0.5]);
    drawnow;
    set(gcf,'doublebuffer','on');    %消除震動
end   
% 設置二號長方體木塊的運動,豎直向上運動到第一條路線的上方
t22=1.0;  dt=0.05;
while t22<=8
    t22=t22+dt;
    set(b,'xdata',[3;3],'ydata',[t22;t22+0.5]);
    drawnow;    
set(gcf,'doublebuffer','on');    %消除震動
end    
% 設置二號長方體木塊的運動,水平運動到第二條路線的上方
t23=3;   dt=0.05;
while t23<=6
    t23=t23+dt;
    set(b,'xdata',[t23;t23],'ydata',[t22;t22+0.5]);
    drawnow;     set(gcf,'doublebuffer','on');    %消除震動
end        
% 設置二號長方體木塊的運動,豎直向下運動到第二條路線的最下方     
t24=8;   dt=0.05;
while t24>=0.5
    t24=t24-dt;
    set(b,'xdata',[6;6],'ydata',[t24;t24+0.5]);
    drawnow;     
set(gcf,'doublebuffer','on');    %消除震動
end         
% 設置五號長方體木塊的運動,豎直向上運動到第三條路線的上方
t25=1.5;  dt=0.05;
while t25<=8
    t25=t25+dt;
    set(e,'xdata',[9;9],'ydata',[t25;t25+0.5]);
    drawnow;    
set(gcf,'doublebuffer','on');    %消除震動
end    
% 設置五號長方體木塊的運動,水平運動到第二條路線的上方
t26=9;   dt=0.05;
while t26>=6
    t26=t26-dt;
    set(e,'xdata',[t26;t26],'ydata',[t25;t25+0.5]);
    drawnow;     set(gcf,'doublebuffer','on');    %消除震動
end        
% 設置五號長方體木塊的運動,豎直向下運動到第二條路線的下方     
t27=8;   dt=0.05;
while t27>=1.0
    t27=t27-dt;
    set(e,'xdata',[6;6],'ydata',[t27;t27+0.5]);
    drawnow;     
set(gcf,'doublebuffer','on');    %消除震動
end        
% 設置四號長方體木塊的運動,豎直向上運動到第三條路線的上方
t28=1.5;  dt=0.05;
while t28<=8
    t28=t28+dt;
    set(d,'xdata',[9;9],'ydata',[t28;t28+0.5]);
    drawnow;    
set(gcf,'doublebuffer','on');    %消除震動
end 
% 設置四號長方體木塊的運動,水平運動到第一條路線的上方
t29=9;   dt=0.05;
while t29>=3
    t29=t29-dt;
    set(d,'xdata',[t29;t29],'ydata',[t28;t28+0.5]);
    drawnow;     set(gcf,'doublebuffer','on');    %消除震動
end        
% 設置四號長方體木塊的運動,豎直向下運動到第一條路線的下方     
t30=8;   dt=0.05;
while t30>=1.0
    t30=t30-dt;
    set(d,'xdata',[3;3],'ydata',[t30;t30+0.5]);
    drawnow;     
set(gcf,'doublebuffer','on');    %消除震動
end  
% 設置五號長方體木塊的運動,豎直向上運動到第二條路線的上方
t31=1.0;  dt=0.05;
while t31<=8
    t31=t31+dt;
    set(e,'xdata',[6;6],'ydata',[t31;t31+0.5]);
    drawnow;    
set(gcf,'doublebuffer','on');    %消除震動
end    
% 設置五號長方體木塊的運動,水平運動到第一條路線的上方
t32=6;   dt=0.05;
while t32>=3
    t32=t32-dt;
    set(e,'xdata',[t32;t32],'ydata',[t31;t31+0.5]);
    drawnow;     set(gcf,'doublebuffer','on');    %消除震動
end        
% 設置五號長方體木塊的運動,豎直向下運動到第一條路線的下方     
t33=8;   dt=0.05;
while t33>=1.5
    t33=t33-dt;
    set(e,'xdata',[3;3],'ydata',[t33;t33+0.5]);
    drawnow;     
set(gcf,'doublebuffer','on');    %消除震動
end  
% 設置三號長方體木塊的運動,豎直向上運動到第三條路線的上方
t34=0.5;  dt=0.05;
while t34<=8
    t34=t34+dt;
    set(c,'xdata',[9;9],'ydata',[t34;t34+0.5]);
    drawnow;    
set(gcf,'doublebuffer','on');    %消除震動
end    
% 設置三號長方體木塊的運動,水平運動到第二條路線的上方
t35=9;   dt=0.05;
while t35>=6
    t35=t35-dt;
    set(c,'xdata',[t35;t35],'ydata',[t34;t34+0.5]);
    drawnow;     set(gcf,'doublebuffer','on');    %消除震動
end        
% 設置三號長方體木塊的運動,豎直向下運動到第二條路線的下方     
t36=8;   dt=0.05;
while t36>=1.0
    t36=t36-dt;
    set(c,'xdata',[6;6],'ydata',[t36;t36+0.5]);
    drawnow;     
set(gcf,'doublebuffer','on');    %消除震動
end     
% 設置五號長方體木塊的運動,豎直向上運動到第三條路線的上方
t37=1.5;  dt=0.05;
while t37<=8
    t37=t37+dt;
    set(e,'xdata',[3;3],'ydata',[t37;t37+0.5]);
    drawnow;    
set(gcf,'doublebuffer','on');    %消除震動
end    
%設置五號長方體木塊的運動,水平運動到第三條路線的最上方
t38=3;   dt=0.05;
while t38<=9
    t38=t38+dt;
    set(e,'xdata',[t38;t38],'ydata',[t37;t37+0.5]);
    drawnow;     set(gcf,'doublebuffer','on');    %消除震動
end        
% 設置五號長方體木塊的運動,豎直向下運動到第三條路線的下方     
t39=8;   dt=0.05;
while t39>=0.5
    t39=t39-dt;
    set(e,'xdata',[9;9],'ydata',[t39;t39+0.5]);
    drawnow;     
set(gcf,'doublebuffer','on');    %消除震動
end  
% 設置四號長方體木塊的運動,豎直向上運動到第二條路線的上方
t40=2.5;  dt=0.05;
while t40<=8
    t40=t40+dt;
    set(d,'xdata',[3;3],'ydata',[t40;t40+0.5]);
    drawnow;    
set(gcf,'doublebuffer','on');    %消除震動
end    
%設置四號長方體木塊的運動,水平運動到第二條路線的最上方
t41=3;   dt=0.05;
while t41<=6
    t41=t41+dt;
    set(d,'xdata',[t41;t41],'ydata',[t40;t40+0.5]);
    drawnow;     set(gcf,'doublebuffer','on');    %消除震動
end        
% 設置四號長方體木塊的運動,豎直向下運動到第二條路線的下方     
t42=8;   dt=0.05;
while t42>=1.5
    t42=t42-dt;
    set(d,'xdata',[6;6],'ydata',[t42;t42+0.5]);
    drawnow;     
set(gcf,'doublebuffer','on');    %消除震動
end  
% 設置五號長方體木塊的運動,豎直向上運動到第三條路線的上方
t43=0.5;  dt=0.05;
while t43<=8
    t43=t43+dt;
    set(e,'xdata',[9;9],'ydata',[t43;t43+0.5]);
    drawnow;    
set(gcf,'doublebuffer','on');    %消除震動
end    
%設置五號長方體木塊的運動,水平運動到第二條路線的最上方
t44=9;   dt=0.05;
while t44>=6
    t44=t44-dt;
    set(e,'xdata',[t44;t44],'ydata',[t43;t43+0.5]);
    drawnow;     set(gcf,'doublebuffer','on');    %消除震動
end        
% 設置五號長方體木塊的運動,豎直向下運動到第二條路線的下方     
t45=8;   dt=0.05;
while t45>=2.0
    t45=t45-dt;
    set(e,'xdata',[6;6],'ydata',[t45;t45+0.5]);
    drawnow;     
set(gcf,'doublebuffer','on');    %消除震動
end    
% 設置一號長方體木塊的運動,豎直向上運動到第一條路線的上方
t46=0.5;  dt=0.05;
while t46<=8
    t46=t46+dt;
    set(a,'xdata',[3;3],'ydata',[t46;t46+0.5]);
    drawnow;    
set(gcf,'doublebuffer','on');    %消除震動
end    
%設置一號長方體木塊的運動,水平運動到第三條路線的最上方
t47=3;   dt=0.05;
while t47<=9
    t47=t47+dt;
    set(a,'xdata',[t47;t47],'ydata',[t46;t46+0.5]);
    drawnow;     set(gcf,'doublebuffer','on');    %消除震動
end        
% 設置一號長方體木塊的運動,豎直向下運動到第三條路線的最下方     
t48=8;   dt=0.05;
while t48>=0.5
    t48=t48-dt;
    set(a,'xdata',[9;9],'ydata',[t48;t48+0.5]);
    drawnow;     
set(gcf,'doublebuffer','on');    %消除震動
end     
% 設置五號長方體木塊的運動,豎直向上運動到第二條路線的上方
t49=2.0;  dt=0.05;
while t49<=8
    t49=t49+dt;
    set(e,'xdata',[6;6],'ydata',[t49;t49+0.5]);
    drawnow;    
set(gcf,'doublebuffer','on');    %消除震動
end    
%設置五號長方體木塊的運動,水平運動到第一條路線的最上方
t50=6;   dt=0.05;
while t50>=3
    t50=t50-dt;
    set(e,'xdata',[t50;t50],'ydata',[t49;t49+0.5]);
    drawnow;     set(gcf,'doublebuffer','on');    %消除震動
end        
% 設置五號長方體木塊的運動,豎直向下運動到第一條路線的最下方     
t51=8;   dt=0.05;
while t51>=0.5
    t51=t51-dt;
    set(e,'xdata',[3;3],'ydata',[t51;t51+0.5]);
    drawnow;     
set(gcf,'doublebuffer','on');    %消除震動
end     
% 設置四號長方體木塊的運動,豎直向上運動到第二條路線的上方
t52=1.5;  dt=0.05;
while t52<=8
    t52=t52+dt;
    set(d,'xdata',[6;6],'ydata',[t52;t52+0.5]);
    drawnow;    
set(gcf,'doublebuffer','on');    %消除震動
end    
%設置四號長方體木塊的運動,水平運動到第三條路線的最上方
t53=6;   dt=0.05;
while t53<=9
    t53=t53+dt;
    set(d,'xdata',[t53;t53],'ydata',[t52;t52+0.5]);
    drawnow;     set(gcf,'doublebuffer','on');    %消除震動
end        
% 設置四號長方體木塊的運動,豎直向下運動到第三條路線的下方     
t54=8;   dt=0.05;
while t54>=1.0
    t54=t54-dt;
    set(d,'xdata',[9;9],'ydata',[t54;t54+0.5]);
    drawnow;     
set(gcf,'doublebuffer','on');    %消除震動
end  
% 設置五號長方體木塊的運動,豎直向上運動到第一條路線的上方
t55=0.5;  dt=0.05;
while t55<=8
    t55=t55+dt;
    set(e,'xdata',[3;3],'ydata',[t55;t55+0.5]);
    drawnow;    
set(gcf,'doublebuffer','on');    %消除震動
end    
%設置五號長方體木塊的運動,水平運動到第三條路線的最上方
t56=3;   dt=0.05;
while t56<=9
    t56=t56+dt;
    set(e,'xdata',[t56;t56],'ydata',[t55;t55+0.5]);
    drawnow;     set(gcf,'doublebuffer','on');    %消除震動
end        
% 設置五號長方體木塊的運動,豎直向下運動到第三條路線的下方     
t57=8;   dt=0.05;
while t57>=1.5
    t57=t57-dt;
    set(e,'xdata',[9;9],'ydata',[t57;t57+0.5]);
    drawnow;     
set(gcf,'doublebuffer','on');    %消除震動
end  
% 設置三號長方體木塊的運動,豎直向上運動到第二條路線的最上方
t58=1.0;  dt=0.05;
while t58<=8
    t58=t58+dt;
    set(c,'xdata',[6;6],'ydata',[t58;t58+0.5]);
    drawnow;    
set(gcf,'doublebuffer','on');    %消除震動
end    
%設置三號長方體木塊的運動,水平運動到第一條路線的最上方
t59=6;   dt=0.05;
while t59>=3
    t59=t59-dt;
    set(c,'xdata',[t59;t59],'ydata',[t58;t58+0.5]);
    drawnow;     set(gcf,'doublebuffer','on');    %消除震動
end        
% 設置三號長方體木塊的運動,豎直向下運動到第一條路線的最下方     
t60=8;   dt=0.05;
while t60>=0.5
    t60=t60-dt;
    set(c,'xdata',[3;3],'ydata',[t60;t60+0.5]);
    drawnow;     
set(gcf,'doublebuffer','on');    %消除震動
end  
% 設置五號長方體木塊的運動,豎直向上運動到第三條路線的上方
t61=1.5;  dt=0.05;
while t61<=8
    t61=t61+dt;
    set(e,'xdata',[9;9],'ydata',[t61;t61+0.5]);
    drawnow;    
set(gcf,'doublebuffer','on');    %消除震動
end    
%設置五號長方體木塊的運動,水平運動到第二條路線的最上方
t62=9;   dt=0.05;
while t62>=6
    t62=t62-dt;
    set(e,'xdata',[t62;t62],'ydata',[t61;t61+0.5]);
    drawnow;     set(gcf,'doublebuffer','on');    %消除震動
end        
% 設置五號長方體木塊的運動,豎直向下運動到第二條路線的下方     
t63=8;   dt=0.05;
while t63>=1.0
    t63=t63-dt;
    set(e,'xdata',[6;6],'ydata',[t63;t63+0.5]);
    drawnow;     
set(gcf,'doublebuffer','on');    %消除震動
end  
% 設置四號長方體木塊的運動,豎直向上運動到第三條路線的最上方
t64=1.0;  dt=0.05;
while t64<=8
    t64=t64+dt;
    set(d,'xdata',[9;9],'ydata',[t64;t64+0.5]);
    drawnow;    
set(gcf,'doublebuffer','on');    %消除震動
end    
%設置四號長方體木塊的運動,水平運動到第一條路線的最上方
t65=9;   dt=0.05;
while t65>=3
    t65=t65-dt;
    set(d,'xdata',[t65;t65],'ydata',[t64;t64+0.5]);
    drawnow;     set(gcf,'doublebuffer','on');    %消除震動
end        
% 設置四號長方體木塊的運動,豎直向下運動到第一條路線的下方     
t66=8;   dt=0.05;
while t66>=1.0
    t66=t66-dt;
    set(d,'xdata',[3;3],'ydata',[t66;t66+0.5]);
    drawnow;     
set(gcf,'doublebuffer','on');    %消除震動
end 
% 設置五號長方體木塊的運動,豎直向上運動到第二條路線的最上方
t67=1.0;  dt=0.05;
while t67<=8
    t67=t67+dt;
    set(e,'xdata',[6;6],'ydata',[t67;t67+0.5]);
    drawnow;    
set(gcf,'doublebuffer','on');    %消除震動
end    
%設置五號長方體木塊的運動,水平運動到第一條路線的最上方
t68=6;   dt=0.05;
while t68>=3
    t68=t68-dt;
    set(e,'xdata',[t68;t68],'ydata',[t67;t67+0.5]);
    drawnow;     set(gcf,'doublebuffer','on');    %消除震動
end        
% 設置五號長方體木塊的運動,豎直向下運動到第一條路線的下方     
t69=8;   dt=0.05;
while t69>=1.5
    t69=t69-dt;
    set(e,'xdata',[3;3],'ydata',[t69;t69+0.5]);
    drawnow;     
set(gcf,'doublebuffer','on');    %消除震動
end 
% 設置二號長方體木塊的運動,豎直向上運動到第二條路線的上方
t70=0.5;  dt=0.05;
while t70<=8
    t70=t70+dt;
    set(b,'xdata',[6;6],'ydata',[t70;t70+0.5]);
    drawnow;    
set(gcf,'doublebuffer','on');    %消除震動
end    
%設置二號長方體木塊的運動,水平運動到第三條路線的最上方
t71=6;   dt=0.05;
while t71<=9
    t71=t71+dt;
    set(b,'xdata',[t71;t71],'ydata',[t70;t70+0.5]);
    drawnow;     set(gcf,'doublebuffer','on');    %消除震動
end        
% 設置二號長方體木塊的運動,豎直向下運動到第三條路線的最下方     
t72=8;   dt=0.05;
while t72>=1.0
    t72=t72-dt;
    set(b,'xdata',[9;9],'ydata',[t72;t72+0.5]);
    drawnow;     
set(gcf,'doublebuffer','on');    %消除震動
end  
% 設置五號長方體木塊的運動,豎直向上運動到第一條路線的最上方
t73=1.5;  dt=0.05;
while t73<=8
    t73=t73+dt;
    set(e,'xdata',[3;3],'ydata',[t73;t73+0.5]);
    drawnow;    
set(gcf,'doublebuffer','on');    %消除震動
end    
%設置五號長方體木塊的運動,水平運動到第三條路線的最上方
t74=3;   dt=0.05;
while t74<=9
    t74=t74+dt;
    set(e,'xdata',[t74;t74],'ydata',[t73;t73+0.5]);
    drawnow;     set(gcf,'doublebuffer','on');    %消除震動
end        
% 設置五號長方體木塊的運動,豎直向下運動到第三條路線的最下方     
t75=8;   dt=0.05;
while t75>=1.5
    t75=t75-dt;
    set(e,'xdata',[9;9],'ydata',[t75;t75+0.5]);
    drawnow;     
set(gcf,'doublebuffer','on');    %消除震動
end           
%設置四號長方體木塊的運動,豎直向上運動到第一條路線的最上方
t76=1.0;   dt=0.05;
while t76<=8
    t76=t76+dt;
    set(d,'xdata',[3;3],'ydata',[t76;t76+0.5]);
    drawnow;    
set(gcf,'doublebuffer','on');    %消除震動
end           
 % 設置四號長方體木塊的運動,水平運動到第二條路線的最上方
t77=3;   dt=0.05;
while t77<=6
    t77=t77+dt;
    set(d,'xdata',[t77;t77],'ydata',[t76;t76+0.5]);
    drawnow;    set(gcf,'doublebuffer','on');    %消除震動
end     
 % 設置四號長方體木塊的運動,豎直向下運動到第二條路線的最下方       
t78=8;   dt=0.05;
while t78>=0.5
    t78=t78-dt;
    set(d,'xdata',[6;6],'ydata',[t78;t78+0.5]);
    drawnow;  
 set(gcf,'doublebuffer','on');    %消除震動
end        
 %設置五號長方體木塊的運動,豎直向上運動到第三條路線的最上方
t79=2.0;   dt=0.05;
while t79<=8
    t79=t79+dt;
    set(e,'xdata',[9;9],'ydata',[t79;t79+0.5]);
    drawnow;    
 set(gcf,'doublebuffer','on');    %消除震動
end        
% 設置五號長方體木塊的運動,水平運動到第二條路線的最上方   
t80=9;   dt=0.05;
while t80>=6
    t80=t80-dt;
    set(e,'xdata',[t80;t80],'ydata',[t79;t79+0.5]);
    drawnow;      
set(gcf,'doublebuffer','on');    %消除震動
end         
% 設置五號長方體木塊的運動,豎直向下運動到第二條路線的下方   
t81=8;    dt=0.05;
while t81>=1.0
    t81=t81-dt;
    set(e,'xdata',[6;6],'ydata',[t81;t81+0.5]);
    drawnow;   
set(gcf,'doublebuffer','on');    %消除震動
end           
 % 設置三號長方體木塊的運動,豎直向上運動到第一條路線的上方
t82=0.5;    dt=0.05;
while t82<=8
    t82=t82+dt;
    set(c,'xdata',[3;3],'ydata',[t82;t82+0.5]);
    drawnow;     
set(gcf,'doublebuffer','on');    %消除震動
end         
% 設置三號長方體木塊的運動,水平運動到第三條路線的上方
t83=3;    dt=0.05;
while t83<=9
    t83=t83+dt;
    set(c,'xdata',[t83;t83],'ydata',[t82;t82+0.5]);
    drawnow;    
set(gcf,'doublebuffer','on');    %消除震動
end         
  % 設置三號長方體木塊的運動,豎直向下運動到第三條路線的下方
t84=8;    dt=0.05;
while t84>=1.5
    t84=t84-dt;
    set(c,'xdata',[9;9],'ydata',[t84;t84+0.5]);
    drawnow;    
set(gcf,'doublebuffer','on');    %消除震動
end     
 % 設置五號長方體木塊的運動,豎直向上運動到第二條路線的上方    
t85=1;   dt=0.05;
while t85<=8
    t85=t85+dt;
    set(e,'xdata',[6;6],'ydata',[t85;t85+0.5]);
    drawnow;    
set(gcf,'doublebuffer','on');    %消除震動
end      
% 設置五號長方體木塊的運動,水平運動到第一條路線的最上方    
t86=6;   dt=0.05;
while t86>=3
    t86=t86-dt;
    set(e,'xdata',[t86;t86],'ydata',[8;8+0.5]);
    drawnow;
   set(gcf,'doublebuffer','on');    %消除震動
end           
% 設置五號長方體木塊的運動,豎直向下運動到第一條路線的下方
t87=8;   dt=0.05;
while t87>=0.5
    t87=t87-dt;
    set(e,'xdata',[3;3],'ydata',[t87;t87+0.5]);
    drawnow; 
  set(gcf,'doublebuffer','on');    %消除震動
end      
% 設置四號長方體木塊的運動,豎直向上運動到第二條路線的上方     
t88=0.5;  dt=0.05;
while t88<=8
    t88=t88+dt;
    set(d,'xdata',[6;6],'ydata',[t88;t88+0.5]);
    drawnow;   
 set(gcf,'doublebuffer','on');    %消除震動
end           
% 設置四號長方體木塊的運動,水平運動到第三條路線的上方
t89=6;   dt=0.05;
while t89<=9
    t89=t89+dt;
    set(d,'xdata',[t89;t89],'ydata',[8;8.5]);
    drawnow;
    set(gcf,'doublebuffer','on');    %消除震動
end     
% 設置四號長方體木塊的運動,豎直向下運動到第三條路線的下方     
t90=8;dt=0.05;
while t90>=2.0
    t90=t90-dt;
    set(d,'xdata',[9;9],'ydata',[t90;t90+0.5]);
    drawnow; 
set(gcf,'doublebuffer','on');    %消除震動
end          
% 設置五號長方體木塊的運動,豎直向上運動到第一條路線的上方
t91=0.5;dt=0.05;
while t91<=8
    t91=t91+dt;
    set(e,'xdata',[3;3],'ydata',[t91;t91+0.5]);
    drawnow;
set(gcf,'doublebuffer','on');    %消除震動
end          
  % 設置五號長方體木塊的運動,水平運動到第三條路線的上方
t92=3;dt=0.05;
while t92<=9
    t92=t92+dt;
    set(e,'xdata',[t92;t92],'ydata',[8;8.5]);
    drawnow; 
set(gcf,'doublebuffer','on');    %消除震動
end     
% 設置五號長方體木塊的運動,豎直向下運動到第三條路線的下方
t93=8; dt=0.05;
while t93>=2.5
    t93=t93-dt;
    set(e,'xdata',[9;9],'ydata',[t93;t93+0.5]);
    drawnow;
    set(gcf,'doublebuffer','on');    %消除震動
end   




在這裏插入圖片描述
對應的程序如下:

function hano_auto(level)
if nargin < 1
   level=6;
end
hold on,axis equal
axis(0.5+[0,120,0,60])
set(gca,'xtick',[],'ytick',[],'xcolor','w','ycolor','w')
set(gca,'color','k')
ground=[120.5,1.5;120.5,0.5;0.5,0.5;0.5,1.5];
column_1=[21,1.5;21,44;19,44;19,1.5];
column_2=[61,1.5;61,44;59,44;59,1.5];
column_3=[101,1.5;101,44;99,44;99,1.5];
step=0;
arrow=[1];k=1.5;control=1;
A=[];B=[];C=[];
A=level:-1:1;
block_1=@(l,h)[20+2*l,3*h-1.5;20+2*l,3*h+1.5;20-2*l,3*h+1.5;20-2*l,3*h-1.5];
block_2=@(l,h)[60+2*l,3*h-1.5;60+2*l,3*h+1.5;60-2*l,3*h+1.5;60-2*l,3*h-1.5];
block_3=@(l,h)[100+2*l,3*h-1.5;100+2*l,3*h+1.5;100-2*l,3*h+1.5;100-2*l,3*h-1.5];
block__=@(l,p)[p+2*l,45-1.5;p+2*l,45+1.5;p-2*l,45+1.5;p-2*l,45-1.5];
set(gcf,'tag','co','CloseRequestFcn',@clo);
    function clo(~,~)
        control=0;
        delete(findobj('tag','co'));
        clf
        close
    end 


    function draw(~,~)
        delete(findobj(gcf,'type','text'))
        delete(findobj(gcf,'type','patch'))
        text(5,-4,'step=')
        text(20,-4,num2str(step))
        text(5,-10,'level=')
        text(20,-10,num2str(level))
        text(34,-4,'use the key(\leftarrow \rightarrow) to move the claw')
        text(34,-10,'use the key(\uparrow \downarrow) to pick or land the block')
        fill(ground(:,1),ground(:,2),'w','EdgeColor','none')
        fill(column_1(:,1),column_1(:,2),'w','EdgeColor','none')
        fill(column_2(:,1),column_2(:,2),'w','EdgeColor','none')
        fill(column_3(:,1),column_3(:,2),'w','EdgeColor','none')
        text(40*arrow(1)-20-2,55,'\downarrow','Color','w','Fontsize',25)
        if length(arrow)==2
            p=40*arrow(1)-20;
            block=block__(arrow(2),p);
            fill(block(:,1),block(:,2),'w','EdgeColor','none')  
        end
        for i=1:length(A)
            block=block_1(A(i),k*i);
            fill(block(:,1),block(:,2),'w','EdgeColor','none')   
        end
        for i=1:length(B)
            block=block_2(B(i),k*i);
            fill(block(:,1),block(:,2),'w','EdgeColor','none')   
        end
        for i=1:length(C)
            block=block_3(C(i),k*i);
            fill(block(:,1),block(:,2),'w','EdgeColor','none')   
        end
        if length(C)==level
            pause(0.2)
            buttonName1=questdlg('Congratulations! You win','you win','close','restart','next level','close');
            if isempty(buttonName1)
                buttonName1='end';
            end
            if strcmp(buttonName1,'restart')
                hano_auto(level)
            end
            if strcmp(buttonName1,'close')
                close;
            end
            if strcmp(buttonName1,'next level')
                if level<10
                    hano_auto(level+1)
                end
                if level==10
                    msgbox('it is already the highest level')
                end
            end
        end
    end

   function key(event)
   switch event
       case 'leftarrow'
           if arrow(1)-1~=0
               arrow(1)=arrow(1)-1;step=step+1;
           end
       case 'rightarrow'
           if arrow(1)-3~=0
               arrow(1)=arrow(1)+1;step=step+1;
           end
       case 'uparrow'
           if length(arrow)==1
               if (arrow(1)==1)&&(~isempty(A))
                   arrow=[arrow(1),A(end)];
                   A(end)=[];
               end
               if (arrow(1)==2)&&(~isempty(B))
                   arrow=[arrow(1),B(end)];
                   B(end)=[];
               end
               if (arrow(1)==3)&&(~isempty(C))
                   arrow=[arrow(1),C(end)];
                   C(end)=[];
               end
           end
       case 'downarrow'
           if length(arrow)==2
               if (arrow(1)==1)
                   if isempty(A)
                       A=[A,arrow(2)];
                       arrow(2)=[];
                   else
                       if A(end)>arrow(2)
                           A=[A,arrow(2)];
                           arrow(2)=[];
                       end
                   end
               end
               if (arrow(1)==2)
                   if isempty(B)
                       B=[B,arrow(2)];
                       arrow(2)=[];
                   else
                       if B(end)>arrow(2)
                           B=[B,arrow(2)];
                           arrow(2)=[];
                       end
                   end           
               end
               if (arrow(1)==3)
                   if isempty(C)
                       C=[C,arrow(2)];
                       arrow(2)=[];
                   else
                       if C(end)>arrow(2)
                           C=[C,arrow(2)];
                           arrow(2)=[];
                       end
                   end
               end
           end
   end
   pause(0.2)
   if control==1
       draw()
   else
       pause
   end
   end
draw()
matrix=[1 2 3];
digui(level,matrix)
    function digui(n,structdigui)
            if n==1
                move(structdigui(1),structdigui(3));
            else
                digui(n-1,[structdigui(1),structdigui(3),structdigui(2)])
                move(structdigui(1),structdigui(3))
                digui(n-1,[structdigui(2),structdigui(1),structdigui(3)])
            end
    end
    function move(a,b)
        while arrow(1)~=a
            if arrow(1)>a
                key('leftarrow')
            end
            if arrow(1)<a
                key('rightarrow')
            end
        end
        key('uparrow')
        while arrow(1)~=b
            if arrow(1)>b
                key('leftarrow')
            end
            if arrow(1)<b
                key('rightarrow')
            end
        end
        key('downarrow')
    end
        

end

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章