第一次写博客,想总结分享下以前做过的一些有趣的东西,目的是为了回望过去与展望未来,同时为了提高自己的写作表达能力。
思路与步骤
- 三阶魔方有6个面,每个面有 3 × 3 3\times3 3×3小块,用一个 6 × 3 × 3 6\times3\times3 6×3×3的矩阵来保存魔方的状态;
- 定义4+12种魔方旋转行为:整体旋转(左右上下共4种方式AaCc),侧面(6个侧面顺逆时针旋转共12种方式LlRrUuDdFfBb),旋转可视化界面方便调试(三维小面作图fill3创建 6 × 3 × 3 = 54 6\times3\times3=54 6×3×3=54个小面对象,对象成员属性包括颜色和4个三维坐标点,定义了全局函数对小面进行绕轴旋转操作,如此可以可视化调试,确保程序是按人想法运行),旋转行为改变矩阵的状态矩阵;
- 定义随机打乱和逆序恢复的函数,测试确保人为给出旋转公式,魔方能正确旋转;
- 编写按公式恢复魔方的函数,记录恢复过程的旋转过程公式(取一个魔方一边拧一边编程,考虑所有情况)
1):顶层拼十字:简化为4次恢复顶面棱中小块(不破坏已恢复的结果)
2):顶层拼四角:简化为4次恢复顶面的角小块(不破坏已恢复的结果)
第一层恢复完成,剩下可按公式恢复魔方,把第一层置底
3):二层拼棱角:简化为4次恢复二层棱角小块(不破坏已恢复的结果)
第二层恢复完成
4):按公式顶层拼十字
5):按公式顶层四角对应恢复
6):按公式顶面同色恢复
7):按公式顶面棱边恢复
第三层恢复完成 - 编写一个公式简化的函数,如消除相邻正反操作、消除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