首页 > 解决方案 > C# 中用于魔方的 7-Riffle Shuffle 算法

问题描述

对于学校作业,我们需要在 C# 中实现一个 7-Riffle 算法方法,它可以打乱魔方的面。不幸的是,网络上没有足够的资源来展示它应该如何编码。我已经实现了秒表来计算不同魔方大小所需的经过时间。

这段代码适用于洗牌位,但它所花费的时间似乎没有意义,因为它比 Fisher Yates 的更快。

        Random rand = new Random();

        for (int i = rubikCubeArray.Length - 1; i > 7; i--)
        {
            int n = rand.Next(i + 1);
            int temp = rubikCubeArray[i];
            rubikCubeArray[i] = rubikCubeArray[n];
            rubikCubeArray[n] = temp;
        }

请问有什么帮助吗?

标签: c#algorithmshufflerubiks-cube

解决方案


  1. 共同的起始种子是个好主意(正如jdweng指出的那样)

    我只是需要修复那个错字,因为新手可能不知道seen应该这样seed。这样,两种比较算法将具有相同的条件。

  2. 嵌套for循环

    不熟悉 7-Riffle Shuffle 算法,但回溯求解器应该嵌套了 for 循环。现在你有一个循环 9 次(为什么?)。

    如果您有N=7轮数 shuffled 立方体,则需要 7 个嵌套的 for 循环,每个循环遍历所有可能的转数3*3*2=18。如果N发生变化,您需要动态嵌套 for 循环以获取更多信息,请参阅:

    或可屏蔽的嵌套 for 循环,直到神数 ( 20)

    每次迭代中的每个 for 循环都会通过选定的移动来转动前一个循环状态立方体,并且在最后一个循环中还应该检测已解决的情况并在发现时中断。

    所以像这样(求解器):

    cube0=solved_cube();
    for (cube1=cube0,i1=0; i1<18; i1++,cube1=turn_cube(cube0,i1))
     for (cube2=cube1,i2=0; i2<18; i2++,cube2=turn_cube(cube1,i2))
      ...
       for (cube7=cube6,i7=0; i7<18; i7++,cube7=turn_cube(cube1,i7))
        if (cube7 == solved_cube()) return { i1,i2,...,i7 }; // solution found
    return false; // unsolved
    

    where turn_cube(cube a,int turn)will return cube aturn by turnwhereturn选择哪个切片朝哪个方向旋转(18 个可能的转弯中的哪一个)...

您也可能对此感兴趣:

[Edit1] 洗牌器

正如我所提到的,我不熟悉 7 riffle shuffle 算法,所以如果你只想让一个立方体从解决状态旋转 7 圈,那么你几乎是对的。你应该有一个单循环for,但在里面你需要进行有效的随机移动,如下所示:

cube=solved_cube();
for (i=0; i<7; i++)
 cube=turn_cube(cube,Random(18));

现在真正的问题是编写 turn_cube 函数。为了帮助解决这个问题,我们需要更多地了解您如何在内部表示您的魔方。

那么它是 1D、2D 还是 3D 阵列?什么是拓扑?元素值是什么(十六进制颜色可能是或只是0..5或一些枚举或变换矩阵)?

在上面的链接中是我的解算器的例子,它带有函数 void 的源代码,RubiCube::cube_rotate(int axis,int slice,double ang)这或多或少是 cube_turn 应该做的。有 18 种可能的转弯:

  • 3 轴 ( axis)
  • 每个轴有 3 个切片 ( slice)
  • 我们可以将 CW 或 CCW 转动 90 度(ang请注意我的 ang 是弧度,并且在我为转弯设置动画时允许任意角度)

所以你需要映射那些int turn = <0,17>将在 cube_turn 中处理并应用于你的立方体的 18 个案例......


推荐阅读