rubiks立方体旋转算法

时间:2017-01-24 22:55:35

标签: java algorithm rubiks-cube

我目前正致力于建立一个正常运作的魔方魔方。该程序不需要GUI。但它必须模拟具有旋转行为的3 X 3立方体,并提供立方体的图形表示(我将使用平面字母结构)。我的代码有一个facet类,它构成一个Face(另一个类),然后有一个包含旋转方法的cube类。

我无法创建/选择要使用的算法,以便准确地模拟立方体和所有可能的旋转。我在这个网站上找到了一个解决方案,引用了一篇论文,提出了7种不同的方法(下面的链接)。但哪种方法最直观/易于编码?更重要的是,哪种最适合下面概述的行为(在伪代码中)?

我无法理解如何使用任何方法同时考虑每个面上的变化,特别是考虑到面部旋转的行为(而不是行和列)。

How would you represent a Rubik's Cube in code?

Rotation Pseudocode: 

map each cube numbers 1-54, faces 1 – 4 are 1 – 36 while top face is 37 - 45 and bottom is 46 – 54
1 turn: clockwise = +9
1 turn: counterclockwise = -9 loops back to 45
1 turn: up = + 37
1 turn: down = -37 loops back to 46
2 turns: clockwise = +9(2)
2 turns: counterclockwise = -9(2)
2 turns: up = +37(2)
2 turns: down = -37(2)
3 turns: clockwise = +9(3)
3 turns: counterclockwise = -9(3)
3 turns: up = +37(3)
3 turns: down = -37(3)

此伪代码不考虑面部更改。

有没有更好/更简单的方法来执行此操作,这与我的伪代码提出的方法不同?如何解释面部变化?

示例:(正面,1圈,顺时针)

123    741
456    852
789    963

注意:我倾向于54元素向量,但我不确定如何操纵它。

此外,这是我的第一个问题,所以如果出现问题,请告诉我(信息不足,信息太多,主题不对等)。

谢谢!

注意:这是我正在使用的代码。

Facet Class:

public class Facets {

    public Color color;


    public Facets(Color color){
    }


    public enum Color {

        B, G, R, Y, O, P


}

    public String getName(){
        return this.color.name();
    }

}

面部课程:

import java.util.Arrays;

public class Face {


    public Facets[] face;

    /*public Face(Facets.Color color, Facets.Color[] array){
        face = new Facets[9];
        for(int i = 0; i < face.length; i++){
            face[i] = new Facets(array[i]);
            face[i] = new Facets(color);

        }
    }*/

    public Face(Facets.Color color){
        face = new Facets[9];
        for(int i = 0; i < face.length; i++){
            face[i] = new Facets(color);
        }
    }

    public Face(Facets.Color[] array){
        face = new Facets[9];
        for (int i = 0; i < face.length; i++){
            face[i] = new Facets(array[i]);
            //face[i] = face[i].toString();
        }
    }


    //Returns a textual representation of Face  
    public String printFace(){
        StringBuilder faceString = new StringBuilder();

        for(Facets f: face){
            faceString.append(f.getName()); 
            System.out.println(f.toString());
        }
        return faceString.toString();

}

    public static void main(String[] args){
        Face face = new Face(Facets.Color.B);
        System.out.println(face.toString());
    }
}

多维数据集类:

public class Cube {

    public Cube(Face front, Face right, Face back, Face left, Face top, Face bottom){

    }

    public Cube createCube(){


    }

    public Cube rotate(int row, int column, String direction, int turns){
        /*Turns must be between 0 - 4
Row must be 1 or 2, column must be 1 or 2, direction must be clockwise, counterclockwise, up or down (0 means no turn, 1 is top row or left column; 2 is bottom row or right column)
*/

    }

    public int turns(){

    }

    public Cube row(){

    }

    public Cube column(){

    }

    public Cube clockwise(){

    }

    public Cube counterClockwise(){

    }

    public Cube up(){

    }

    public Cube down(){

    }

    public Cube random(Cube cube){

    }

    public Cube configuration(Cube cube){

    }



}

Rubik's Cube:

public class RubiksCube {

    public RubiksCube(Cube cube){

    }

    public RubiksCube(Face front, Face rightOfFront, Face back, Face leftOfFront, Face top, Face bottom){

    }


    //calls face and colors and initializes the arrays into a object
    //default config: solid color on each side so each array, representing a face, is set to a solid color
    public void createNewCube(){

    }


    public void rotation(Cube cube, int row, int column, String direction, int turns){

    }

    public Cube configuration(Cube cube){//should return 6 Faces? or cube?

        return cube;

    }

}

2 个答案:

答案 0 :(得分:2)

考虑一下哪种数据结构使您最容易将多维数据集概念化。您提供的链接中的不同解决方案都有利有弊。您可以拥有更简洁的结构(即五个整数表示),它占用更少的内存并优化性能。但是,如果您不熟悉这个问题,那么这种表示可能很难处理。在光谱的另一端是一个面向对象的表示,它模拟了大多数人对rubik立方体的思考方式。这可能是新人使用rubik立方体的最佳方法。

