三阶魔方自动求解及动态可视化matlab代码

这篇博客介绍了使用MATLAB实现三阶魔方的自动求解和动态可视化过程,包括魔方状态表示、旋转行为定义、随机打乱和逆序恢复、公式恢复算法。作者通过编写函数对魔方的每一步旋转进行建模,并实现了动态显示魔方旋转的动画。虽然目前的算法仍需改进以减少旋转步数,但已能成功完成魔方的还原。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

三阶魔方自动求解及动态可视化matlab代码


第一次写博客,想总结分享下以前做过的一些有趣的东西,目的是为了回望过去与展望未来,同时为了提高自己的写作表达能力。

思路与步骤

  1. 三阶魔方有6个面,每个面有 3 × 3 3\times3 3×3小块,用一个 6 × 3 × 3 6\times3\times3 6×3×3的矩阵来保存魔方的状态;
  2. 定义4+12种魔方旋转行为:整体旋转(左右上下共4种方式AaCc),侧面(6个侧面顺逆时针旋转共12种方式LlRrUuDdFfBb),旋转可视化界面方便调试(三维小面作图fill3创建 6 × 3 × 3 = 54 6\times3\times3=54 6×3×3=54个小面对象,对象成员属性包括颜色和4个三维坐标点,定义了全局函数对小面进行绕轴旋转操作,如此可以可视化调试,确保程序是按人想法运行),旋转行为改变矩阵的状态矩阵;
  3. 定义随机打乱和逆序恢复的函数,测试确保人为给出旋转公式,魔方能正确旋转;
  4. 编写按公式恢复魔方的函数,记录恢复过程的旋转过程公式(取一个魔方一边拧一边编程,考虑所有情况)
    1):顶层拼十字:简化为4次恢复顶面棱中小块(不破坏已恢复的结果)
    2):顶层拼四角:简化为4次恢复顶面的角小块(不破坏已恢复的结果)
    第一层恢复完成,剩下可按公式恢复魔方,把第一层置底
    3):二层拼棱角:简化为4次恢复二层棱角小块(不破坏已恢复的结果)
    第二层恢复完成
    4):按公式顶层拼十字
    5):按公式顶层四角对应恢复
    6):按公式顶面同色恢复
    7):按公式顶面棱边恢复
    第三层恢复完成
  5. 编写一个公式简化的函数,如消除相邻正反操作、消除4次相同操作、3次同向旋转替换为一次反向旋转操作、不相关跳跃旋转整合等,未能考虑所有可化简的情况,还未能化简为最少旋转步数公式。时间精力有限,待以后有新思路的时候再玩。

总结

很多指令都是现查现用的,编程模块化,过程分解,编程周期较长,编完以后,整体思路清晰,但单独模块缺少注释,不好看懂,特别是手动旋转对应编程部分,时间久了容易忘记。这是2019年1月编的代码(忘记了具体参考过哪些代码了),现在整理下思路,这里三阶魔方恢复算法是普通的按公式还原算法,主要难点在于判断魔方的状态,我编程的过程中是实际拿着个魔方一边转一边进行状态观察遍历,方法比较笨,可以实现自动魔方还原,但是还原步骤较多,程序中通过增加一些函数进行了步骤的简化
function TurnManu=simplifyTurnManu(TurnManu)
但是简化结果并不彻底,需要更高级的简化函数,或高级的魔方恢复算法。

思考

如果能够用快速相机记录并识别魔方高手旋转魔方的方法,通过机器学习、聚类、迁移等思想,改善算法,数据即算法?如果没有如果,给定初始的算法,能不能让算法自己通过运行自学习,更新算法,或者产生模拟高级的数据用于机器学习?感觉这会不会是一个很好的案例?数据为王?算法为王?Alpha Zero从0开始?有人实现了吗?

参考链接

没作记录,忘了,对参考过代码的博主表示歉意,如有发现雷同的地方,欢迎提醒,以作补充。

魔方

源代码

