魔方的加扰生成器算法

时间:2019-04-24 14:14:49

标签: c++

我最近一直在从事一个项目,该项目包括一个Rubik的Cube加密生成器。基本上,程序应生成并显示随机的多维数据集符号,以便用户可以跟随每个动作并获得一个相当混乱的多维数据集。标记包括:“ R”用于右移图层,“ L”用于左移图层,“ F”用于旋转顶层,“ D”用于向下,“ U”用于向上,“ B”用于后向。因此,您总共有6个面“ R,L,U,D,F,B”。这些符号中的任何一个之后的提案表示逆时针移动该层,“ 2”表示将该层移动两次。问题是您不能像“ R2”一样将相同的符号彼此相邻地重复,例如“ R,R”,也不能使“ R,R'”彼此相邻会互相抵消。我的解决方案是制作一个二维数组,用于存储每种类型的3组符号。

string notation_group[row][column] = { { "R ", "L ", "F ", "B ", "U ", "D " },
    {"R' ", "L' ", "F' ", "B' ", "U' ", "D' "}, { "R2", "L2", "F2", "B2", "U2", "D2"} };

这意味着,只要程序从这些组中的任何一个中选择一个随机列,该程序就必须防止下一个生成的符号选择任何其他组中的相同列。因此,假设程序选择了第一组“ R”的第一个元素,那么对于下一次迭代,它可以选择“ R”,“ R”和“ R2”以外的任何符号,它们都属于第一列他们各自的群体。因此,程序要做的就是不要在下次迭代中选择该列。

我使用了一个“ temp”变量来记住当前随机生成的表示法,并将其与下一个表示法进行比较,并在它们相等时生成一个新的表示法。

int temp;

            scrambled_notation[i] = notation_group[pickGroup][pickColumn];

            temp = pickColumn;

            pickColumn = 0 + rand() % 6;

            while (temp == pickColumn) {
                pickColumn = 0 + rand() % 6;
            }

它确实有效,但是仍然存在另一个问题,每当您将诸如“ R,L”或“ R,L',R”之类的内容彼此相邻重复多次时,它们将再次相互抵消,不会造成任何影响在多维数据集上。有什么想法可以防止两个相对的边彼此重复多次?我将非常感谢您的帮助。

    void initScramble(const int, string[][6], string[]);

int main() {

    srand(time(0));

    const int row = 3, column = 6;
    string notation_group[row][column] = { { "R", "L", "F", "B", "U", "D" },
    {"R'", "L'", "F'", "B'", "U'", "D'"}, { "R2", "L2", "F2", "B2", "U2", "D2"} };

    const int scrambleSize = 22;
    string scrambled_notation[scrambleSize];

    cout << "SCRAMBLE: " << endl;

    initScramble(scrambleSize, notation_group, scrambled_notation);

    system("pause");
    return 0;
}

void initScramble(const int scrambleSize, string notation_group[][6], string scrambled_notation[]) {

    int pickColumn = 0 + rand() % 6;

    while (true) {

        cin.get();

        for (int i = 0; i < scrambleSize; i++) {

            int pickGroup = 0 + rand() % 3;

            int temp;

            scrambled_notation[i] = notation_group[pickGroup][pickColumn];

            temp = pickColumn;

            pickColumn = 0 + rand() % 6;

            while (temp == pickColumn) {
                pickColumn = 0 + rand() % 6;
            }
        }

        for (int i = 0; i < scrambleSize; i++) {
            cout << scrambled_notation[i] << "  ";
        }
        cin.get();
        system("CLS");
    }

}

1 个答案:

答案 0 :(得分:1)

您必须寻找最后两个动作,只要它们是可交换的。如果不是,则只检查最后一步。每对列都是可交换的,从而简化了这一过程:

void initScramble(const int scrambleSize, string notation_group[][6], string scrambled_notation[]) {
    while (true) {
        int lastColumn = 7; // Invalid columns
        int beforeLastColumn = 7;

        cin.get();

        for (int i = 0; i < scrambleSize; i++) {
            int pickGroup = 0 + rand() % 3;
            int pickColumn = 0 + rand() % 6;
            bool isCommutative = (lastColumn / 2) == (beforeLastColumn / 2);

            while (pickColumn == lastColumn || isCommutative && pickColumn == beforeLastColumn) {
                pickColumn = 0 + rand() % 6;
            }

            scrambled_notation[i] = notation_group[pickGroup][pickColumn];
            beforeLastColumn = lastColumn;
            lastColumn = pickColumn;
        }

        for (int i = 0; i < scrambleSize; i++) {
            cout << scrambled_notation[i] << "  ";
        }
        cin.get();
        system("CLS");
    }
}

您不必进一步看,因为按照加扰规则,您只能进行2个可交换的连续移动。例如,“ L,R,L”和“ L,R,R”将被丢弃,因此将永远不会产生3个换向运动。