在拥有对您有意义的数据结构之后,请考虑可以在多维数据集上执行的不同操作。您可以在改变数据状态的函数中捕获每个移动。如果你有一个真正的rubik立方体可以玩,找出所有不同的转弯是什么以及它们如何改变rubik立方体的值。然后尝试在自己的函数中对它们进行建模。即,最明智的转弯会导致六个面中的五个改变,对。这将导致四个面部接收其邻居的顶行。它也会导致顶面发生变化。底面不受影响。

如果您对复杂性感到不知所措,请尝试将问题分解为较小的问题。也许您可以尝试为2 x 2而不是3 x 3的rubik立方体编写表示。一旦掌握了较小的问题,请返回较大的问题。

答案 1 :(得分:0)

我刚刚开始编写一些代码来操作多维数据集。

package p;
import java.util.Arrays;
import static p.Facet.*;
enum Facet { // used for face, color, and operations
    u(1),d(1),r(2),l(0),f(1),b(3); // maybe FRULBD instead?
    Facet(int pad) {
        this.pad=pad;
    }
    // u pad n+1
    // l pad 0
    // f pad n+1
    // r pad 2(n+1)
    // b pad 3(n+1) or at the bottom.
    // d pad n+1
    final int pad; // for formatting
}
class Face {
    Face(int n,Facet facet) {
        this.n=n;
        this.facet=facet;
        facets=new Facet[n][n];
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
                facets[i][j]=facet;
    }
    Face(Face face) {
        this.n=face.n;
        this.facet=face.facet;
        facets=new Facet[n][n];
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
                facets[i][j]=face.facets[i][j];
    }
    @Override public String toString() {
        return toString(0);
    }
    public String toString(int pad) {
        StringBuffer stringBuffer=new StringBuffer();
        for(int i=0;i<n;i++) {
            stringBuffer.append(pad(pad,n));
            for(int j=0;j<n;j++)
                stringBuffer.append(facets[i][j]);
            stringBuffer.append('\n');
        }
        return stringBuffer.toString();
    }
    String pad() {
        return pad(facet.pad,n);
    }
    static String pad(int length) {
        StringBuffer stringBuffer=new StringBuffer(length);
        for(int i=0;i<length;i++)
            stringBuffer.append(" ");
        return stringBuffer.toString();
    }
    static String pad(int length,int n) {
        return pad(length*(n+1));
    }
    @Override public int hashCode() {
        final int prime=31;
        int result=1;
        result=prime*result+((facet==null)?0:facet.hashCode());
        result=prime*result+Arrays.deepHashCode(facets);
        result=prime*result+n;
        return result;
    }
    @Override public boolean equals(Object obj) {
        if(this==obj) return true;
        if(obj==null) return false;
        if(getClass()!=obj.getClass()) return false;
        Face other=(Face)obj;
        if(facet!=other.facet) return false;
        if(!Arrays.deepEquals(facets,other.facets)) return false;
        if(n!=other.n) return false;
        return true;
    }
    static void rotateClockwise(Object[][] objects) {
        Object temp;
        int n=objects.length;
        // For each concentric square around the middle of the matrix to rotate...
        // This value will be used as (m, n) offset when moving in.
        // Integer division by 2 will skip center if odd length.
        for(int i=0;i<n/2;i++)
            // for the length of this ring
            for(int j=0;j<n-2*i-1;j++) {
                temp=objects[i][i+j];
                objects[i][i+j]=objects[n-i-j-1][i];
                objects[n-i-j-1][i]=objects[n-i-1][n-i-j-1];
                objects[n-i-1][n-i-j-1]=objects[i+j][n-i-1];
                objects[i+j][n-i-1]=temp;
            }
    }
    static void rotateCounterClockwise(Object[][] objects) {
        int n=objects.length;
        for(int i=0;i<n/2;i++) {
            for(int j=i;j<n-i-1;j++) {
                Object temp=objects[i][j];
                objects[i][j]=objects[j][n-1-i]; // move values from right to top
                objects[j][n-1-i]=objects[n-1-i][n-1-j]; // move values from bottom to right
                objects[n-1-i][n-1-j]=objects[n-1-j][i]; // move values from left to bottom
                objects[n-1-j][i]=temp;
            }
        }
    }
    final int n;
    final Facet facet;
    final Facet[][] facets;
}
class Cube {
    Cube(int n) {
        u=new Face(n,Facet.u);
        d=new Face(n,Facet.d);
        r=new Face(n,Facet.r);
        l=new Face(n,Facet.l);
        f=new Face(n,Facet.f);
        b=new Face(n,Facet.b);
    }
    void rotatex(Face face,Face old) {
        for(int i=0;i<face.n;i++)
            for(int j=0;i<face.n;j++)
                face.facets[i][j]=old.facets[i][j];
    }
    void rotateConterClockwise(Face f,Face u,Face l,Face d,Face r) {
        for(int i=0;i<3;i++)
            rotate(f,u,l,d,r);
    }
    void rotate(Face f,Face u,Face l,Face d,Face r) {
        Face.rotateClockwise(f.facets);
        Facet[] top=new Facet[u.n];
        for(int i=0;i<u.n;i++)
            top[i]=u.facets[u.n-1][i];
        for(int i=0;i<u.n;i++) // move left to u
            u.facets[u.n-1][i]=l.facets[u.n-i-1][u.n-1];
        for(int i=0;i<u.n;i++) // bottom to left
            l.facets[u.n-i-1][u.n-1]=d.facets[0][i];
        for(int i=0;i<u.n;i++) // right to bottom
            d.facets[0][i]=r.facets[i][0];
        for(int i=0;i<u.n;i++)
            r.facets[i][0]=top[i];
    }
    void op(Facet facet) {
        switch(facet) {
            case b:
                rotate(b,u,r,d,l);
                break;
            case d:
                rotate(d,f,l,b,r);
                break;
            case f:
                rotate(f,u,l,d,r);
                break;
            case l:
                rotate(l,u,b,d,f);
                break;
            case r:
                rotate(r,u,f,d,b);
                break;
            case u:
                rotate(u,d,l,f,r);
                break;
        }
    }
    void opInverse(Facet facet) {
        switch(facet) {
            case b:
                rotateConterClockwise(b,u,r,d,l);
                break;
            case d:
                rotateConterClockwise(d,f,l,b,r);
                break;
            case f:
                rotateConterClockwise(f,u,l,d,r);
                break;
            case l:
                rotateConterClockwise(l,u,b,d,f);
                break;
            case r:
                rotateConterClockwise(r,u,f,d,b);
                break;
            case u:
                rotateConterClockwise(u,d,l,f,r);
                break;
        }
    }
    @Override public int hashCode() {
        final int prime=31;
        int result=1;
        result=prime*result+((b==null)?0:b.hashCode());
        result=prime*result+((d==null)?0:d.hashCode());
        result=prime*result+((f==null)?0:f.hashCode());
        result=prime*result+((l==null)?0:l.hashCode());
        result=prime*result+((r==null)?0:r.hashCode());
        result=prime*result+((u==null)?0:u.hashCode());
        return result;
    }
    @Override public boolean equals(Object obj) {
        if(this==obj) return true;
        if(obj==null) return false;
        if(getClass()!=obj.getClass()) return false;
        Cube other=(Cube)obj;
        if(b==null) {
            if(other.b!=null) return false;
        } else if(!b.equals(other.b)) return false;
        if(d==null) {
            if(other.d!=null) return false;
        } else if(!d.equals(other.d)) return false;
        if(f==null) {
            if(other.f!=null) return false;
        } else if(!f.equals(other.f)) return false;
        if(l==null) {
            if(other.l!=null) return false;
        } else if(!l.equals(other.l)) return false;
        if(r==null) {
            if(other.r!=null) return false;
        } else if(!r.equals(other.r)) return false;
        if(u==null) {
            if(other.u!=null) return false;
        } else if(!u.equals(other.u)) return false;
        return true;
    }
    @Override public String toString() { //ulfrbd
        StringBuffer stringBuffer=new StringBuffer(3*4*(u.n+1));
        for(int i=0;i<u.n;i++) {
            stringBuffer.append(u.pad());
            for(int j=0;j<u.n;j++)
                stringBuffer.append(u.facets[i][j]);
            stringBuffer.append('\n');
        }
        for(int i=0;i<u.n;i++) {
            stringBuffer.append(l.pad());
            for(int j=0;j<u.n;j++)
                stringBuffer.append(l.facets[i][j]);
            stringBuffer.append(' ');
            for(int j=0;j<u.n;j++)
                stringBuffer.append(f.facets[i][j]);
            stringBuffer.append(' ');
            for(int j=0;j<u.n;j++)
                stringBuffer.append(r.facets[i][j]);
            stringBuffer.append(' ');
            for(int j=0;j<u.n;j++)
                stringBuffer.append(b.facets[i][j]);
            stringBuffer.append('\n');
        }
        for(int i=0;i<u.n;i++) {
            stringBuffer.append(d.pad());
            for(int j=0;j<u.n;j++)
                stringBuffer.append(d.facets[i][j]);
            stringBuffer.append('\n');
        }
        return stringBuffer.toString();
    }
    final Face u,d,r,l,f,b;
}
public class Main {
    public static void main(String[] args) {
        Cube initial=new Cube(3);
        Cube cube=new Cube(3);
        System.out.println(cube.u.facets[0][0]);
        System.out.println(cube.u);
        System.out.println(cube);
        for(int i=0;i<4;i++) {
            cube.op(Facet.f);
            System.out.println(cube);
        }
        // F' U L' U'
        cube=new Cube(3);
        int i=0;
        do {
            fpulpup(cube);
            System.out.println(i);
            System.out.println(cube);
            i++;
        } while(!cube.equals(initial));
    }
    private static void fpulpup(Cube cube) {
        cube.opInverse(f);
        cube.op(u);
        cube.opInverse(l);
        cube.opInverse(f);
    }
}