%% 主调函数
% ---定义魔方的初始状态
face0=ones(3,3);
MFstate={
   face0;face0+1;face0+2;face0+3;face0+4;face0+5};
% % MFstate=faceTurn(MFstate,'r');
% % MFstate=sideTurn(MFstate,'r'); 
[MFstate,TurnManu]=disorganize(MFstate,10);
% DispTurnManu(TurnManu,1);
figure;pltMoFang(MFstate);
set(gcf,'color','k');axis square;axis off;view(160,30)

TurnManu=simplifyTurnManu(TurnManu,0);
TurnManu0=DispTurnManu(TurnManu);
disp({
   '魔方打乱操作:';TurnManu0.'})

% MFstate=disorganize(MFstate,TurnManu);

[MFstate1,TurnManu1]=InvRecover(MFstate,TurnManu);
TurnManu0=DispTurnManu(TurnManu1);
disp({
   '魔方逆序恢复操作:';TurnManu0.'})
figure;pltMoFang(MFstate1);
set(gcf,'color','k');axis square;axis off;view(160,30)

 [MFstate,TurnManu2]=formulaRecover(MFstate);
 TurnManu2=simplifyTurnManu(TurnManu2,0);
TurnManu0=DispTurnManu(TurnManu2);
disp({
   '魔方公式恢复操作:';TurnManu0.'})
figure;pltMoFang(MFstate);
set(gcf,'color','k');axis square;axis off;view(160,30)
-----------------------------------------------------------------------------------------------------------------------------------
%% 动画显示
face0=ones(3,3);
MFstate={
   face0;face0+1;face0+2;face0+3;face0+4;face0+5};
limL=-4;limU=1;
close all;fig=figure; fig.Color=[1,1,1];  fig.Position=[400 200 550 600];
fig.ToolBar='none';  fig.MenuBar='none';  fig.NumberTitle='off';  fig.Name='魔方'; 
hds=pltMoFang(MFstate); 
set(gcf,'color','k');axis([limL,limU,limL,limU,limL,limU]);axis off;view(160,30);
pause(4);
TurnManu_all=[TurnManu;TurnManu2];
for n=1:length(TurnManu_all)
    pause(0.00001);
    turnAroundP(hds,TurnManu_all(n),10,0.01,limL,limU);
    MFstate=disorganize(MFstate,TurnManu_all(n));
    hold off;hds=pltMoFang(MFstate);axis([limL,limU,limL,limU,limL,limU]);axis off;view(160,30);
end
%% 部分子函数编写
%% 公式恢复魔方
function [MFstate,TurnManu]=formulaRecover(MFstate)
TurnManu=[];
        %---第一层恢复
        %将顶层拼十字
        num=zeros(1,4);
        for n=1:4
            [MFstate,TnMn,num]=recoverF10(MFstate,num);TurnManu=[TurnManu;TnMn];
            if sum(num)==4;break;end
            MFstate=faceTurn(MFstate,'r');num=circshift(num,-1);TurnManu=[TurnManu;'a'];
        end
        TurnManu=[TurnManu;('- ').'];
        %将顶层4个角恢复,完成第一层恢复
        num=zeros(1,4);
        for n=1:4
            [MFstate,TnMn,num]=recoverF4(MFstate,num);TurnManu=[TurnManu;TnMn];
            if sum(num)==4;break;end
            MFstate=faceTurn(MFstate,'r');num=circshift(num,-1);TurnManu=[TurnManu;'a'];
        end
        

        TurnManu=[TurnManu;('- ').'];
        %第二层恢复 4个角恢复,完成第二层恢复
        [MFstate,TnMn]=disorganize(MFstate,'CC');TurnManu=[TurnManu;TnMn];
        num=zeros(1,4);
        for n=1:4
            [MFstate,TnMn,num]=recover2F4(MFstate,num);TurnManu=[TurnManu;TnMn];
            if sum(num)==4;break;end
            MFstate=faceTurn(MFstate,'l');num=circshift(num,-1);TurnManu=[TurnManu;'A'];
        end
        
        TurnManu=[TurnManu;('- ').'];
        %第三层公式恢复
        %---步骤1:顶上拼十字
         [MFstate,TnMn]=recover3F10(MFstate);TurnManu=[TurnManu;TnMn];
                 
        TurnManu=[TurnManu;('- ').'];
        %---步骤2:四个角对应上
         [MFstate,TnMn]=recover3F4(MFstate);TurnManu=[TurnManu;TnMn];
         
         TurnManu=[TurnManu;('- ').'];
         %---步骤3:顶面恢复
         [MFstate,TnMn]=recover3Face(MFstate);TurnManu=[TurnManu;TnMn];
         while isempty(TnMn)==0
             [MFstate,TnMn]=recover3Face(MFstate);TurnManu=[TurnManu;TnMn];
         end
         
         TurnManu=[TurnManu;('- ').'];
         %---步骤4:顶棱中恢复
         [MFstate,TnMn]=recover3FArris(MFstate);TurnManu=[TurnManu;TnMn];
         while isempty(TnMn)==0
             [MFstate,TnMn]=recover3FArris(MFstate);TurnManu=[TurnManu;TnMn];
         end
         
end
% ---定义魔方整体旋转行为---改变朝前面
% r,l,u,d 共4种行为
function MFstate=faceTurn(MFstate,manu)
    if manu=='r'
            MFstate={
   MFstate{
   5};rot90(MFstate{
   3},2);MFstate{
   1};fliplr(MFstate{
   4}.');rot90(MFstate{2},2);fliplr(MFstate{6}).'};
    elseif manu=='l'
            MFstate={
   MFstate{
   3};rot90(MFstate{
   5},2);rot90(MFstate{
   2},2);fliplr(MFstate{
   4}).';MFstate{1};fliplr(MFstate{6}.')};
    elseif manu=='u'
            MFstate={
   MFstate{
   4};MFstate{
   6};fliplr(MFstate{
   3}.');MFstate{2};fliplr(MFstate{5}).';MFstate{
   1}};
    elseif manu=='d'
            MFstate={
   MFstate{
   6};MFstate{
   4};fliplr(MFstate{
   3}).';MFstate{1};fliplr(MFstate{5}.');MFstate{
   2}};
    else 
        return;
    end
end
----------------------------------------------------------------------------------------------------------------------------------------------------------
% ---定义一个旋转过程的函数
function turnAroundP(hds,TurnManu,stepNum,tSec,limL,limU)
if nargin==4
    limL=-3;limU=0;
end
if TurnManu=='a'
    [az,el]=view();
    azStep=linspace(0,-90,stepNum);
    for n=1:stepNum
        view(az+azStep(n),el);pause(tSec);
    end

elseif TurnManu=='A'
    [az,el]=view();
    azStep=linspace(0,90,stepNum);
    for n=1:stepNum
        view(az+azStep(n),el);pause(tSec);
    end
  
elseif TurnManu=='c' || TurnManu=='C'
    azStep=90/(stepNum+1);
    if TurnManu=='C'
         azStep=-azStep;
    end
    direct=[1,0,0];
    origin=-[1.5,1.5,1.5];
    for n=1:stepNum
        for k=1:6
            for kk=1:3
                for kkk=1:3
                    h=hds{
   k}{
   kk,kkk};
                    rotate(h,direct,azStep,origin);
                end
            end
        end
        axis([limL,limU,limL,limU,limL,limU]);axis off;view(160,30);pause(tSec);
    end
       
elseif TurnManu=='r' || TurnManu=='R'
    azStep=90/(stepNum+1);
    if TurnManu=='R'
         azStep=-azStep;
    end
    direct=[1,0,0];
    origin=-[1.5,1.5,1.5];
    for n=1:stepNum
        for k=3
            for kk=1:3
                for kkk=1:3
                    h=hds{
   k}{
   kk,kkk};
                    rotate(h,direct,azStep,origin);
                end
            end
        end
        
        for k=[1,2,4,6]
            for kk=1:3
                for kkk=3
                    h=hds{
   k}{
   kk,kkk};
                    rotate(h,direct,azStep,origin);
                end
            end
        end
        axis([limL,limU,limL,limU,limL,limU]);axis off;view(160,30);pause(tSec);
    end
       
elseif TurnManu=='l' || TurnManu=='L'
    azStep=-90/(stepNum+1);
    if TurnManu=='L'
         azStep=-azStep;
    end
    direct=[1,0,0];
    origin=-[1.5,1.5,1.5];
    for n=1:stepNum
        for k=5
            for kk=1:3
                for kkk=1:3
                    h=hds{
   k}{
   kk,kkk};
                    rotate(h,direct,azStep,origin);
                end
            end
        end
        
        for k=[1,2,4,6]
            for kk=1:3
                for kkk=1
                    h=hds{
   k}{
   kk,kkk};
                    rotate(h,direct,azStep,origin);
                end
            end
        end
        axis([limL,limU,limL,limU,limL,limU]);axis off;view(160,30);pause(tSec);
    end
       
elseif TurnManu=='u' || TurnManu=='U'
    azStep=-90/(stepNum+1);
    if TurnManu=='U'
         azStep=-azStep;
    end
    direct=[0,0,1];
    origin=-[1.5,1.5,1.5];
    for n=1:stepNum
        for k=6
            for kk=1:3
                for kkk=1:3
                    h=hds{
   k}{
   kk,kkk};
                    rotate(h,direct,azStep,origin);
                end
            end
        end
        
        for k=[1,3,5]
            for kk=1
                for kkk=1:3
                    h=hds{
   k}{
   kk,kkk};
                    rotate(h,direct,azStep,origin);
                end
            end
        end
 
        for k=2
            for kk=3
                for kkk=1:3
                    h=hds{
   k}{
   kk,kkk};
                    rotate(h,direct,azStep,origin);
                end
            end
        end
        axis([limL,limU,limL,limU,limL,limU]);axis off;view(160,30);pause(tSec);
    end    
       
elseif TurnManu=='d' || TurnManu=='D'
    azStep=90/(stepNum+1);
    if TurnManu=='D'
         azStep=-azStep;
    end
    direct=[0,0,1];
    origin=-[1.5,1.5,1.5];
    for n=1:stepNum
        for k=4
            for kk=1:3
                for kkk=1:3
                    h=hds{
   k}{
   kk,kkk};
                    rotate(h,direct,azStep,origin);
                end
            end
        end
        
        for k=[1,3,5]
            for kk=3
                for kkk=1:3
                    h=hds{
   k}{
   kk,kkk};
                    rotate(h,direct,azStep,origin);
                end
            end
        end
 
        for k=2
            for kk=1
                for kkk=1:3
                    h=hds{
   k}{
   kk,kkk};
                    rotate(h,direct,azStep,origin);
                end
            end
        end
        axis([limL,limU,limL,limU,limL,limU]);axis off;view(160,30);pause(tSec);
    end    
       
elseif TurnManu=='f' || TurnManu=='F'
    azStep=-90/(stepNum+1);
    if TurnManu=='F'
         azStep=-azStep;
    end
    direct=[0,1,0];
    origin=-[1.5,1.5,1.5];
    for n=1:stepNum
        for k=1
            for kk=1:3
                for kkk=1:3
                    h=hds{
   k}{
   kk,kkk};
                    rotate(h,direct,azStep,origin);
                end
            end
        end
            for kk=1:3
                    h=hds{
   3}{
   kk,1};
                    rotate(h,direct,azStep,origin);
            end
            for kk=1:3
                    h=hds{
   5}{
   kk,3};
                    rotate(h,direct,azStep,origin);
            end
            
            for kkk=1:3
                    h=hds{
   4}{
   1,kkk};
                    rotate(h,direct,azStep,origin);
            end
            
            for kkk=1:3
                    h=hds{
   6}{
   3
评论 19
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值