楼主
怎么说呢 我小学时做扁桃体切除手术,后面同学来我家探望我的时候 有一个人送了个魔方。
然后我打乱了这个魔方 很久都不能复原。
我那时候一直不知道怎么复原,于是开始研究。
研究出来了一些奇奇怪怪的公式。不过并没有真正复原。
研究这些公式很痛苦,因为万一又弄乱了,我就得重新拆魔方。
到了初二的时候,我再一次开始研究魔方。
那时候我已经研究完了数字华容道如何复原。
于是借着这个思想 我确认了所有我需要的公式。
最终又找到了两个公式,并且尽可能利用了我小学时发现的公式的组合。
然后我第一次完成了魔方复原。
后面我继续确认了所有边界情况,以及奇偶校验的方法。
最后在初三以后,我将其做到了网页上 使用了一个虚拟魔方。
图形化体验地址:https://www.altzin.com/cube/demo.html
基本算法:
async function 上右下左(cubeobj) {
await cubeobj.op(3);
await cubeobj.op(7);
await cubeobj.op(6);
await cubeobj.op('a');
}
async function 逆上右下左(cubeobj) {
await cubeobj.op(7);
await cubeobj.op(3);
await cubeobj.op('a');
await cubeobj.op(6);
}
async function 左上右下左(cubeobj) {
await cubeobj.op(1);
await cubeobj.op('a');
await cubeobj.op(4);
await cubeobj.op(7);
}
async function 逆左上右下左(cubeobj) {
await cubeobj.op('a');
await cubeobj.op(1);
await cubeobj.op(7);
await cubeobj.op(4);
}
async function 逆时针三棱换(cubeobj) {
await 上右下左(cubeobj);
await 上右下左(cubeobj);
await 左上右下左(cubeobj);
await 左上右下左(cubeobj);
await 逆上右下左(cubeobj);
await 逆上右下左(cubeobj);
await 逆左上右下左(cubeobj);
await 逆左上右下左(cubeobj);
}
async function 顺时针三棱换(cubeobj) {
await 左上右下左(cubeobj);
await 左上右下左(cubeobj);
await 上右下左(cubeobj);
await 上右下左(cubeobj);
await 逆左上右下左(cubeobj);
await 逆左上右下左(cubeobj);
await 逆上右下左(cubeobj);
await 逆上右下左(cubeobj);
}
async function 上面对二棱反(cubeobj) {
for (let i = 0; i < 4; i++) {
await cubeobj.op(2);
await cubeobj.op(7);
}
for (let i = 0; i < 4; i++) {
await cubeobj.op(2);
await cubeobj.op('a');
}
}
async function 当面左上邻二楞反(cubeobj) {
await 逆时针三棱换(cubeobj);
await cubeobj.rotateX(-1);
await 上面对二棱反(cubeobj);
await cubeobj.rotateX(1);
await 顺时针三棱换(cubeobj);
}
async function 当面上下到前左转角(cubeobj) {
await cubeobj.rotateX(-1);
await 上右下左(cubeobj);
await 上右下左(cubeobj);
await cubeobj.op(4);
await 逆上右下左(cubeobj);
await 逆上右下左(cubeobj);
await cubeobj.op(1);
await cubeobj.rotateX(1);
}
async function 内部函数1(cubeobj) {
await 上右下左(cubeobj);
await 上右下左(cubeobj);
await 上右下左(cubeobj);
await cubeobj.op(4);
await 逆上右下左(cubeobj);
await 逆上右下左(cubeobj);
await 逆上右下左(cubeobj);
await cubeobj.op(1);
}
async function 右上顺时针三角换(cubeobj) {
await 内部函数1(cubeobj);
await cubeobj.rotateX(1);
await cubeobj.rotateZ(2);
await 内部函数1(cubeobj);
await cubeobj.rotateX(1);
await cubeobj.rotateZ(2);
}
async function 打乱(cubeobj) {
cubeobj.output('[打乱] 开始随机打乱魔方…');
const 操作列表 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 'a', 'b', 'c'];
for (let i = 0; i < 20; i++) {
const 随机操作 = 操作列表[Math.floor(Math.random() * 操作列表.length)];
await cubeobj.op(随机操作);
}
cubeobj.output('[打乱] 第一阶段 20 步切片操作完成');
const 整体旋转轴 = ['X', 'Y', 'Z'];
const 随机轴 = 整体旋转轴[Math.floor(Math.random() * 整体旋转轴.length)];
const 随机方向 = Math.random() > 0.5 ? 1 : -1;
await cubeobj[`rotate${随机轴}`](随机方向);
cubeobj.output(`[打乱] 整体旋转 rotate${随机轴}(${随机方向})`);
for (let i = 0; i < 20; i++) {
const 随机操作 = 操作列表[Math.floor(Math.random() * 操作列表.length)];
await cubeobj.op(随机操作);
}
cubeobj.output('[打乱] 第二阶段 20 步切片操作完成,打乱结束');
}
async function 复原底面(cubeobj) {
cubeobj.output('[底面] 开始复原底面…');
await 复原底面楞(cubeobj);
await 复原底面角(cubeobj);
cubeobj.output('[底面] 底面复原完成');
}
async function 复原底面楞(cubeobj) {
cubeobj.output('[底面] 复原底面棱块:取下 → 归位 → 调向');
await 把底面楞弄下来(cubeobj);
await 把底面楞放上去(cubeobj);
await 把底面楞方向弄正确(cubeobj);
cubeobj.output('[底面] 底面棱块完成');
}
function 数组等(arr1, arr2) {
return arr1.length === arr2.length &&
arr1.every((item, index) => item === arr2[index]);
}
function 相等(a, b) {
return 数组等(a.sort(), b.sort());
}
function 在里面(a, b) {
return b.some(item => 相等(item, a));
}
async function 底面角弄到下面(cubeobj) {
await cubeobj.op('a');
await cubeobj.op('b');
await cubeobj.op(3);
await cubeobj.op(7);
await cubeobj.op(8);
}
async function 底面角循环一下(cubeobj) {
await cubeobj.rotateX(1);
await cubeobj.op('a');
await cubeobj.op('b');
await cubeobj.op(3);
await cubeobj.op(3);
await cubeobj.op(7);
await cubeobj.op(8);
await cubeobj.rotateX(-1);
await cubeobj.op('c');
}
async function 底面角复原(cubeobj) {
await cubeobj.rotateX(1);
await 底面角弄到下面(cubeobj);
await cubeobj.rotateX(-1);
}
async function 复原底面角(cubeobj) {
cubeobj.output('[底面] 开始复原底面角块(4 个)…');
let 侧面颜色 = ['D', 'C', 'E', 'B'];
let 需要的角 = null;
let 右下的角 = null;
for (let i = 0; i < 4; i++) {
cubeobj.output(`[底面] 角块 ${i + 1}/4:观察面 ${侧面颜色[i]}`);
await cubeobj.setDirection(侧面颜色[i], 'F');
需要的角 = ['F', 侧面颜色[((i + 1) % 4)], 侧面颜色[i]]
await cubeobj.rotateX(1);
for (let k = 0; k < 4; k++) {
右下的角 = cubeobj.query(9);
if (相等(需要的角, 右下的角)) {
cubeobj.output(`[底面] 角块 ${i + 1}/4 在底面,要先弄到顶面`);
await 底面角弄到下面(cubeobj);
break;
}
await cubeobj.rotateZ(-1);
}
await cubeobj.setDirection(侧面颜色[i], 'F');
for (; ;) {
右下的角 = cubeobj.query(9);
if (相等(需要的角, 右下的角)) {
break;
}
await cubeobj.op('c');
}
cubeobj.output(`[底面] 找到角块 ${i + 1}/4…`);
for (; ;) {
右下的角 = cubeobj.query(9);
if (右下的角[0] === 'F') {
break;
}
cubeobj.output(`[底面] 角块 ${i + 1}/4 方向不对,循环一下…`);
await 底面角循环一下(cubeobj);
}
cubeobj.output(`[底面] 插入角块 ${i + 1}/4`);
await 底面角复原(cubeobj);
cubeobj.output(`[底面] 角块 ${i + 1}/4 已就位`);
}
}
async function 弄一个底面楞下来(cubeobj, 需要的块) {
let 下面的楞 = null;
for (let j = 0; ; j++) {
下面的楞 = cubeobj.query(8);
if (在里面(下面的楞, 需要的块)) {
await cubeobj.op(9);
if (j === 3) {
return;
}
} else {
break;
}
}
await cubeobj.rotateX(-1);
await cubeobj.op('a');
await cubeobj.rotateX(1);
}
async function 把底面楞弄下来(cubeobj) {
cubeobj.output('[底面] 将所有底棱块移到顶层…');
let 侧面颜色 = ['C', 'D', 'B', 'E'];
let 需要的块 = [];
for (let i = 0; i < 4; i++) {
需要的块.push([侧面颜色[i], 'F']);
}
for (let i = 0; i < 4; i++) {
cubeobj.output('[底面] 从第'+(i+1)+'个侧面尝试弄下棱块…');
await cubeobj.setDirection(侧面颜色[i], 'F');
await 弄一个底面楞下来(cubeobj, 需要的块);
await 弄一个底面楞下来(cubeobj, 需要的块);
await 弄一个底面楞下来(cubeobj, 需要的块);
}
}
async function 把底面楞放上去(cubeobj) {
cubeobj.output('[底面] 将底棱块插入底层正确位置…');
let 下面的楞 = null;
let 侧面颜色 = ['C', 'D', 'B', 'E'];
for (let i = 0; i < 4; i++) {
await cubeobj.setDirection(侧面颜色[i], 'F');
for (let j = 0; ; j++) {
下面的楞 = cubeobj.query(8);
if (相等(下面的楞, [侧面颜色[i], 'F'])) {
break;
}
await cubeobj.op('9');
}
await cubeobj.rotateX(-1);
await cubeobj.op('a');
await cubeobj.op('a');
await cubeobj.rotateX(1);
cubeobj.output('[底面] 第'+(i+1)+'个棱块已插入…');
}
}
async function 把底面楞方向弄正确(cubeobj) {
cubeobj.output('[底面] 调整底棱块朝向…');
let 左边的楞 = null;
let 左边楞颜色 = null;
await cubeobj.setDirection('F', 'C');
for (let i = 0; i < 4; i++) {
cubeobj.output('[底面] 调整第'+(i+1)+'个底棱块朝向…');
左边的楞 = cubeobj.query(4);
左边楞颜色 = 左边的楞[0];
if (左边楞颜色 !== 'F') {
cubeobj.output('[底面] 翻转第'+(i+1)+'个底棱块…');
await cubeobj.rotateY(1);
await cubeobj.rotateX(-1);
await 上面对二棱反(cubeobj);
await cubeobj.rotateX(1);
await cubeobj.rotateY(-1);
}
await cubeobj.rotateZ(-1);
}
}
async function 复原中层(cubeobj) {
cubeobj.output('[中层] 开始复原中层棱块…');
let 目标棱块 = null;
目标棱块 = ['C', 'D'];
let 左边的楞 = null;
let 上面的楞 = null;
let 右边的楞 = null;
await cubeobj.setDirection('D', 'A');
for (let g = 0; g < 4; g++) {
左边的楞 = cubeobj.query(4);
if (相等(目标棱块, 左边的楞)) {
cubeobj.output('[中层] 发现目标CD棱块,弄到顶层…');
await 顺时针三棱换(cubeobj);
break;
}
await cubeobj.rotateY(-1);
}
await cubeobj.setDirection('C', 'A');
for (; ;) {
上面的楞 = cubeobj.query(2);
if (相等(目标棱块, 上面的楞)) {
cubeobj.output('[中层] 拿到顶层目标CD棱块,执行插入…');
await 顺时针三棱换(cubeobj);
break;
}
await cubeobj.op('a');
}
目标棱块 = ['B', 'D'];
await cubeobj.setDirection('E', 'A');
右边的楞 = cubeobj.query(6);
if (相等(目标棱块, 右边的楞)) {
cubeobj.output('[中层] 在E面发现目标BD棱块,弄到顶层…');
await 逆时针三棱换(cubeobj);
}
await cubeobj.setDirection('B', 'A');
右边的楞 = cubeobj.query(6);
if (相等(目标棱块, 右边的楞)) {
cubeobj.output('[中层] 在B面发现目标BD棱块,弄到顶层…');
await 逆时针三棱换(cubeobj);
}
左边的楞 = cubeobj.query(4);
if (相等(目标棱块, 左边的楞)) {
cubeobj.output('[中层] 在B面发现目标BD棱块,弄到顶层…');
await 顺时针三棱换(cubeobj);
}
await cubeobj.setDirection('B', 'A');
for (; ;) {
上面的楞 = cubeobj.query(2);
if (相等(目标棱块, 上面的楞)) {
cubeobj.output('[中层] 拿到顶层目标BD棱块,执行插入…');
await 逆时针三棱换(cubeobj);
break;
}
await cubeobj.op('a');
}
await cubeobj.setDirection('E', 'A');
let 不想要的楞 = ['B', 'E'];
目标棱块 = ['E', 'C'];
左边的楞 = cubeobj.query(4);
if (相等(左边的楞, 不想要的楞)) {
cubeobj.output('[中层] 在E面左边发现不想要的棱块,弄到顶层…');
await 顺时针三棱换(cubeobj);
}
右边的楞 = cubeobj.query(6);
if (相等(右边的楞, 不想要的楞)) {
cubeobj.output('[中层] 在E面右边发现不想要的棱块,弄到顶层…');
await 逆时针三棱换(cubeobj);
}
let 发现了不想要 = false;
上面的楞 = cubeobj.query(2);
if (相等(不想要的楞, 上面的楞)) {
cubeobj.output('[中层] 在E面顶层发现不想要的棱块,设置标志…');
发现了不想要 = true;
}
右边的楞 = cubeobj.query(6);
if (相等(右边的楞, 目标棱块)) {
if (发现了不想要) {
cubeobj.output('[中层] 在E面顶层有不想要的棱块干扰,转走…');
await cubeobj.op(7);
}
cubeobj.output('[中层] 发现目标棱块在E面右边,直接插入目标棱块…');
await 顺时针三棱换(cubeobj);
} else {
左边的楞 = cubeobj.query(4);
if (!相等(左边的楞, 目标棱块)) {
for (; ;) {
上面的楞 = cubeobj.query(2);
if (相等(目标棱块, 上面的楞)) {
cubeobj.output('[中层] 在顶层找到目标棱块,现在插入目标棱块…');
await 逆时针三棱换(cubeobj);
break;
}
await cubeobj.op(7);
}
}else{
cubeobj.output('[中层] 发现目标棱块已经就位,跳过…');
}
}
for (; ;) {
上面的楞 = cubeobj.query(2);
if (相等(不想要的楞, 上面的楞)) {
cubeobj.output('[中层] 在顶层找到曾经不想要的棱块,现在一次性插入到正确位置…');
await 逆时针三棱换(cubeobj);
break;
}
await cubeobj.op(7);
}
await cubeobj.setDirection('E', 'A');
let 侧面颜色 = ['E', 'C', 'D', 'B'];
for (let l = 0; l < 3; l++) {
左边的楞 = cubeobj.query(4);
if (左边的楞[0] !== 侧面颜色[l]) {
cubeobj.output('[中层] 发现第'+(l+1)+'个棱块颜色不对,现在翻转一下…');
await cubeobj.rotateX(-1);
await 上面对二棱反(cubeobj);
await cubeobj.rotateX(1);
}
await cubeobj.rotateY(-1);
}
左边的楞 = cubeobj.query(4);
if (左边的楞[0] !== 侧面颜色[3]) {
cubeobj.output('[中层] 发现最后一个棱块颜色不对,现在翻转一下,溢出到顶层…');
await 当面左上邻二楞反(cubeobj);
}
cubeobj.output('[中层] 中层棱块复原完成');
}
async function 复原顶层(cubeobj) {
cubeobj.output('[顶层] 开始复原顶层…');
await 保证奇偶(cubeobj);
await 复原顶层楞块(cubeobj);
await 复原顶层角块(cubeobj);
cubeobj.output('[顶层] 顶层复原完成');
}
async function 复原顶层角块(cubeobj) {
cubeobj.output('[顶层] 复原顶层角块…');
await cubeobj.setDirection('A', 'D');
let 右上的角 = null;
右上的角 = cubeobj.query(3);
let 目标角块 = ['A', 'B', 'E'];
if (相等(右上的角, 目标角块)) {
cubeobj.output('[顶层] 发现目标角块在不可触及处,移动到可用处…');
await 右上顺时针三角换(cubeobj);
}
await cubeobj.rotateZ(2);
for (; ;) {
右上的角 = cubeobj.query(3);
if (相等(右上的角, 目标角块)) {
cubeobj.output('[顶层] 循环可见处最终插入了目标角块到正确位置…');
break;
}
cubeobj.output('[顶层] 目标角块不在正确位置,循环一下…');
await 右上顺时针三角换(cubeobj);
}
await cubeobj.rotateZ(2);
目标角块 = ['A', 'C', 'D'];
for (; ;) {
右上的角 = cubeobj.query(3);
if (相等(右上的角, 目标角块)) {
cubeobj.output('[顶层] 剩下三个角块位置正确了…');
break;
}
cubeobj.output('[顶层] 剩下三个角块位置不正确,循环一下…');
await 右上顺时针三角换(cubeobj);
}
let 左上的角 = null;
for (let u = 0; u < 3; u++) {
for (; ;) {
左上的角 = cubeobj.query(1);
if (左上的角[0] === 'A') {
break;
}
cubeobj.output('[顶层] 发现第'+(u+1)+'个角块方向不对,旋转一下…');
await 当面上下到前左转角(cubeobj);
}
await cubeobj.rotateZ(1);
}
cubeobj.output('[顶层] 顶层角块完成');
}
async function 复原顶层楞块(cubeobj) {
cubeobj.output('[顶层] 复原顶层棱块…');
await cubeobj.setDirection('A', 'B');
let 上面的楞 = null;
let 左边的楞 = null;
上面的楞 = cubeobj.query(2);
let 目标楞块 = ['C', 'A'];
if (相等(上面的楞, 目标楞块)) {
cubeobj.output('[顶层] 发现目标棱块在不可触及处,移动到可用处…');
await 逆时针三棱换(cubeobj);
}
await cubeobj.rotateZ(2);
for (; ;) {
上面的楞 = cubeobj.query(2);
if (相等(目标楞块, 上面的楞)) {
cubeobj.output('[顶层] 循环可见处最终插入了目标棱块到正确位置…');
break;
}
cubeobj.output('[顶层] 目标棱块不在正确位置,循环一下…');
await 逆时针三棱换(cubeobj);
}
await cubeobj.rotateZ(2);
目标楞块 = ['B', 'A'];
for (; ;) {
上面的楞 = cubeobj.query(2);
if (相等(目标楞块, 上面的楞)) {
cubeobj.output('[顶层] 剩下三个棱块位置正确了…');
break;
}
cubeobj.output('[顶层] 剩下三个棱块位置不正确,循环一下…');
await 逆时针三棱换(cubeobj);
}
左边的楞 = cubeobj.query(4);
if (左边的楞[0] !== 'A') {
cubeobj.output('[顶层] 第1个棱块方向不对,现在翻转一下…');
await cubeobj.rotateX(-1);
await 上面对二棱反(cubeobj);
await cubeobj.rotateX(1);
}
await cubeobj.rotateZ(1);
左边的楞 = cubeobj.query(4);
if (左边的楞[0] !== 'A') {
cubeobj.output('[顶层] 第2个棱块方向不对,现在翻转一下…');
await cubeobj.rotateX(-1);
await 上面对二棱反(cubeobj);
await cubeobj.rotateX(1);
}
await cubeobj.rotateZ(2);
左边的楞 = cubeobj.query(4);
if (左边的楞[0] !== 'A') {
cubeobj.output('[顶层] 最后两个棱块方向不对,现在翻转一下…');
await 当面左上邻二楞反(cubeobj);
}
cubeobj.output('[顶层] 顶层棱块完成');
}
async function 保证奇偶(cubeobj) {
cubeobj.output('[顶层] 检查顶层棱块奇偶性…');
await cubeobj.setDirection('C', 'A');
let 上面的楞 = null;
let 目标楞块 = ['C', 'A'];
for (; ;) {
上面的楞 = cubeobj.query(2);
if (相等(目标楞块, 上面的楞)) {
cubeobj.output('[顶层] 为了检查奇偶已对齐一个棱块…');
break;
}
await cubeobj.op('a');
}
await cubeobj.rotateX(1);
let 符合的数量 = 1;
if (相等(cubeobj.query(2), ['A', 'B'])) {
符合的数量++;
}
if (相等(cubeobj.query(4), ['A', 'E'])) {
符合的数量++;
}
if (相等(cubeobj.query(6), ['A', 'D'])) {
符合的数量++;
}
await cubeobj.rotateX(-1);
if (符合的数量 == 2) {
await cubeobj.op('a');
cubeobj.output('[顶层] 奇偶不符,执行修正手顺');
} else {
cubeobj.output('[顶层] 奇偶性正常');
}
}
async function 复原(cubeobj) {
cubeobj.output('======== 开始自创层先法复原 ========');
await 复原底面(cubeobj);
await 复原中层(cubeobj);
await 复原顶层(cubeobj);
cubeobj.output('======== 复原完成 ========');
}
if (typeof window !== 'undefined') {
window.CubeAlgo = { 打乱, 复原 };
}