Solver : Cubie Scanning -> algorithm execution

Hello, I have worked on a Rubik's Cube Simulator since months and I try to make work my solver but it crash the sketch every time and work once out of 6 times and I've no idea what is exactly the problem so here the code:

void solve(String method){//method used to solve the Rubik's cube
  solverStat = "inspecting ...";
  if(!rc.isSolved()){
    println(rc.codeString());
    if(method.toLowerCase()=="undo" || method.toLowerCase() == solvingMethod[0]){//robot's method
      while(!rc.isSolved()){//tant que le cube n'est pas résolue l'IA undo les mouvementss
        undo();
      }
    }else if(method.toLowerCase()=="beginner" || method.toLowerCase()=="lbl" || method.toLowerCase() == solvingMethod[1]){//Beginner's method
      //Cube scanning to find cubies
      int[] UFpos = getCubie("UF"), URpos = getCubie("UR"), UBpos = getCubie("UB"), ULpos = getCubie("UL");
      if(UFpos[0]>=3) UFpos = getCubie("FU");//if the cubie isn't in/on the cube
      //indicate the position of the desired cubies
      solverStat = "searching solution ...\nUF("+UFpos[0]+", "+UFpos[1]+", "+UFpos[2]+"), UR("+URpos[0]+", "+URpos[1]+", "+URpos[2]+"), UB("+UBpos[0]+", "+UBpos[1]+", "+UBpos[2]+"), UL("+ULpos[0]+", "+ULpos[1]+", "+ULpos[2]+")";
      println(solverStat);//display the solver's stat
      //UF
      println("UF is at: "+UFpos[0]+", "+UFpos[1]+", "+UFpos[2]);
      whoIs("UF");//At which place the UF cubie is
      if(!cubieInPlace("UF")){//If this cubie isn't in place
        solverStat = "placing UF";
        if(cubieIsOriented("UF")){//good edge
          //cf fiche
          if(UFpos[0]==1 && UFpos[1]==0 && UFpos[2]==2) moveStr = "FF";//MDDm
          else if(UFpos[0]==0 && UFpos[1]==1 && UFpos[2]==2) moveStr = "F";
          else if(UFpos[0]==2 && UFpos[1]==1 && UFpos[2]==2) moveStr = "f";
          else if(UFpos[0]==0 && UFpos[1]==0 && UFpos[2]==1) moveStr = "DFF";
          else if(UFpos[0]==2 && UFpos[1]==0 && UFpos[2]==1) moveStr = "dFF";
        }else{//bad edge (wrong orientation)
          if(UFpos[0]==1 && UFpos[1]==0 && UFpos[2]==2) moveStr = "DMdm";//dMDm
          else if(UFpos[0]==0 && UFpos[1]==1 && UFpos[2]==2) moveStr = "Ulu";
          else if(UFpos[0]==2 && UFpos[1]==1 && UFpos[2]==2) moveStr = "uRU";
          else if(UFpos[0]==0 && UFpos[1]==0 && UFpos[2]==1) moveStr = "lFl";
          else if(UFpos[0]==2 && UFpos[1]==0 && UFpos[2]==1) moveStr = "Rfr";
          else if(UFpos[0]==1 && UFpos[1]==2 && UFpos[2]==2) moveStr = "FuRU";//fUlu or FFDMdm or ffdMDm
        }
      }else rc.rotU();//Y
      algorithm = moveStr;moveStrValid = true;//moves validation
    }else if(method.toLowerCase()=="fridrich" || method.toLowerCase()=="cfop" || method.toLowerCase() == solvingMethod[2]){//speedcuber's method
      
    }else if(method.toLowerCase()=="petrus" || method.toLowerCase() == solvingMethod[3]){//...
      
    }else if(method.toLowerCase()=="roux" || method.toLowerCase() == solvingMethod[4]){
      
    }else if(method.toLowerCase()=="edgefirst" || method.toLowerCase() == solvingMethod[5]){
      
    }else if(method.toLowerCase()=="cornerfirst" || method.toLowerCase() == solvingMethod[6]){
      
    }else if(method.toLowerCase()=="zz" || method.toLowerCase() == solvingMethod[7]){
      
    }else if(method.toLowerCase()=="vh" || method.toLowerCase() == solvingMethod[8]){
      
    }else if(method.toLowerCase()=="m2 3op" || method.toLowerCase() == solvingMethod[9]){//BLD method for speedcubers
      
    }else{
      println("the method selected to solve the cube isn't available for the moment.\nThe methods available are: "+solvingMethod);//indique que la méthode choisi n'est pas disponible et celles disponibles
    }
  }else{//If the cube is solved, it anounce it
    solverStat = "cube solved";
    fill(255, 0, 0);
    textSize(24);
    text("Solved", 60, height/2);
    save("data/cubeStyle-"+cubeStyleSelected+".png");
  }
  println(solverStat);
}
String[][][] getCubiePos(int[] fpos, String code){
  String[][][] gpos = {{{code}}};
  gpos[fpos[0]][fpos[1]][fpos[2]] = code;
  return gpos;
}
void whoIs(String ccode){//who is the cubie
  if(cubieInPlace(ccode)) println(ccode+" is in is place");
  else println(ccode+" is in the place of "+rc.grid[getCubie(ccode)[0]][getCubie(ccode)[1]][getCubie(ccode)[2]].code);
}
String[][][] findCubie(String ccode){
  int[] pos = {0};
  String[][][] cpos;
  for(int x=0; x<3; x++){
    for(int y=0; y<3; y++){
      for(int z=0; z<3; z++){
        //int[][][] pos = {x{y{z}}};
        if(rc.grid[x][y][z].code.equals(ccode)){pos[0] = x; pos[1] = y; pos[2] = z;}
      }
    }
  }
  cpos = getCubiePos(pos, ccode);
  return cpos;
}
int[] getCubie(String code){//scan to find the cubie that has the code
  int x=findCubieX(code), y=findCubieY(code), z=findCubieZ(code);
  String[] ncode;
  if(x>=3||x<0){//If the cubie is inexistant or out of the cube
    String tmp;
    ncode = split(code, "");
    if(ncode.length==2){tmp=ncode[0];ncode[0]=ncode[1];ncode[1]=tmp;}
    else{tmp=ncode[2];ncode[2]=ncode[1];ncode[1]=ncode[0];ncode[0]=tmp;}
    code = join(ncode, "");
    x=findCubieX(code);
    y=findCubieY(code);
    z=findCubieZ(code);
  }
  if(x>=3||x

And the dead line is the 21 of may (this month).

Please help me, I've asked to anyone who knows about programming and Processing but non of them could help. So I'll appreciate your help.

Answers

  • we can't run the code since it is not complete

    you wrote:

    crash the sketch every time

    what happens exactly? which line? You should mark the important part

    also you need to explain what the concept is

    long parts above are commented out with /* */ so why post them?

    comments are in French, better use English

  • I don't know what "crash the sketch" means either. You should be a bit more precise.

    I see an obvious error. See String. Don't compare strings with ==.

  • edited May 2014

    Ho yes sorry guys: here is it:

      if(x>=3||x<0){
        String tmp;
        ncode = split(code, "");
        if(ncode.length==2){tmp=ncode[0];ncode[0]=ncode[1];ncode[1]=tmp;}
        else{tmp=ncode[2];ncode[2]=ncode[1];ncode[1]=ncode[0];ncode[0]=tmp;}
        code = join(ncode, "");
        x=findCubieX(code);
        y=findCubieY(code);
        z=findCubieZ(code);
      }
      int[] p={x, y, z};
      return p;
    }
    boolean cubieInPlace(String ccode){//Si le cubie à besoin d'être permuter ou non (si c'est en place)
      int[] p=getCubie(ccode);
      if(rc.grid[p[0]][p[1]][p[2]].code.equals(ccode)) return true;
      else return false;
    }
    boolean cubieIsOriented(String ccode){//Si le cubie à besoin d'être orienter ou non (si les stickers sont bien placés)
      int[] p=getCubie(ccode);
      if(rc.grid[p[0]][p[1]][p[2]].code.equals(ccode)) return true;
      else{
        String tmp;
        String[] arrCode = split(ccode, "");
        if(ccode.length()==2){tmp=arrCode[0];arrCode[0]=arrCode[1];arrCode[1]=tmp;}
        else{tmp=arrCode[2];arrCode[2]=arrCode[1];arrCode[1]=arrCode[0];arrCode[0]=tmp;}
        ccode = join(arrCode, "");
        if(rc.grid[p[0]][p[1]][p[2]].code.equals(ccode)) return false;
        else if(ccode.length()==3){
          tmp=arrCode[2];arrCode[2]=arrCode[1];arrCode[1]=arrCode[0];arrCode[0]=tmp;
          ccode=join(arrCode, "");
          if(rc.grid[p[0]][p[1]][p[2]].code.equals(ccode)) return false;
        }
        return false;
      }
    }
    int findCubieX(String code){//cherche la coordonné X du cubie voulu
      int x=0;
      for(x=0; x<3; x++){
        for(int y=0; y<3; y++){
          for(int z=0; z<3; z++){
            if(rc.grid[x][y][z].code.equals(code)) return x;
          }
        }
      }
      return x;
    }
    int findCubieY(String code){//cherche la coordonné Y du cubie voulu
      int y=0;
      for(int x=0; x<3; x++){
        for(y=0; y<3; y++){
          for(int z=0; z<3; z++){
            if(rc.grid[x][y][z].code.equals(code)) return y;
          }
        }
      }
      return y;
    }
    int findCubieZ(String code){//cherche la coordonné Z du cubie voulu
      int z=0;
      for(int x=0; x<3; x++){
        for(int y=0; y<3; y++){
          for(z=0; z<3; z++){
            if(rc.grid[x][y][z].code.equals(code)) return z;
          }
        }
      }
      return z;
    }
    
  • edited May 2014

    @Chrisir: it doesn't show which line is problematic, btw I've translated all into english (I had to put it in french because it's required). The concept of the solver is that it allows the computer to solve the Rubik's cube in it current state with the possibility to change the method, in all case the rules of the AI is to search a desired cubie than depending on the position and the orientation of this cubie it will apply a specific algorithm to solve the cubie and do that for every cubie unteal it has solved the Rubik's cube

  • String foo = "Foo";
    String bar = foo;
    
    if (foo == bar)
      println("It works because they are the same object");
    
    if (foo == "Foo")
      println("It works because Java sees they are the same string at compilation time and makes them te same object.");
    
    if (foo.toLowerCase() == "foo")
      println("It doesn't work because they are not the same object");
    
    if (foo.toLowerCase().equals("foo"))
      println("It works because that's how Java is designed...");
    
  • @PhiLho where's the error ? Is this for debugging or what ?

  • edited May 2014

    line 5, 9, 38, 40 ... everywhere ;-)

    as he wrote: every string must be compared with equals -- never use == for string pls

  • edited May 2014

    line 38, 40 ? It's correct. What's the difference between foo.toLowerCase().equals("foo") and foo.toLowerCase() == "foo" ?

  • == doesn't work with string

    equals works

    try it with philhos example

  • Okay, I understand now this glichy problem but it doesn't solve the main problem

  • edited May 2014

    this occurs very often in your code...

    i'm referring to the 1st post

    also in line 39,41 etc. nothing happens, there is a long if condition and then nothing between { and }

    I don't understand this...

    I can't help you with that anyway since I don't know how to solve the cube. I'm sorry.

    :-S :-S :-S

  • "where's the error ?"
    Have you tried to run the code I shown? One line is missing, the one where the result of toLowerCase() is compared with ==

    If your code is faulty at something as fundamental as this, there is no point in trying to fix something else, until this is OK, at least.

  • @Chrisir: l.39-41 is a placeholder for the next solving methods but first LbL has to work than I'll work on the next ones. @PhiLho yes I've ran it and saw the error and I've corrected all the conditions comparing strings but the problem isn't solved yet :-( So now, let's see other things

  • edited May 2014

    crash

    you wrote it crashes

    but you don't know where

    but we can't run your code.

    please post your entire code so we can run it (or somebody else who knows the topic)

    also you just can place println("1"); println("2"); println("3"); and thus see how far he goes until he crashes (or write to textfile when he really crashes hard)

    this line

    this line alone

    if(method.toLowerCase()=="beginner" || method.toLowerCase()=="lbl" || method.toLowerCase() == solvingMethod[1]){

    looks strange to me. Why not unify those?

    • Why not use method = method.toLowerCase(); once and not 30 times?

    • Why not use switch (method) { ?

    • Why not unify beginner / lbl / solvingMethod[1] to one?

    solver

    did you search the forum for rubick' s cube or so? There was another thread some weeks ago

    here

    http://forum.processing.org/two/discussion/2493/how-to-simulate-a-rubiks-cube/p1

  • @Chrisir: good idea an btw here's the entire code:

    /*
    Projet final d'ISN 2013-2014
    auteur: Berkmann Maximilian
    */
    float M[][] = new float[4][4];
     //descritif des styles de cubes
    color cubeFaceColors[] = {//défaut
      //D, B, R, F, L, U
      color(255, 255, 0), color(255, 127, 0), color(0, 0, 255), color(255, 0, 0), color(0, 255, 0), color(255)
    }, vCubeFC[] = {//VCube
      color(127), color(255, 127, 0), color(0, 0, 255), color(255, 0, 0), color(0, 255, 0), color(0)
    }, girlCFC[] = {//fille
      color(255, 255, 0), color(255, 127, 0), color(255, 0, 255), color(255, 16, 120), color(0, 255, 0), color(255)
    }, cF2C[] = {//blanc et noir
      color(255), color(255), color(0), color(0), color(255), color(0)
    }, cF3C[] = {//rouge, vert et bleu
      color(0, 255, 0), color(255, 0, 0), color(0, 0, 127), color(127, 0, 0), color(0, 0, 255), color(0, 127, 0)
    }, MirrorFC[] = {//couleur argent du cube Mirror
      color(210), color(210), color(210), color(210), color(210), color(210)
    }, MinxFC[] = {//cyan, magenta et orange
      color(0, 255, 0), color(255, 0, 0), color(0, 255, 255), color(255, 255, 0), color(0, 0, 255), color(255, 0, 255)
    }, OldStyle[] = {//noir, gris et blanc
      color(255), color(127), color(0), color(255), color(127), color(0)
    }, WCAClrSch[] = {//Schéma de couleur de la WCA
      color(255, 255, 0), color(0, 0, 255), color(255, 0, 0), color(0, 255, 0), color(255, 128, 0), color(255)
    }, TwoFC[] = {//seulement 2 faces
      color(255, 255, 0), color(128, 64), color(128, 64), color(128, 64), color(128, 64), color(255)
    }, Visual[] = {//Schéma de couleur de Visual Cube
      color(255, 255, 0, 127), color(0, 0, 255, 127), color(255, 0, 0, 127), color(0, 255, 0, 127), color(255, 128, 0, 127), color(255, 127)
    };
    //axe (0-3), tranche (0-3), direction (1: sens des aiguilles d'une montre; -1: sens inverse des aiguilles d'une montre)
    int axis=0, slice=2, direction=1, speed=10, nbOfMoves = 0;//vitesse: défaut=3; max=16;
    float theta = 0.0;//angle theta
     
    boolean orient=false;//cube orienté
    boolean firstRun = true;//début de l'animation
    float xRot=-35.264, yRot=45, zRot=0;//rotation en x, en y et en z
     
    PVector frontBound[], topBound[], rightBound[], downBound[], backBound[], leftBound[];//attachement des faces avec le centres du cube
    float backViewDisp;//position de la vue arrière
     
    stack stackOfMoves = new stack();//stack de mouvement
    rubikCube rc;//Rubik's cube
     
    String moveStr, algorithm = "", solverStat = "";//chaine de mouvement, algorithme affiché, état du solveur, algorithme pour undo algorithm
    boolean moveStrValid = false;//validité du mouvement pour éviter la répétition involontaire de mouvements
    int strMoveCount=0;//nombre de mouvements
     
    boolean inMove = false;//indication du cube si c'est en mouvement ou non
    int thetaCount = 0, cubeStyleSelected = 0;//comptage de l'angle, style du cube sélectionner
    
    String[] solvingMethod = {"undo", "Beginner\'s", "Fridrich", "Petrus", "Roux", "EdgeFirst", "CornerFirst", "ZZ", "VH", "M2 3OP"},//méthode de résolution
      cubeStyles = {"classic", //bordure noir, couleur de base (normale)
                    "VCube", //bordure blanche, noir au lieu de blanc et gris au lieu de jaune
                    "girlish", //bordure jaune, magenta au lieu de bleu et rose au lieu de rouge
                    "whiteAndBlack", //cube blanc et noir
                    "rgb", //rouge, vert et bleu
                    "mirror", //même couleur que le Mirror Cube (BLD cube)
                    "minx", //Couleur du Megaminx en plus des couleurs classiques
                    "OldStyle", //sans couleur
                    "Heise\'s", //cube de Ryan Heise
                    "WCA", //cube de la WCA
                    "2F", //Couleur de 2 faces
                    "Visual" //transparent
      };
    char[] undoStr;
    color cubiesBorder = color(255);//couleur de la bordure du cube
    
    void setup(){
      chCubeStyle(0);//change le style du cube
      size(1210, 600, OPENGL);//Taille et moteur de rendu
      ortho();//orthogonalité des formes
      strokeJoin(ROUND);//jointure ronde
      frame.setTitle("Rubik's Cube Simulator");//titre
      rc = new rubikCube(height/8);//création du cube
      if(cubeStyleSelected==8) rc.setSize(5); //100 par défaut (séparation des cubies)
     
      rc.cubePosition = new PVector(width/3, height/2.0, 0.0);//position du cube
      backViewDisp = width/3;//vue arrière au tier de la fenêtre en longueur
      for(int i=0;i<8;i++){//dessin des faces
        rot(rc.frontY, 1, rc.boundary.points[i]);//face avant en Y
        rot(rc.frontX, 0, rc.boundary.points[i]);//face avant en X
        trans(rc.cubePosition.x, rc.cubePosition.y, rc.cubePosition.z, rc.boundary.points[i]);//coin avant
        rot(rc.backY, 1, rc.boundary2.points[i]);//face arrière en Y
        rot(rc.backX, 0, rc.boundary2.points[i]);//face arrière en X
        trans(rc.cubePosition.x + backViewDisp, rc.cubePosition.y, rc.cubePosition.z, rc.boundary2.points[i]);//coin arrière
      }
      computeBoundaries();//attachement et frottement des cubies entre eux et entre le centre
      //scramble();
    }
     
    void draw(){
      //if(cubeStyleSelected<cubeStyles.length) cubeStyleSelected++;
      //else cubeStyleSelected=0;
      background(200);//effacement du fond
      if(!inMove && moveStrValid) strOfMoves();//autorisation de l'exécution des mouvements
      move(false);//reste sur le premier mouvement
      strokeWeight(5.0);//épaisseur des bordures
      //rc.drawBound(); bordure fixe
      pushMatrix();//matrice géométrique lancer
      translate(rc.cubePosition.x, rc.cubePosition.y, rc.cubePosition.z);
      pushMatrix();//sous matrice géométrique (cube avant)
      rotateX(radians(rc.frontX));//rotation du cube en X
      rotateY(radians(rc.frontY));//... en Y
     
      rc.drawRubikCube(theta);//dessine le cube avant (le 1er à gauche)
      popMatrix();//fermeture de la sous matrice
      translate(backViewDisp, 0, 0);//cube arrière
      rotateX(radians(rc.backX));
      rotateY(radians(rc.backY));
      rc.drawRubikCube(0.0); //dessine le cube arrière (le deuxième à droite)
      popMatrix();//ferme la matrice
      textSize(20);
      text(nbOfMoves+" moves", width/2, height-40);//affiche le nombre de mouvement sur le sketch
      if(nbOfMoves>0 && algorithm != "" && inMove) println("moves: "+nbOfMoves);//dans la console
      if(algorithm.length()>0){
        text("scramble: "+algorithm, 20, 40);//affiche le mélange
        if(inMove) println("scramble: "+algorithm);//affiche le mélange dans la console
      }
      textSize(15);
      text(rc.codeString(), width/2-80, height-20);
      fill(255, 0, 0);
      textSize(24);
      if(rc.isSolved()) text("Solved", 60, height/2);//si le cube est résolu alors ça l'indique
      fill(0);
      textSize(30);
      text(min+":"+s+"."+ms, 50, height-50);//affiche le temps
      textSize(24);
      text("cube style: "+cubeStyles[cubeStyleSelected], width-250, height-45);//indique le style choisi
      //slowMove();
    }
    class cube{//cubie
      PVector pos;//position
      int id, size;//numéro d'identification, taille
      PVector points[];//points de construction
      float angX, angY, angZ;//angles
      String code;//code
     
      cube(int id, int size){//constructeur de cube
        this.id = id;//assignation du paramètre à l'attribut
        pos = new PVector(0, 0, 0);//initialisation vectoriel
        points = new PVector[8];//création du tableau vectoriel
        for(int i=0;i<8;i++) points[i] = new PVector();//remplissage du tableau cellule par cellule
        this.size = size;
        for(int i=0;i<8;i++){//position des points celon les signes de chaque coordonnées
          int xSign = (i%2==0)?1:-1;
          int ySign = (i/4 == 0)?1:-1;
          int zSign = ((i/2)%2 == 0)?1:-1;
          points[i].x = xSign*size/2.0;
          points[i].y = ySign*size/2.0;
          points[i].z = zSign*size/2.0;
        }
        angX = angY = angZ = 0.0;//remise à zero des angles (angZ=0;angY=angZ;angX=angY;) 
        code = new String("");//code vide
      }
     
      void setPos(PVector p){//assigne la position
        for(int i=0;i<8;i++) trans(p.x, p.y, p.z, points[i]);
      }
     
      void findCenter(){//trouve les centres pour les correspondances cubies-centres
        PVector temp;//vecteur temporaire
        temp = PVector.add(points[0], points[7]);//ajout des points d'extremité du vecteur
        temp.div(2.0);//division en 2
      }
     
      void drawCube(PVector t){//dessine le cubie
        int idx[] = {//tableau à numéro d'identification de cubie
          0, 1, 3, 2, 3, 7, 6, 2, 0, 2, 6, 4, 0, 4, 5, 1, 1, 5, 7, 3, 4, 6, 7, 5
        };
        for(int i=0;i<8;i++) rot(angY, 1, points[i]);//rotation en Y
        for(int i=0;i<8;i++) rot(angX, 0, points[i]);//rotation en X
        for(int i=0;i<8;i++) rot(angZ, 2, points[i]);//rotation en Z
        angX = angY = angZ = 0.0;
        for(int i=0;i<6;i++){
          if((this.id & (1<<i)) != 0) fill(cubeFaceColors[i]);
          else fill(0);
          stroke(cubiesBorder);//bordure du cubie
          beginShape(QUADS);//déclaration d'une forme de type quadrilatère
          for(int j=0;j<4;j++){
            int pt = idx[i*4+j];//chaque point recoive un id
            vertex(this.points[pt].x, this.points[pt].y, this.points[pt].z);//créer un vertex à chaque endroits spécifié dans le tableau de points
          }
          endShape();//fermeture de la déclaration
        }
        findCenter();//recherche de centre pour assurer une cohérence des faces
      }
     
      PVector getCenter(){//retourne le centre
        return this.pos;//la position du cubie
      }
    }
    class stack{//stack de donné
      char data[];//tableau de donné
      int top;//seuil
     
      stack(){//constructeur de stack
        //initialisation des attributs
        top = -1;
        data = new char[9999];
      }
     
      void push(char v){//ajout d'un caractère
        if(top < 9999) data[top++] = v;//si le seuil n'est pas au maximum
      }
      char pop(){//enlève un caractère
        if(top>=0) return data[top--];//si le seuil n'est pas au minimum
        return 1;
      }
      boolean isEmpty(){//indique si le stack est vide
        return (top<0);//si top<0: top=-1; ce qui signifie que top n'a pas était modifier donc pas d'ajout ou de suppression de donné
      }
      void reset(){//réinitialise le stack
        top = -1;
      }
    }
    class rubikCube{//Rubik's cube
      cube grid[][][];//grille à cubie
      cube boundary, boundary2;//frontière avant et arrière
      PVector cubePosition;//vecteur de position du cube
      char UP, FRONT, RIGHT, BACK, LEFT, DOWN;//face
      int GREEN, BLUE, WHITE, YELLOW, ORANGE, RED, size;//id des couleur, taille
      float frontX, frontY, backX, backY;//angle de vue avant/arrière en X/Y
     
      rubikCube(int sz){//constructeur de Rubik's cube (sz: écartement de cubie)
        //attribution des id au couleur
        WHITE = 32;
        RED = 8;
        BLUE = 4;
        ORANGE = 2;
        GREEN = 16;
        YELLOW = 1;
     
        grid = new cube[3][][];//établissement de la grille en X
        for(int i=0;i<3;i++){//.. en Y
          grid[i] = new cube[3][];
          for(int j=0;j<3;j++){//.. en Z
            grid[i][j] = new cube[3];
          }
        }
     
        int code=0;//code de correspondance avec les couleurs
        //coloration des cubies
        for(int x=0;x<3;x++){
          for(int y=0;y<3;y++){
            for(int z=0;z<3;z++){
              if(x==0) code |= GREEN;//si c'est la face gauche (L)
              else if(x==2) code |= BLUE;//sinon si c'est la face droite (R)
              if(y==0) code |= YELLOW;//si c'est la face du bas (D)
              else if(y==2) code |= WHITE;//sinon si c'est la face du haut (U)
              if(z==2) code |= RED;//si c'est la face avant (F)
              else if(z==0) code |= ORANGE;//sinon si c'est la face arrière (B)
     
              grid[x][y][z] = new cube(code, sz);//remplissage de la grille par des cubies
              code = 0;//remise à zero du code
            }
          }
        }
        //association face-mouvement
        UP = 'U';
        DOWN = 'D';
        FRONT = 'F';
        BACK = 'B';
        RIGHT = 'R';
        LEFT = 'L';
        //mise des valeurs des angles de vue
        frontY = -45.0;
        frontX = -23.26;
        backX = -frontX;
        backY = frontY+180;
     
        setSize(sz);//met l'écartement à sz
        assignCode();//assignation de code propre à chaque cubie
        //création des frontières
        boundary = new cube(0, 3*size);
        boundary2 = new cube(0, 3*size);
      }
     
      void assignCode(){//assignation de code à chaque cubie de la grille
        //arrêtes (2 lettres==2 stickers)
        grid[1][2][2].code = new String("UF");
        grid[2][2][1].code = new String("UR");
        grid[1][2][0].code = new String("UB");
        grid[0][2][1].code = new String("UL");
        grid[1][0][2].code = new String("DF");
        grid[2][0][1].code = new String("DR");
        grid[1][0][0].code = new String("DB");
        grid[0][0][1].code = new String("DL");
        grid[2][1][2].code = new String("FR");
        grid[0][1][2].code = new String("FL");
        grid[2][1][0].code = new String("BR");
        grid[0][1][0].code = new String("BL");
        //coins
        grid[2][2][2].code = new String("UFR");
        grid[2][2][0].code = new String("URB");
        grid[0][2][0].code = new String("UBL");
        grid[0][2][2].code = new String("ULF");
        grid[2][0][2].code = new String("DRF");
        grid[0][0][2].code = new String("DFL");
        grid[0][0][0].code = new String("DLB");
        grid[2][0][0].code = new String("DBR");
      }
     
      void lTurn(){//rotation en L
        grid[0][2][2].code = rotateStr(grid[0][2][2].code, 1);//ULF
        grid[0][2][0].code = rotateStr(grid[0][2][0].code, 2);//UBL
        grid[0][0][0].code = rotateStr(grid[0][0][0].code, 1);//DLB
        grid[0][0][2].code = rotateStr(grid[0][0][2].code, 2);//DFL
      }
      void rTurn(){//rotation en R
        grid[2][2][2].code = rotateStr(grid[2][2][2].code, 2);//UFR
        grid[2][2][0].code = rotateStr(grid[2][2][0].code, 1);//URB
        grid[2][0][0].code = rotateStr(grid[2][0][0].code, 2);//DBR
        grid[2][0][2].code = rotateStr(grid[2][0][2].code, 1);//DRF
      }
      void fTurn(){//rotation en F
        grid[1][2][2].code = flipEdge(grid[1][2][2].code);//UF
        grid[1][0][2].code = flipEdge(grid[1][0][2].code);//DF
        grid[2][1][2].code = flipEdge(grid[2][1][2].code);//FR
        grid[0][1][2].code = flipEdge(grid[0][1][2].code);//FL
     
        grid[2][2][2].code = rotateStr(grid[2][2][2].code, 1);//UFR
        grid[0][0][2].code = rotateStr(grid[0][0][2].code, 1);//DFL
        grid[2][0][2].code = rotateStr(grid[2][0][2].code, 2);//DRF
        grid[0][2][2].code = rotateStr(grid[0][2][2].code, 2);//ULF
      }
      void bTurn(){//.. en B
        grid[1][2][0].code = flipEdge(grid[1][2][0].code);//UB
        grid[1][0][0].code = flipEdge(grid[1][0][0].code);//DB
        grid[2][1][0].code = flipEdge(grid[2][1][0].code);//BR
        grid[0][1][0].code = flipEdge(grid[0][1][0].code);//BL
     
        grid[2][2][0].code = rotateStr(grid[2][2][0].code, 2);//URB
        grid[0][2][0].code = rotateStr(grid[0][2][0].code, 1);//UBL
        grid[0][0][0].code = rotateStr(grid[0][0][0].code, 2);//DLB
        grid[2][0][0].code = rotateStr(grid[2][0][0].code, 1);//DBR
      }
    
    
  •  
      String codeString(){//affiche la chaine de code au format singmaster (utiliser dans les fichier .sgm)
        return new String(grid[1][2][2].code + " " + grid[2][2][1].code + " " + grid[1][2][0].code + " " + grid[0][2][1].code + " " + grid[1][0][2].code + " " + grid[2][0][1].code
          + " " + grid[1][0][0].code + " " + grid[0][0][1].code + " " + grid[2][1][2].code + " " + grid[0][1][2].code + " " + grid[2][1][0].code + " " + grid[0][1][0].code
          + " " + grid[2][2][2].code + " " + grid[2][2][0].code + " " + grid[0][2][0].code + " " + grid[0][2][2].code + " " + grid[2][0][2].code + " " + grid[0][0][2].code
          + " " + grid[0][0][0].code + " " + grid[2][0][0].code);
      }
      boolean isSolved(){//si le cube est résolu ça retourne vrai sinon faux
        //c'est-à-dire si chaque code des cubies corresponde avec celui à l'état résolu
        return grid[1][2][2].code.equals("UF") && grid[2][2][1].code.equals("UR") && grid[1][2][0].code.equals("UB") && grid[0][2][1].code.equals("UL") 
          && grid[1][0][2].code.equals("DF") && grid[2][0][1].code.equals("DR") && grid[1][0][0].code.equals("DB") && grid[0][0][1].code.equals("DL")
            && grid[2][1][2].code.equals("FR") && grid[0][1][2].code.equals("FL") && grid[2][1][0].code.equals("BR") && grid[0][1][0].code.equals("BL")
              && grid[2][2][2].code.equals("UFR") && grid[2][2][0].code.equals("URB") && grid[0][2][0].code.equals("UBL") && grid[0][2][2].code.equals("ULF")
                && grid[2][0][2].code.equals("DRF") && grid[0][0][2].code.equals("DFL") && grid[0][0][0].code.equals("DLB") && grid[2][0][0].code.equals("DBR");
      }
      void setSize(int size){//écartement cubie-cubie
        PVector p;
        //décalage en coordonné
        int xOff, yOff, zOff;
        xOff = -size;
        for(int x=0;x<3;x++){
          yOff = size;
          for(int y=0;y<3;y++){
            zOff = -size;
            for(int z=0;z<3;z++){
              p = new PVector();
              p.x = xOff;
              p.y = yOff;
              p.z = zOff;
              grid[x][y][z].setPos(p);//position individuelle
              zOff += size;
            }
            yOff -= size;
          }
          xOff += size;
        }
        this.size = size;
      }
     
      void drawRubikCube(float th){//dessine le cube en fonction de la valeur de l'angle theta
        for(int x=0;x<3;x++)
          for(int y=0;y<3;y++)
            for(int z=0;z<3;z++){
              if(axis==0 && x==slice) grid[x][y][z].angX = th;
              else if(axis==1 && y==slice) grid[x][y][z].angY = -th;
              else if(axis==2 && z==slice) grid[x][y][z].angZ = th;
              grid[x][y][z].drawCube(cubePosition);//dessine chaque cubie selon la position du cube
            }
      }
     
      void updateRotate(int a, int s, int d){//met à jour les rotations (a: axis (axe); s: slice (tranche), d: direction)
        cube temp;//cubie temporaire
        //PVector tpos;
        if(d == 1){//sens des aiguilles d'une montre
          if(a == 0){//première axe
            //affection en queue (grid[s][0][0]->grid[s][2][0]->grid[s][2][2]->grid[s][0][2]->temp)
            temp = grid[s][0][0];//dernier valeur à affecter donc mise dans une variable temporaire pour ne pas la perdre
            grid[s][0][0] = grid[s][2][0];
            grid[s][2][0] = grid[s][2][2];
            grid[s][2][2] = grid[s][0][2];
            grid[s][0][2] = temp;
            temp = grid[s][1][0];
            grid[s][1][0] = grid[s][2][1];
            grid[s][2][1] = grid[s][1][2];
            grid[s][1][2] = grid[s][0][1];
            grid[s][0][1] = temp;
          }else if(a == 1){//axe centrale
            temp = grid[0][s][2];
            grid[0][s][2] = grid[2][s][2];
            grid[2][s][2] = grid[2][s][0];
            grid[2][s][0] = grid[0][s][0];
            grid[0][s][0] = temp;
            temp = grid[0][s][1];
            grid[0][s][1] = grid[1][s][2];
            grid[1][s][2] = grid[2][s][1];
            grid[2][s][1] = grid[1][s][0];
            grid[1][s][0] = temp;
          }else{//dernier axe
            temp = grid[0][0][s];
            grid[0][0][s] = grid[2][0][s];
            grid[2][0][s] = grid[2][2][s];
            grid[2][2][s] = grid[0][2][s];
            grid[0][2][s] = temp;
            temp = grid[1][0][s];
            grid[1][0][s] = grid[2][1][s];
            grid[2][1][s] = grid[1][2][s];
            grid[1][2][s] = grid[0][1][s];
            grid[0][1][s] = temp;
          }
        }else{
          if(a == 0){
            temp = grid[s][0][2];
            grid[s][0][2] = grid[s][2][2];
            grid[s][2][2] = grid[s][2][0];
            grid[s][2][0] = grid[s][0][0];
            grid[s][0][0] = temp;
            temp = grid[s][0][1];
            grid[s][0][1] = grid[s][1][2];
            grid[s][1][2] = grid[s][2][1];
            grid[s][2][1] = grid[s][1][0];
            grid[s][1][0] = temp;
          }else if(a == 1){
            temp = grid[0][s][0];
            grid[0][s][0] = grid[2][s][0];
            grid[2][s][0] = grid[2][s][2];
            grid[2][s][2] = grid[0][s][2];
            grid[0][s][2] = temp;
            temp = grid[1][s][0];
            grid[1][s][0] = grid[2][s][1];
            grid[2][s][1] = grid[1][s][2];
            grid[1][s][2] = grid[0][s][1];
            grid[0][s][1] = temp;
          }else{
            temp = grid[0][2][s];
            grid[0][2][s] = grid[2][2][s];
            grid[2][2][s] = grid[2][0][s];
            grid[2][0][s] = grid[0][0][s];
            grid[0][0][s] = temp;
            temp = grid[0][1][s];
            grid[0][1][s] = grid[1][2][s];
            grid[1][2][s] = grid[2][1][s];
            grid[2][1][s] = grid[1][0][s];
            grid[1][0][s] = temp;
          }
        }
        //mise à jour des faces concerné pour éviter de le faire à tout le cube pouvant causé une invalidité du cube
        if(a == 2 && s == 2) fTurn();
        else if(a == 2 && s == 0) bTurn();
        else if(a == 0 && s == 2) rTurn();
        else if(a == 0 && s == 0) lTurn();
      }
     
      void drawBound(){//dessine les frontières
        noFill();//pas de remplissage
        stroke(0);//bordure noir
        beginShape();//début de forme
        for(int i=0;i<4;i++) vertex(leftBound[i].x, leftBound[i].y, leftBound[i].z);//vertex que comporte un carré
        endShape(CLOSE);//fermeture
      }
     
      void rotateOnU(){//y
        char temp = FRONT;//on sauvegarde la face F
        FRONT = RIGHT;//on la remplace avec la face R
        RIGHT = BACK;//on remplace la face R avec la face B
        BACK = LEFT;//on remplace la face B avec la face L
        LEFT = temp;//on remplace la face L avec la sauvegarde (de la face F)
        frontY -= 90;//on décale l'avant en Y
        backY = frontY + 180;//et l'arrière
      }
      void rotU(){//identique à la fonction précédente mais sans décaler les zones d'actions des mouvements
        moveStr = "Ued";//U E' D' sur un vrai
        moveStrValid = true;
      }
      void rotateOnD(){//y'
        char temp = FRONT;
        FRONT = LEFT;
        LEFT = BACK;
        BACK = RIGHT;
        RIGHT = temp;
        frontY += 90;
        backY = frontY + 180;
      }
      void rotD(){
        moveStr = "uED";
        moveStrValid = true;
      }
      void rotateOnR(){//x
        char temp = FRONT;
        FRONT = DOWN;
        DOWN = BACK;
        BACK = UP;
        UP = temp;
        frontY -= 90;
        backY = frontY + 180;
      }
      void rotR(){
        moveStr = "Rml";
        moveStrValid = true;
      }
      void rotateOnL(){//x'
        char temp = FRONT;
        FRONT = UP;
        UP = BACK;
        BACK = DOWN;
        DOWN = temp;
        frontY -= 90;
        backY = frontY + 180;
      }
      void rotL(){
        moveStr = "rML";
        moveStrValid = true;
      }
      void rotateDown(){//Tourne dans l'axe des ordonnées (en Y) de FR quand 2*rotateDown() = z x' z
        char temp = FRONT;
        FRONT = UP;
        UP = BACK;
        BACK = DOWN;
        DOWN = temp;
        frontX -= 90;
        backX = -frontX;
      }   
      void rotateUp(){//idem que rotateDown() mais dans le sens inverse soit 2*rotateUp() = z' x z'
        char temp = FRONT;
        FRONT = DOWN;
        DOWN = BACK;
        BACK = UP;
        UP = temp;
        frontX += 90;
        backX = -frontX;
      }
      void rotateOnF(){//z
        char temp = LEFT;
        LEFT = DOWN;
        DOWN = RIGHT;
        RIGHT = UP;
        UP = temp;
        frontX += 180;
        backY = frontY + 180;
      }
      void rotF(){
        moveStr = "FSb";
        moveStrValid = true;
      }
      void rotB(){
        moveStr = "fsB";
        moveStrValid = true;
      }
      String flipEdge(String c){//retourne une arrête (ex: flipEdge("FU")="UF")
        char temp[] = {//sauvegarde les tout les caractère
          c.charAt(1), c.charAt(0)//le deuxième, le premier
          };
          return new String(temp);//retourne le résultat de l'inversion
      }
      String rotateStr(String c, int b){//retourne une chaine de caractère (décale les caractère de b rang (cf. principe de cryptographie Vegenère))
        char temp[] = {
          't', 't', 't'//remplissage pour éviter l'erreur: création d'un tableau vide qu'on essais de remplir tout en une fois (sans passer par le remplissage cellule par cellule)
        };
        for(int i=0;i<3;i++){//interchange les cellules celon la valeur de décalage b
          temp[(i+b)%3] = c.charAt(i);//tout en ayant bien les caractères de c et non pas 't' de temp[]
        }
        return new String(temp);
      }
    }
    void rot(float th, int ax, PVector v){//th: angle theta, ax: axe; v: vecteur;
      for(int i=0;i<4;i++){
        for(int j=0;j<4;j++){
          if(i==j) M[i][j] = 1.0;
          else M[i][j] = 0.0;
        }
      }
      float cosTh = cos(radians(th));//cosinus(theta)
      float sinTh = sin(radians(th));//sinus(theta)
      if(ax==0){
        M[1][1] = M[2][2] = cosTh;
        M[1][2] = -sinTh;
        M[2][1] = sinTh;
      }else if(ax==1){
        M[0][0] = M[2][2] = cosTh;
        M[0][2] = sinTh;
        M[2][0] = -sinTh;
      }else if(ax==2){
        M[1][1] = M[0][0] = cosTh;
        M[0][1] = -sinTh;
        M[1][0] = sinTh;
      }
     
      float tp[] = {//coordonné du vecteur
        v.x, v.y, v.z, 1.0
      };
      float res[] = {//tableau de résultat
        0, 0, 0, 0
      };
     
      for(int i=0;i<4;i++){
        for(int k=0;k<4;k++){
          res[i] += M[i][k] * tp[k];
        }
      }
      //mise à jour sur les coordonné du vecteur v
      v.x = res[0];
      v.y = res[1];
      v.z = res[2];
      
    }
     
    void trans(float dx, float dy, float dz, PVector v){//équivaut à translate()
      v.x += dx;//direction en abscisse
      v.y += dy;//direction en ordonné
      v.z += dz;//direction en profondeur/côte
    }
     
    void scal(float sx, float sy, float sz, PVector v){//redimension équivaut à scale()
      v.x *= sx;
      v.y *= sy;
      v.z *= sz;
    }
     
    void move(boolean newCall){//en mouvement ou pas
      if(newCall){//si vraie
        if(inMove || thetaCount != 0) return;//si en mouvement et que l'angle n'est pas nulle, ça retourne rien vue que cette fonction est du type void
        if(!inMove && newCall){//si ce n'est pas en mouvement et qu'il ya eu une nouvelle appel
          inMove = true;//on change son statut en "en mouvement"
          thetaCount = 0;//l'angle theta revien à zero
        }
      }
     
      if(inMove){//si en mouvement
        if(thetaCount > 90/speed){//si le compte d'angle dépasse l'angle droit divisé par la vitesse
          rc.updateRotate(axis, slice, direction);//mise à jour des rotations
          inMove = false;
          theta = 0;
          thetaCount = 0;
          return;
        }
        theta = direction*speed;//pour suivre les mouvements dans l'espace
        thetaCount++;//en conséquence le comptage de theta aussi
      }
    } 
     
    void fastMove(){//mouvement rapide
      if(!inMove){//mise à jour à l'état de repos
        rc.drawRubikCube(90.0*direction);//dessine le cube 
        rc.updateRotate(axis, slice, direction);//met à jour les rotations
      }
    }
    void slowMove(){//mouvement lent
      if(!inMove){
        rc.drawRubikCube(direction);
        rc.updateRotate(axis, slice, direction);
      }
    }
    void scramble(){//mélangeur
      String j[] = {//tableau à mélanges spécifique et aléatoire
        new String("FBUDlrfbudLR"), new String("LRFBUDlr"), new String("FBUDlr"), new String("FFBBRRLLudlrbf"), new String(randAlgo(8, 50)), new String(randAlgo2(4, 25)), new String(randomAlgo(50)), new String(randomAlgo2(25)),
        new String(extremAlgo()), new String(extremAlgo2()), new String("FFyFyFyF"),
        new String("FRUFRUFRU"), new String("MMEESS"), new String("drDRdrDRdrDR"), new String("FRUruRUruRUruf"), new String("FSRUruRUruRUrufs"), new String("MUMUMUMUMUMUMU"), new String("FrFrFrFrFrFrFrFrFr"), new String("MESMESMESMES")
        };
      moveStr = j[int(random(100.0))%j.length];//sélection aléatoire
      //moveStr = j[10];//sélection du 11e mélange
      algorithm = moveStr;//le mélange est affecter à l'algorithme affiché
      moveStrValid = true;//validité
      if(rc.isSolved()) text("Solved", 60, height/2);//au cas où ça ne s'affiche pas lors que le cube est résolu
    }
    String randAlgo(int min, int max){//extension de randomAlgo() avec la possibilité de générer un algorithme aléatoire avec un nombre aléatoire
      int r=(int) random(min, max);//r est un nombre aléatoire compris entre min et max
      return randomAlgo(r);//génere l'algorithme aléatoire à r mouvement
    }
    void WCAScramble(){//mélange valide de la WCA
      String randomState="";//état aléatoire (algorithme du mélange)
      String[] allmoves = {"F", "f", "FF", "L", "l", "LL", "R", "r", "RR", "U", "u", "UU", "D", "d", "DD", "B", "b", "BB"}; //liste des mouvement autorisés (18 mouvements)
      for(int i=0; i<20; i++){//génération d'un algorithme à 20 mouvements mais cela varie car les mouvements à 180° (2x la même lettre) sont comptées comme 2
        randomState += allmoves[int(random(allmoves.length))]+" ";//ajoute un mouvement de liste aléatoirement seulon le numéro de la cellule compris entre 0 et allmoves.length (longueur du tableau allmoves = 18)
      }
      moveStr = join(split(randomState, " "), "");//affiche le mélange sans espace pour éviter les ambiguïté de l'IA (exemple: prendre les espaces pour des répétition de mouvements, de pause, d'arrêt, ...)
      moveStrValid = true;
      if(rc.isSolved()) text("Solved", 60, height/2);
    }
    String randomAlgo(int moves){//fonction qui retourne un algorithme avec moves mouvements (mouvement simple: pas de mouvements à 180°, pas de double mouvement)
      //regroupement de tout movement lorsque le rubik's cube est fixe et notamment les mouvements
      String[] allmoves = {"F", "f", "L", "l", "R", "r", "U", "u", "D", "d", "B", "b", "S", "s", "M", "m", "E", "e", "X", "x", "Y", "y", "Z", "z"}; //24 mouvements (mouvements simples/de tranches et rotations)
      String algo = "";//création de la variable algo contenant l'algorithme
      for(int i=0; i<moves; i++) algo += allmoves[int(random(allmoves.length))];//ajout de mouvements choisi aléatoirement en fonction du nombres de mouvements
      return algo;//retourne l'algorithme
    }
    String randAlgo2(int min, int max){
      int r=(int) random(min, max);
      return randomAlgo2(r);
    }
    String randomAlgo2(int moves){//identique à randomAlgo() mais avec tout les mouvements à une couche (donc pas des mouvements du genre: Rm)
      String[] allmoves = {"F", "f", "FF", "L", "l", "LL", "R", "r", "RR", "U", "u", "UU", "D", "d", "DD", "B", "b", "BB", "S", "s", "SS", "M", "m", "MM", "E", "e", "EE", "X", "x", "XX", "Y", "y", "YY", "Z", "z", "ZZ"}; //27
      String algo = "";//création de la variable algo contenant l'algorithme
      for(int i=0; i<moves; i++){//ajout de mouvements choisi aléatoirement en fonction du nombres de mouvements
        algo += allmoves[int(random(allmoves.length))]+" ";
      }
      return algo;//retourne l'algorithme
    }
    String extremAlgo(){//génération à l'extreme
      return randomAlgo(100);
    }
    String extremAlgo2(){//moins extrême que la précédente car il y plus de mouvements possible
      return randomAlgo2(80);
    }
    
  • 
    void solve(String method){//méthode à utiliser pour résoudre le cube
      solverStat = "inspecting ...";
      if(!rc.isSolved()){//si le cube n'est pas résolu
        println("code: "+rc.codeString());//affiche le code du cube
        if(method.toLowerCase().equals("undo") || method.toLowerCase().equals(solvingMethod[0])){//méthode du robot
          while(!rc.isSolved()){//tant que le cube n'est pas résolue l'IA undo les mouvements
            undo();
          }
        }else if(method.toLowerCase().equals("beginner") || method.toLowerCase().equals("lbl") || method.toLowerCase().equals(solvingMethod[1])){//méthode des débutant
          //Scanne du cube pour trouver les cubies
          solverStat = "scanning to find UF, UR, UB and UL";
          int[] UFpos = getCubie("UF"), URpos = getCubie("UR"), UBpos = getCubie("UB"), ULpos = getCubie("UL");//positions des 4 premières arrêtes ciblé par la 1er étape de cette méthode
          if(UFpos[0]>=3 || UFpos[0]<0) UFpos = getCubie("FU");//si le cubie n'est pas dans/sur le cube
          if(URpos[0]>=3 || URpos[0]<0) URpos = getCubie("RU");
          if(UBpos[0]>=3 || UBpos[0]<0) UBpos = getCubie("BU");
          if(ULpos[0]>=3 || ULpos[0]<0) ULpos = getCubie("LU");
          //indique les positions des cubies désirer
          solverStat = "searching solution ...\nUF("+UFpos[0]+", "+UFpos[1]+", "+UFpos[2]+"), UR("+URpos[0]+", "+URpos[1]+", "+URpos[2]+"), UB("+UBpos[0]+", "+UBpos[1]+", "+UBpos[2]+"), UL("+ULpos[0]+", "+ULpos[1]+", "+ULpos[2]+")";
          println(solverStat);//affiche l'état du solveur
          //UF
          println("UF is at: "+UFpos[0]+", "+UFpos[1]+", "+UFpos[2]);
          whoIs("UF");//à quel place se trouve le cubie UF
          if(!cubieInPlace("UF")){//si le cubie n'est pas à sa place
            solverStat = "placing UF";
            if(cubieIsOriented("UF")){//bonne arrête
              //recherche de l'emplacement du cubie (cf. fiche)
              if(UFpos[0]==1 && UFpos[1]==0 && UFpos[2]==2) moveStr = "FF";//MDDm si les coins (UFR et ULF) sont résolu
              else if(UFpos[0]==0 && UFpos[1]==1 && UFpos[2]==2) moveStr = "Ulu";
              else if(UFpos[0]==2 && UFpos[1]==1 && UFpos[2]==2) moveStr = "uRU";
              else if(UFpos[0]==0 && UFpos[1]==0 && UFpos[2]==1) moveStr = "DFF";
              else if(UFpos[0]==2 && UFpos[1]==0 && UFpos[2]==1) moveStr = "dFF";
              else if(UFpos[0]==1 && UFpos[1]==0 && UFpos[2]==0) moveStr = "DDFF";
              else solverStat = "I can't find UF";
              moveStrValid=true;
            }else{//mauvaise arrête (mal orienté)
              if(UFpos[0]==1 && UFpos[1]==0 && UFpos[2]==2) moveStr = "DMdm";//dMDm (mirroir)
              else if(UFpos[0]==0 && UFpos[1]==1 && UFpos[2]==2) moveStr = "F";
              else if(UFpos[0]==2 && UFpos[1]==1 && UFpos[2]==2) moveStr = "f";
              else if(UFpos[0]==0 && UFpos[1]==0 && UFpos[2]==1) moveStr = "lFl";
              else if(UFpos[0]==2 && UFpos[1]==0 && UFpos[2]==1) moveStr = "Rfr";
              else if(UFpos[0]==1 && UFpos[1]==2 && UFpos[2]==2) moveStr = "FuRU";//fUlu (mirroir) ou FFDMdm ou ffdMDm
              else solverStat = "I can't find FU";
              moveStrValid=true;
            }
          }else rc.rotU();//Y pour passer au cubie suivant
          algorithm = moveStr;moveStrValid = true;
          //UR
          if(!cubieInPlace("UR")){
            solverStat = "placing UR";
            if(cubieIsOriented("UR")){//bonne arrêtes
              if(URpos[0]==1 && URpos[1]==0 && URpos[2]==2) moveStr = "FF";
              else if(URpos[0]==0 && URpos[1]==1 && URpos[2]==2) moveStr = "F";
              else if(URpos[0]==2 && URpos[1]==1 && URpos[2]==2) moveStr = "f";
              else if(URpos[0]==0 && URpos[1]==0 && URpos[2]==1) moveStr = "DFF";
              else if(URpos[0]==2 && URpos[1]==0 && URpos[2]==1) moveStr = "dFF";
              else solverStat = "I can't find UR";
              moveStrValid=true;
            }else{//mauvaise arrête
              if(URpos[0]==1 && URpos[1]==0 && URpos[2]==2) moveStr = "DMdm";
              else if(URpos[0]==0 && URpos[1]==1 && URpos[2]==2) moveStr = "Ulu";
              else if(URpos[0]==2 && URpos[1]==1 && URpos[2]==2) moveStr = "uRU";
              else if(URpos[0]==0 && URpos[1]==0 && URpos[2]==1) moveStr = "lFl";
              else if(URpos[0]==2 && URpos[1]==0 && URpos[2]==1) moveStr = "Rfr";
              else if(URpos[0]==1 && URpos[1]==2 && URpos[2]==2) moveStr = "FuRU";
              else solverStat = "I can't find RU";
              moveStrValid=true;
            }
          }else rc.rotU();
          algorithm = moveStr;moveStrValid = true;
          if(!cubieInPlace("UB")){
            solverStat = "placing UB";
            if(cubieIsOriented("UB")){
              if(UBpos[0]==1 && UBpos[1]==0 && UBpos[2]==2) moveStr = "FF";
              else if(UBpos[0]==0 && UBpos[1]==1 && UBpos[2]==2) moveStr = "F";
              else if(UBpos[0]==2 && UBpos[1]==1 && UBpos[2]==2) moveStr = "f";
              else if(UBpos[0]==0 && UBpos[1]==0 && UBpos[2]==1) moveStr = "DFF";
              else if(UBpos[0]==2 && UBpos[1]==0 && UBpos[2]==1) moveStr = "dFF";
              else solverStat = "I can't find UB";
              moveStrValid=true;
            }else{
              if(UBpos[0]==1 && UBpos[1]==0 && UBpos[2]==2) moveStr = "DMdm";
              else if(UBpos[0]==0 && UBpos[1]==1 && UBpos[2]==2) moveStr = "Ulu";
              else if(UBpos[0]==2 && UBpos[1]==1 && UBpos[2]==2) moveStr = "UBU";
              else if(UBpos[0]==0 && UBpos[1]==0 && UBpos[2]==1) moveStr = "lFl";
              else if(UBpos[0]==2 && UBpos[1]==0 && UBpos[2]==1) moveStr = "Rfr";
              else if(UBpos[0]==1 && UBpos[1]==2 && UBpos[2]==2) moveStr = "FUBU";
              else solverStat = "I can't find BU";
              moveStrValid=true;
            }
          }else rc.rotU();
          algorithm = moveStr;moveStrValid = true;
          if(!cubieInPlace("UL")){
            solverStat = "placing UL";
            if(cubieIsOriented("UL")){
              if(ULpos[0]==1 && ULpos[1]==0 && ULpos[2]==2) moveStr = "FF";
              else if(ULpos[0]==0 && ULpos[1]==1 && ULpos[2]==2) moveStr = "F";
              else if(ULpos[0]==2 && ULpos[1]==1 && ULpos[2]==2) moveStr = "f";
              else if(ULpos[0]==0 && ULpos[1]==0 && ULpos[2]==1) moveStr = "DFF";
              else if(ULpos[0]==2 && ULpos[1]==0 && ULpos[2]==1) moveStr = "dFF";
              else solverStat = "I can't find UL";
              moveStrValid=true;
            }else{
              if(ULpos[0]==1 && ULpos[1]==0 && ULpos[2]==2) moveStr = "DMdm";
              else if(ULpos[0]==0 && ULpos[1]==1 && ULpos[2]==2) moveStr = "Ulu";
              else if(ULpos[0]==2 && ULpos[1]==1 && ULpos[2]==2) moveStr = "ULU";
              else if(ULpos[0]==0 && ULpos[1]==0 && ULpos[2]==1) moveStr = "lFl";
              else if(ULpos[0]==2 && ULpos[1]==0 && ULpos[2]==1) moveStr = "Rfr";
              else if(ULpos[0]==1 && ULpos[1]==2 && ULpos[2]==2) moveStr = "FULU";
              else solverStat = "I can't find LU";
              moveStrValid=true;
            }
            solverStat = "Cross finished";
            solverStat = "scanning to find UFR, URB, UBL and ULF";
          int[] UFRpos = getCubie("UFR"), URBpos = getCubie("URB"), UBLpos = getCubie("UBL"), ULFpos = getCubie("ULF");//positions des 4 premières coins ciblé par la 2ème étape de cette méthode
          }else rc.rotU();
        }else if(method.toLowerCase().equals("fridrich") || method.toLowerCase().equals("cfop") || method.toLowerCase().equals(solvingMethod[2])){//méthode utiliser par des speedcubers
          
        }else if(method.toLowerCase().equals("petrus") || method.toLowerCase().equals(solvingMethod[3])){//méthode utiliser par des speedcubers
          
        }else if(method.toLowerCase().equals("roux") || method.toLowerCase().equals(solvingMethod[4])){//...
          
        }else if(method.toLowerCase().equals("edgefirst") || method.toLowerCase().equals(solvingMethod[5])){
          
        }else if(method.toLowerCase().equals("cornerfirst") || method.toLowerCase().equals(solvingMethod[6])){
          
        }else if(method.toLowerCase().equals("zz") || method.toLowerCase().equals(solvingMethod[7])){
          
        }else if(method.toLowerCase().equals("vh") || method.toLowerCase().equals(solvingMethod[8])){
          
        }else if(method.toLowerCase().equals("m2 3op") || method.toLowerCase().equals(solvingMethod[9])){//méthode utiliser par des speedcubers à l'aveugle
          
        }else{
          println("La méthode choisie pour résoudre le cube n'est pas disponible pour l'instant.\nLes méthodes disponible sont: "+solvingMethod);//indique que la méthode choisi n'est pas disponible et celles disponibles
        }
      }else{//si le cube est déjà résolu, ça l'annonce si ce n'était pas le cas et de modifie pas le cube
        solverStat = "cube solved";
        fill(255, 0, 0);
        textSize(24);
        text("Solved", 60, height/2);
        save("data/cubeStyle-"+cubeStyleSelected+".png");//pour garder un aperçu du style en cours
      }
      println(solverStat);//affiche l'état du solveur
      frame.setTitle("Rubik's Cube Simulator - Solveur: "+solverStat);
    }
    String[][][] findCubie(String ccode){
      int[] pos = {0};
      String[][][] cpos;
      for(int x=0; x<3; x++){
        for(int y=0; y<3; y++){
          for(int z=0; z<3; z++){
            //int[][][] pos = {x{y{z}}};
            if(rc.grid[x][y][z].code.equals(ccode)){pos[0] = x; pos[1] = y; pos[2] = z;}
          }
        }
      }
      cpos = getCubiePos(pos, ccode);
      return cpos;
    }*/
    int[] getCubie(String code){//scanne pour trouver le cubie ayant le code
      println("getting cubie "+code+" ...");//debug+indication de l'action effectué par l'IA
      //recherche individuelle des coordonnées du cubie pour éviter de passer par 3 fonctions (celle-ci y compris, dont les deux autre servent à retourner 3 résultat ce qui est complexe à faire) pour savoir où se trouve le cubie (défaut des autres fonctions en commentaire)
      int x=findCubieX(code), y=findCubieY(code), z=findCubieZ(code);
      if(x>=3||x<0||y>=3||y<0||z>=3||z<0){//si le cubie est inexistant ou hors du cube
        println("Ho the cubie has a problem !");//indique qu'il y a problème que l'IA vient de rencontrer
        if(code.length()==2) code=rc.flipEdge(code);//si le cubie en question est une arrête
        else code=rc.rotateStr(code, 1);//sinon ce cubie est un coin
        println("new code: "+code);//indique le nouveau code pour assurer un bon déroulement de cette arrangement au yeux de l'IA
        x=findCubieX(code);y=findCubieY(code);z=findCubieZ(code);//on recherche les coordonné qui étaient jugées mauvaises
        if(code.length()==3) getCubie(code);//vérification au cas où le code du coin est toujour pas trouvable (mauvais) car un coin à 3 code possible (celon son orientation) exemple: UFR/FRU/RUF; 
      }
      int[] p={x, y, z};//on case toute les coordonnés (donné tri-dimentionnel du cubie) dans une variable pour faciliter le retour et l'exploitation du résultat
      println("cubie "+code+" finded");//indique que la recherche du cubie en question à bien été fait
      return p;
    }
    boolean cubieInPlace(String ccode){//Si le cubie à besoin d'être permuter ou non (si c'est en place)
      int[] p=getCubie(ccode);//on récupère les coordonné du cubie
      if(rc.grid[p[0]][p[1]][p[2]].code.equals(ccode)) return true;//s'il est à sa place alors ça retourne vrai
      else if(ccode.length()==2 && rc.flipEdge(rc.grid[p[0]][p[1]][p[2]].code).equals(ccode)) return true;
      else if(ccode.length()==3 && rc.rotateStr(rc.grid[p[0]][p[1]][p[2]].code, 1).equals(ccode)) return true;
      else if(ccode.length()==3 && rc.rotateStr(rc.grid[p[0]][p[1]][p[2]].code, 2).equals(ccode)) return true;
      else return false;//sinon faux
    }
    boolean cubieIsOriented(String ccode){//Si le cubie à besoin d'être orienter ou non (si les stickers sont bien placés)
      int[] p=getCubie(ccode);
      if(rc.grid[p[0]][p[1]][p[2]].code.equals(ccode)) return true;
      else{
        if(ccode.length()==2) ccode=rc.flipEdge(ccode);
        else ccode=rc.rotateStr(ccode, 1);
        if(rc.grid[p[0]][p[1]][p[2]].code.equals(ccode)) return false;
        else if(ccode.length()==3){//au cas où ce n'est toujours pas bon
          ccode=rc.rotateStr(ccode, 1);
          if(rc.grid[p[0]][p[1]][p[2]].code.equals(ccode)) return false;
        }
        return false;
      }
    }
    int findCubieX(String code){//cherche la coordonné X du cubie voulu
      int x=0;
      //navigue à traver le cube au niveau des 3 dimensions pour une suretté maximale
      for(x=0; x<3; x++){
        for(int y=0; y<3; y++){
          for(int z=0; z<3; z++){
            if(rc.grid[x][y][z].code.equals(code)) return x;
          }
        }
      }
      return x;
    }
    int findCubieY(String code){//cherche la coordonné Y du cubie voulu
      int y=0;
      for(int x=0; x<3; x++){
        for(y=0; y<3; y++){
          for(int z=0; z<3; z++){
            if(rc.grid[x][y][z].code.equals(code)) return y;
          }
        }
      }
      return y;
    }
    int findCubieZ(String code){//cherche la coordonné Z du cubie voulu
      int z=0;
      for(int x=0; x<3; x++){
        for(int y=0; y<3; y++){
          for(z=0; z<3; z++){
            if(rc.grid[x][y][z].code.equals(code)) return z;
          }
        }
      }
      return z;
    }
    void reset(){//réinitialise le cube
      background(200);//efface le sketch (la fenêtre du programme)
      rc = new rubikCube(height/8);//construit à nouveau le cube
      //et tout ce qu'il en suit
      rc.cubePosition = new PVector(width/3, height/2.0, 0.0);
      backViewDisp = width/3;
      for(int i=0;i<8;i++){
        rot(rc.frontY, 1, rc.boundary.points[i]);
        rot(rc.frontX, 0, rc.boundary.points[i]);
        trans(rc.cubePosition.x, rc.cubePosition.y, rc.cubePosition.z, rc.boundary.points[i]);
        rot(rc.backY, 1, rc.boundary2.points[i]);
        rot(rc.backX, 0, rc.boundary2.points[i]);
        trans(rc.cubePosition.x + backViewDisp, rc.cubePosition.y, rc.cubePosition.z, rc.boundary2.points[i]);
      }
      nbOfMoves = 0;//pas de triche (passive ou par undo /!\ pas la méthode) et nécessaire pour les résolutions en FM (Fewest Moves: le moins de mouvements possible) c'est-à-dire pour ne pas pénaliser l'utilisateur/l'IA avec en ayant mis plus de mouvements qu'il n'en a fallut
    }
    
    
  • edited May 2014
    void keyPressed(){//au moment où une touche est appuyée
      println(key+":"+keyCode);//affiche la touche et son code pour les débuggage et pour vérifier l'identité d'une touche
      if(keyCode == 70 || keyCode == 86 || keyCode == 82 || keyCode == 84 || keyCode == 85 || keyCode == 73//touche "mouvement" car si la validité se fait pour toute touches,
        || keyCode == 66 || keyCode == 78 || keyCode == 76 || keyCode == 77 || keyCode == 68 || keyCode == 67//s'il n'y a pas d'exécution d'un quelquonque mouvement le mouvement précedemment exécuter est répéter
        || keyCode == 65 || keyCode == 49 || keyCode == 81 || keyCode == 50 || keyCode == 69 || keyCode == 51 || keyCode == 79 || keyCode == 80 || keyCode == 72 || keyCode == 74){
        if(!rc.isSolved() && min==0 && s==0 && ms==0) startTimer();//si le cube est mélanger et que le temps n'est pas en cours (d'évolution) le chrono s'active
        //liste de mouvement aisni que les touches dédié à un mouvement spécifique
        if(key == 'F' || keyCode == 70) moveStr = "F";//F
        else if(key == 'V' || keyCode == 86) moveStr = "f";//F'
        else if(key == 'R' || keyCode == 82) moveStr = "R";//R
        else if(key == 'T' || keyCode == 84) moveStr = "r";//R'
        else if(key == 'U' || keyCode == 85) moveStr = "U";//U
        else if(key == 'I' || keyCode == 73) moveStr = "u";//U'
        else if(key == 'B' || keyCode == 66) moveStr = "B";//B
        else if(key == 'N' || keyCode == 78) moveStr = "b";//B'
        else if(key == 'L' || keyCode == 76) moveStr = "L";//L
        else if(key == 'M' || keyCode == 77) moveStr = "l";//L'
        else if(key == 'D' || keyCode == 68) moveStr = "D";//D
        else if(key == 'C' || keyCode == 67) moveStr = "d";//D'
        else if(key == 'A' || keyCode == 65) moveStr = "M";//M
        else if(key == '1' || keyCode == 49 || keyCode == '&') moveStr = "m";//M'
        else if(key == 'Q' || keyCode == 81) moveStr = "S";//S
        else if(key == '2' || keyCode == 50) moveStr = "s";//S'
        else if(key == 'E' || keyCode == 69) moveStr = "E";//E
        else if(key == '3' || keyCode == 51) moveStr = "e";//E'
        else if(key == 'O' || keyCode == 79) moveStr = "LM";//l
        else if(key == 'P' || keyCode == 80) moveStr = "lm";//l'
        else if(key == 'H' || keyCode == 72) moveStr = "Rm";//r
        else if(key == 'J' || keyCode == 74) moveStr = "rM";//r'
        else if(key == 'K' || keyCode == 75) moveStr = "Ue";//u
        else if(/*key == '?' || key == ',' || */keyCode == 44) moveStr = "uE";//u'
        else if(key == '5' /*|| key == '(' */|| keyCode == 53) moveStr = "FS";//f
        else if(key == '6' /*|| key == '-' */|| keyCode == 54) moveStr = "fs";//f'
        moveStrValid = true;
        algorithm += moveStr;//bien sur en conserve une trace écrite des mouvements fait
      }
      if(key==ENTER || keyCode == 10) solve("beginner");//activation manuelle du solveur
      else if(key=='S' || keyCode == 83){if(cubeStyleSelected==9 || cubeStyleSelected==11) WCAScramble();else scramble();}//lancement du mélangeur et si le cube est le n°10 ou 12 alors le mélange est de catégorie WCA
      else if(key == CONTROL || keyCode == 17) reset();//retour à l'état résolu
      else if(key == 'X' || keyCode == 88) rc.rotR();//x
      else if(key == 'W' || keyCode == 87) rc.rotL();//x'
      else if(key == 'Y' || keyCode == 89) rc.rotU();//y
      else if(key == 'G' || keyCode == 71) rc.rotD();//y'
      else if(key == 'Z' || keyCode == 90) rc.rotateUp();//z
      else if(key == '4' || keyCode == 52) rc.rotateDown();//z'
      else if(key == '0' || keyCode == 48) println("Code du cube: "+rc.codeString());//indique le code du cube au format Singmaster
      else if(key == BACKSPACE || keyCode == BACKSPACE || keyCode == 8) undo();//undo 1 seul mouvement
      else if(key == UP || keyCode == 38) chCubeStyle(1);//va plus haut dans la table à style
      else if(key == DOWN || keyCode == 40) chCubeStyle(-1);//va plus bas ...
    }
    void chCubeStyle(int n){//change le style du cube par n rang
      println("changement de style par "+n);
      //réinitialisation au cas où une ou plusieurs face(s) d'un style remplace celle(s) des autres styles pouvant ainsi gaché les autres en question
      vCubeFC[0] = color(127);//D
      vCubeFC[1] = color(255, 127, 0);//B
      vCubeFC[2] = color(0, 0, 255);//R
      vCubeFC[3] = color(255, 0, 0);//F
      vCubeFC[4] = color(0, 255, 0);//L
      vCubeFC[5] = color(0);//U
      girlCFC[0] = color(255, 255, 0);
      girlCFC[1] = color(255, 127, 0);
      girlCFC[2] = color(255, 0, 255);
      girlCFC[3] = color(255, 16, 120);
      girlCFC[4] = color(0, 255, 0);
      girlCFC[5] = color(255);
      cF2C[0] = color(255);
      cF2C[1] = color(255);
      cF2C[2] = color(0);
      cF2C[3] = color(0);
      cF2C[4] = color(255);
      cF2C[5] = color(0);
      cF3C[0] = color(0, 255, 0);
      cF3C[1] = color(255, 0, 0);
      cF3C[2] = color(0, 0, 127);
      cF3C[3] = color(127, 0, 0);
      cF3C[4] = color(0, 0, 255);
      cF3C[5] = color(0, 127, 0);
      MirrorFC[0] = color(210);
      MirrorFC[1] = color(210);
      MirrorFC[2] = color(210);
      MirrorFC[3] = color(210);
      MirrorFC[4] = color(210);
      MirrorFC[5] = color(210);
      MinxFC[0] = color(0, 255, 0);
      MinxFC[1] = color(255, 0, 0);
      MinxFC[2] = color(0, 255, 255);
      MinxFC[3] = color(255, 255, 0);
      MinxFC[4] = color(0, 0, 255);
      MinxFC[5] = color(255, 0, 255);
      OldStyle[0] = color(255);
      OldStyle[1] = color(127);
      OldStyle[2] = color(0);
      OldStyle[3] = color(255);
      OldStyle[4] = color(127);
      OldStyle[5] = color(0);
      WCAClrSch[0] = color(255, 255, 0);
      WCAClrSch[1] = color(0, 0, 255);
      WCAClrSch[2] = color(255, 0, 0);
      WCAClrSch[3] = color(0, 255, 0);
      WCAClrSch[4] = color(255, 128, 0);
      WCAClrSch[5] = color(255);
      TwoFC[0] = color(255, 255, 0);
      TwoFC[1] = color(128, 64);
      TwoFC[2] = color(128, 64);
      TwoFC[3] = color(128, 64);
      TwoFC[4] = color(128, 64);
      TwoFC[5] = color(255);
      Visual[0] = color(255, 255, 0, 127);
      Visual[1] = color(0, 0, 255, 127);
      Visual[2] = color(255, 0, 0, 127);
      Visual[3] = color(0, 255, 0, 127);
      Visual[4] = color(255, 128, 0, 127);
      Visual[5] = color(255, 127);
      cubiesBorder = color(255);//couleur de la bordure du cube
      if(cubeStyleSelected<cubeStyles.length && n==1) cubeStyleSelected++;//si le style n'est pas le dernier de la liste et que le rang de changement est de 1
      else if(cubeStyleSelected>0 && n==-1) cubeStyleSelected--;//si le style n'est pas le premier de la liste et que le rang de changement est de -1
      if(cubeStyleSelected==0){//si le style sélectionné est le premier
        cubeFaceColors[0] = color(255, 255, 0);
        cubeFaceColors[1] = color(255, 127, 0);
        cubeFaceColors[2] = color(0, 0, 255);
        cubeFaceColors[3] = color(255, 0, 0);
        cubeFaceColors[4] = color(0, 255, 0);
        cubeFaceColors[5] = color(255);
        cubiesBorder = color(0);//bordure du cube de couleur noir
      }else if(cubeStyleSelected==1){//si le style sélectionné est le deuxième
        cubiesBorder = color(255);//bordure du cube de couleur blanche
        cubeFaceColors = vCubeFC;//le schéma de couleur est celui de vCubeFC
      }else if(cubeStyleSelected==2){//...
        cubiesBorder = color(255, 255, 0);
        cubeFaceColors = girlCFC;
      }else if(cubeStyleSelected==3){
        cubiesBorder = color(32);
        cubeFaceColors = cF2C;
      }else if(cubeStyleSelected==4){
        cubiesBorder = color(180);
        cubeFaceColors = cF3C;
      }else if(cubeStyleSelected==5){
        cubiesBorder = color(0);
        cubeFaceColors = MirrorFC;
      }else if(cubeStyleSelected==6){
        cubiesBorder = color(0);
        cubeFaceColors = MinxFC;
      }else if(cubeStyleSelected==7){
        cubiesBorder = color(180);
        cubeFaceColors = OldStyle;
      }else if(cubeStyleSelected==8){
        cubiesBorder = color(127, 0);//pas de bordure
        cubeFaceColors[0] = color(255, 255, 0);
        cubeFaceColors[1] = color(255, 127, 0);
        cubeFaceColors[2] = color(0, 0, 255);
        cubeFaceColors[3] = color(255, 0, 0);
        cubeFaceColors[4] = color(0, 255, 0);
        cubeFaceColors[5] = color(255);
      }else if(cubeStyleSelected==9){
        cubiesBorder = color(0);
        cubeFaceColors = WCAClrSch;
      }else if(cubeStyleSelected==10){
        cubiesBorder = color(0, 200);//a peine transparent
        cubeFaceColors = TwoFC;
      }else if(cubeStyleSelected==11){
        cubiesBorder = color(64, 127);//semi opaque
        cubeFaceColors = Visual;
      }
      if(cubeStyleSelected==8) rc.setSize(5);//particularité visuelle/physique du style n°9
      else reset();//rc.setSize(height/8); pour éviter le sur écartement cubie-cubie sur la globalité des style
    }
    void faceMove(char face){//mouvement de face
      char pVal;
      switch(face){//condition multiple sur la valeur de face
      case 'R': //mouvement R
        axis = 0;//premier axe
        slice = 2;//dernière tranche
        direction = 1;//sens des aiguïlles d'une montre
        pVal = 'r';//mouvement pour l'undo
        break;//evite la boucle dans switch()
      case 'r': 
        axis = 0;
        slice = 2;
        direction = -1;//sens inverse ..
        pVal = 'R';
        break;
      case 'M': 
        axis = 0;
        slice = 1;
        direction = -1;
        pVal = 'm';
        break;
      case 'm': 
        axis = 0;
        slice = 1;
        direction = 1;
        pVal = 'M';
        break;
      case 'L': 
        axis = 0;
        slice = 0;
        direction = -1;
        pVal = 'l';
        break;
      case 'l': 
        axis = 0;
        slice = 0;
        direction = 1;
        pVal = 'L';
        break;
      case 'X': 
        axis = 0;//R
        slice = 2;
        direction = 1;
        axis = 0;//M'
        slice = 1;
        direction = 1;
        axis = 0;//L'
        slice = 2;
        direction = 1;
        pVal = 'x';
        break;
      case 'x': 
        axis = 0;//R'
        slice = 2;
        direction = -1;
        axis = 0;//M
        slice = 1;
        direction = -1;
        axis = 0;//L
        slice = 2;
        direction = -1;
        pVal = 'X';
        break;
      case 'D': 
        axis = 1;
        slice = 0;
        direction = -1;
        pVal = 'd';
        break;
      case 'd': 
        axis = 1;
        slice = 0;
        direction = 1;
        pVal = 'D';
        break;
      case 'E': 
        axis = 1;
        slice = 1;
        direction = -1;
        pVal = 'e';
        break;
      case 'e': 
        axis = 1;
        slice = 1;
        direction = 1;
        pVal = 'E';
        break;
      case 'U': 
        axis = 1;
        slice = 2;
        direction = 1;
        pVal = 'u';
        break;
      case 'u': 
        axis = 1;
        slice = 2;
        direction = -1;
        pVal = 'U';
        break;
      case 'Y': 
        axis = 1;//U
        slice = 2;
        direction = 1;
        axis = 1;//E'
        slice = 1;
        direction = 1;
        axis = 1;//D'
        slice = 0;
        direction = 1;
        pVal = 'y';
        break;
      case 'y': 
        axis = 1;//U'
        slice = 2;
        direction = -1;
        axis = 1;//E
        slice = 1;
        direction = -1;
        axis = 1;//D
        slice = 0;
        direction = -1;
        pVal = 'Y';
        break;
      case 'B': 
        axis = 2;
        slice = 0;
        direction = -1;
        pVal = 'b';
        break;
      case 'b': 
        axis = 2;
        slice = 0;
        direction = 1;
        pVal = 'B';
        break;
      case 'S': 
        axis = 2;
        slice = 1;
        direction = 1;
        pVal = 's';
        break;
      case 's': 
        axis = 2;
        slice = 1;
        direction = -1;
        pVal = 'S';
        break;
      case 'F': 
        axis = 2;
        slice = 2;
        direction = 1;
        pVal = 'f';
        break;
      case 'f': 
        axis = 2;
        slice = 2;
        direction = -1;
        pVal = 'F';
        break;
      case 'Z': 
        axis = 2;//F
        slice = 2;
        direction = 1;
        axis = 2;//S
        slice = 1;
        direction = 1;
        axis = 2;//B'
        slice = 0;
        direction = 1;
        pVal = 'z';
        break;
      case 'z': 
        axis = 2;//F'
        slice = 2;
        direction = -1;
        axis = 2;//S'
        slice = 1;
        direction = -1;
        axis = 2;//B
        slice = 0;
        direction = -1;
        pVal = 'Z';
        break;
      default:
        return;
      }
      //undoStr[undoStr.length] = pVal;//undoStr.push(pVal);
      move(true);//autorise le mouvement
    }
    void undo(){//comme son nom l'indique
      if(!inMove){//pour éviter d'interrompre l'algorithme en cour
        char p = stackOfMoves.pop();//retire le dernier mouvements enregistré dans le stack
        faceMove(p);//refait les mouvements sans le dernier
        //moveStr = join(split(undoStr[undoStr.length-1]+"", ""), "");moveStrValid = true;// pour (char) pVal et (char[]) undoStr
        //undoStr.pop(undoStr.length-1);
        /*String poping = join(split(undoStr[undoStr.length-1]+"", ""), "").substring(0, undoStr.length-2);
        String[] popedStr = split(poping, "");*/
      }
    }
    
    void computeBoundaries(){//frontière du cube (pas important)
      PVector pt[] = new PVector[8];//tableau à 8 vecteur pour les premiers points
      PVector pt2[] = new PVector[8];//... les deuxièmes point
      for(int i=0;i<8;i++){//remplis les deux tableau en fonction de l'abscisse et de l'ordonné des points de frontière du cube apparaisant sur le plan 2D de l'écran à partir du plan 3D du cube
        pt[i] = new PVector(screenX(rc.boundary.points[i].x, rc.boundary.points[i].y, rc.boundary.points[i].z),
        screenY(rc.boundary.points[i].x, rc.boundary.points[i].y, rc.boundary.points[i].z), 0.0);
        pt2[i] = new PVector(screenX(rc.boundary2.points[i].x, rc.boundary2.points[i].y, rc.boundary2.points[i].z), 
        screenY(rc.boundary2.points[i].x, rc.boundary2.points[i].y, rc.boundary2.points[i].z), 0.0);
      }
      //points visible sur la vue avant
      //frontière du haut
      topBound = new PVector[4];
      topBound[0] = new PVector(pt[4].x, pt[4].y, pt[4].z);
      topBound[1] = new PVector(pt[5].x, pt[5].y, pt[5].z);
      topBound[2] = new PVector(pt[7].x, pt[7].y, pt[7].z);
      topBound[3] = new PVector(pt[6].x, pt[6].y, pt[6].z);
      //frontière du devant
      frontBound = new PVector[4];
      frontBound[0] = new PVector(pt[0].x, pt[0].y, pt[0].z);
      frontBound[1] = new PVector(pt[1].x, pt[1].y, pt[1].z);
      frontBound[2] = new PVector(pt[5].x, pt[5].y, pt[5].z);
      frontBound[3] = new PVector(pt[4].x, pt[4].y, pt[4].z);
      //frontière de droite
      rightBound = new PVector[4];
      rightBound[0] = new PVector(pt[0].x, pt[0].y, pt[0].z);
      rightBound[1] = new PVector(pt[2].x, pt[2].y, pt[2].z);
      rightBound[2] = new PVector(pt[6].x, pt[6].y, pt[6].z);
      rightBound[3] = new PVector(pt[4].x, pt[4].y, pt[4].z);
      //points visible sur la vue arrière
      //frontière du bas
      downBound = new PVector[4];
      downBound[0] = new PVector(pt2[0].x, pt2[0].y, pt2[0].z);
      downBound[1] = new PVector(pt2[2].x, pt2[2].y, pt2[2].z);
      downBound[2] = new PVector(pt2[3].x, pt2[3].y, pt2[3].z);
      downBound[3] = new PVector(pt2[1].x, pt2[1].y, pt2[1].z);
      //frontière de l'arrière
      backBound = new PVector[4];
      backBound[0] = new PVector(pt2[2].x, pt2[2].y, pt2[2].z);
      backBound[1] = new PVector(pt2[6].x, pt2[6].y, pt2[6].z);
      backBound[2] = new PVector(pt2[7].x, pt2[7].y, pt2[7].z);
      backBound[3] = new PVector(pt2[3].x, pt2[3].y, pt2[3].z);
      //frontière de gauche
      leftBound = new PVector[4];
      leftBound[0] = new PVector(pt2[1].x, pt2[1].y, pt2[1].z);
      leftBound[1] = new PVector(pt2[3].x, pt2[3].y, pt2[3].z);
      leftBound[2] = new PVector(pt2[7].x, pt2[7].y, pt2[7].z);
      leftBound[3] = new PVector(pt2[5].x, pt2[5].y, pt2[5].z);
    }
    void strOfMoves(){//algorithme
      if(!inMove){//si il n'y pas de risque de perturber l'algorithme en cour
        if(strMoveCount < moveStr.length()){//si le compte de mouvement est inférieur au nombre de mouvement
          faceMove(moveStr.charAt(strMoveCount));//se place au dernier mouvement comptabilisé par strMoveCount
          strMoveCount++;//incrémente strMoveCount de 1
          nbOfMoves++;
        }else{
          moveStrValid = false;//sinon l'ajout de mouvement est invalidé
          strMoveCount = 0;//remise à zero
        }
      }
    }
    int ms=00, s=00, min=00;
    void startTimer(){//chronomètre
      if(!rc.isSolved()){//si le cube est résolut ça n'a pas de sens
        ms++;//augmentation des milliseconde
        if(ms>=100){s++;ms=00;}//si t=100ms : t=1s
        if(s>=60){min++;s=00;}//si t=60s : t=1min
      }else if(ms>=0 && s>0){println("["+millis()+"] "+min+":"+s+"."+ms);min=00;s=00;ms=00;}//affiche temps et le moment où la résolution c'est terminée et aussi pour éviter d'affiche le temps alors qu'il n'y a pas eu de résolution
    }
  • void keyPressed(){//au moment où une touche est appuyée
      println(key+":"+keyCode);//affiche la touche et son code pour les débuggage et pour vérifier l'identité d'une touche
      if(keyCode == 70 || keyCode == 86 || keyCode == 82 || keyCode == 84 || keyCode == 85 || keyCode == 73//touche "mouvement" car si la validité se fait pour toute touches,
        || keyCode == 66 || keyCode == 78 || keyCode == 76 || keyCode == 77 || keyCode == 68 || keyCode == 67//s'il n'y a pas d'exécution d'un quelquonque mouvement le mouvement précedemment exécuter est répéter
        || keyCode == 65 || keyCode == 49 || keyCode == 81 || keyCode == 50 || keyCode == 69 || keyCode == 51 || keyCode == 79 || keyCode == 80 || keyCode == 72 || keyCode == 74){
        if(!rc.isSolved() && min==0 && s==0 && ms==0) startTimer();//si le cube est mélanger et que le temps n'est pas en cours (d'évolution) le chrono s'active
        //liste de mouvement aisni que les touches dédié à un mouvement spécifique
        if(key == 'F' || keyCode == 70) moveStr = "F";//F
        else if(key == 'V' || keyCode == 86) moveStr = "f";//F'
        else if(key == 'R' || keyCode == 82) moveStr = "R";//R
        else if(key == 'T' || keyCode == 84) moveStr = "r";//R'
        else if(key == 'U' || keyCode == 85) moveStr = "U";//U
        else if(key == 'I' || keyCode == 73) moveStr = "u";//U'
        else if(key == 'B' || keyCode == 66) moveStr = "B";//B
        else if(key == 'N' || keyCode == 78) moveStr = "b";//B'
        else if(key == 'L' || keyCode == 76) moveStr = "L";//L
        else if(key == 'M' || keyCode == 77) moveStr = "l";//L'
        else if(key == 'D' || keyCode == 68) moveStr = "D";//D
        else if(key == 'C' || keyCode == 67) moveStr = "d";//D'
        else if(key == 'A' || keyCode == 65) moveStr = "M";//M
        else if(key == '1' || keyCode == 49 || keyCode == '&') moveStr = "m";//M'
        else if(key == 'Q' || keyCode == 81) moveStr = "S";//S
        else if(key == '2' || keyCode == 50) moveStr = "s";//S'
        else if(key == 'E' || keyCode == 69) moveStr = "E";//E
        else if(key == '3' || keyCode == 51) moveStr = "e";//E'
        else if(key == 'O' || keyCode == 79) moveStr = "LM";//l
        else if(key == 'P' || keyCode == 80) moveStr = "lm";//l'
        else if(key == 'H' || keyCode == 72) moveStr = "Rm";//r
        else if(key == 'J' || keyCode == 74) moveStr = "rM";//r'
        else if(key == 'K' || keyCode == 75) moveStr = "Ue";//u
        else if(/*key == '?' || key == ',' || */keyCode == 44) moveStr = "uE";//u'
        else if(key == '5' /*|| key == '(' */|| keyCode == 53) moveStr = "FS";//f
        else if(key == '6' /*|| key == '-' */|| keyCode == 54) moveStr = "fs";//f'
        moveStrValid = true;
        algorithm += moveStr;//bien sur en conserve une trace écrite des mouvements fait
      }
      if(key==ENTER || keyCode == 10) solve("beginner");//activation manuelle du solveur
      else if(key=='S' || keyCode == 83){if(cubeStyleSelected==9 || cubeStyleSelected==11) WCAScramble();else scramble();}//lancement du mélangeur et si le cube est le n°10 ou 12 alors le mélange est de catégorie WCA
      else if(key == CONTROL || keyCode == 17) reset();//retour à l'état résolu
      else if(key == 'X' || keyCode == 88) rc.rotR();//x
      else if(key == 'W' || keyCode == 87) rc.rotL();//x'
      else if(key == 'Y' || keyCode == 89) rc.rotU();//y
      else if(key == 'G' || keyCode == 71) rc.rotD();//y'
      else if(key == 'Z' || keyCode == 90) rc.rotateUp();//z
      else if(key == '4' || keyCode == 52) rc.rotateDown();//z'
      else if(key == '0' || keyCode == 48) println("Code du cube: "+rc.codeString());//indique le code du cube au format Singmaster
      else if(key == BACKSPACE || keyCode == BACKSPACE || keyCode == 8) undo();//undo 1 seul mouvement
      else if(key == UP || keyCode == 38) chCubeStyle(1);//va plus haut dans la table à style
      else if(key == DOWN || keyCode == 40) chCubeStyle(-1);//va plus bas ...
    }
    void chCubeStyle(int n){//change le style du cube par n rang
      println("changement de style par "+n);
      //réinitialisation au cas où une ou plusieurs face(s) d'un style remplace celle(s) des autres styles pouvant ainsi gaché les autres en question
      vCubeFC[0] = color(127);//D
      vCubeFC[1] = color(255, 127, 0);//B
      vCubeFC[2] = color(0, 0, 255);//R
      vCubeFC[3] = color(255, 0, 0);//F
      vCubeFC[4] = color(0, 255, 0);//L
      vCubeFC[5] = color(0);//U
      girlCFC[0] = color(255, 255, 0);
      girlCFC[1] = color(255, 127, 0);
      girlCFC[2] = color(255, 0, 255);
      girlCFC[3] = color(255, 16, 120);
      girlCFC[4] = color(0, 255, 0);
      girlCFC[5] = color(255);
      cF2C[0] = color(255);
      cF2C[1] = color(255);
      cF2C[2] = color(0);
      cF2C[3] = color(0);
      cF2C[4] = color(255);
      cF2C[5] = color(0);
      cF3C[0] = color(0, 255, 0);
      cF3C[1] = color(255, 0, 0);
      cF3C[2] = color(0, 0, 127);
      cF3C[3] = color(127, 0, 0);
      cF3C[4] = color(0, 0, 255);
      cF3C[5] = color(0, 127, 0);
      MirrorFC[0] = color(210);
      MirrorFC[1] = color(210);
      MirrorFC[2] = color(210);
      MirrorFC[3] = color(210);
      MirrorFC[4] = color(210);
      MirrorFC[5] = color(210);
      MinxFC[0] = color(0, 255, 0);
      MinxFC[1] = color(255, 0, 0);
      MinxFC[2] = color(0, 255, 255);
      MinxFC[3] = color(255, 255, 0);
      MinxFC[4] = color(0, 0, 255);
      MinxFC[5] = color(255, 0, 255);
      OldStyle[0] = color(255);
      OldStyle[1] = color(127);
      OldStyle[2] = color(0);
      OldStyle[3] = color(255);
      OldStyle[4] = color(127);
      OldStyle[5] = color(0);
      WCAClrSch[0] = color(255, 255, 0);
      WCAClrSch[1] = color(0, 0, 255);
      WCAClrSch[2] = color(255, 0, 0);
      WCAClrSch[3] = color(0, 255, 0);
      WCAClrSch[4] = color(255, 128, 0);
      WCAClrSch[5] = color(255);
      TwoFC[0] = color(255, 255, 0);
      TwoFC[1] = color(128, 64);
      TwoFC[2] = color(128, 64);
      TwoFC[3] = color(128, 64);
      TwoFC[4] = color(128, 64);
      TwoFC[5] = color(255);
      Visual[0] = color(255, 255, 0, 127);
      Visual[1] = color(0, 0, 255, 127);
      Visual[2] = color(255, 0, 0, 127);
      Visual[3] = color(0, 255, 0, 127);
      Visual[4] = color(255, 128, 0, 127);
      Visual[5] = color(255, 127);
      cubiesBorder = color(255);//couleur de la bordure du cube
      if(cubeStyleSelected<cubeStyles.length && n==1) cubeStyleSelected++;//si le style n'est pas le dernier de la liste et que le rang de changement est de 1
      else if(cubeStyleSelected>0 && n==-1) cubeStyleSelected--;//si le style n'est pas le premier de la liste et que le rang de changement est de -1
      if(cubeStyleSelected==0){//si le style sélectionné est le premier
        cubeFaceColors[0] = color(255, 255, 0);
        cubeFaceColors[1] = color(255, 127, 0);
        cubeFaceColors[2] = color(0, 0, 255);
        cubeFaceColors[3] = color(255, 0, 0);
        cubeFaceColors[4] = color(0, 255, 0);
        cubeFaceColors[5] = color(255);
        cubiesBorder = color(0);//bordure du cube de couleur noir
      }else if(cubeStyleSelected==1){//si le style sélectionné est le deuxième
        cubiesBorder = color(255);//bordure du cube de couleur blanche
        cubeFaceColors = vCubeFC;//le schéma de couleur est celui de vCubeFC
      }else if(cubeStyleSelected==2){//...
        cubiesBorder = color(255, 255, 0);
        cubeFaceColors = girlCFC;
      }else if(cubeStyleSelected==3){
        cubiesBorder = color(32);
        cubeFaceColors = cF2C;
      }else if(cubeStyleSelected==4){
        cubiesBorder = color(180);
        cubeFaceColors = cF3C;
      }else if(cubeStyleSelected==5){
        cubiesBorder = color(0);
        cubeFaceColors = MirrorFC;
      }else if(cubeStyleSelected==6){
        cubiesBorder = color(0);
        cubeFaceColors = MinxFC;
      }else if(cubeStyleSelected==7){
        cubiesBorder = color(180);
        cubeFaceColors = OldStyle;
      }else if(cubeStyleSelected==8){
        cubiesBorder = color(127, 0);//pas de bordure
        cubeFaceColors[0] = color(255, 255, 0);
        cubeFaceColors[1] = color(255, 127, 0);
        cubeFaceColors[2] = color(0, 0, 255);
        cubeFaceColors[3] = color(255, 0, 0);
        cubeFaceColors[4] = color(0, 255, 0);
        cubeFaceColors[5] = color(255);
      }else if(cubeStyleSelected==9){
        cubiesBorder = color(0);
        cubeFaceColors = WCAClrSch;
      }else if(cubeStyleSelected==10){
        cubiesBorder = color(0, 200);//a peine transparent
        cubeFaceColors = TwoFC;
      }else if(cubeStyleSelected==11){
        cubiesBorder = color(64, 127);//semi opaque
        cubeFaceColors = Visual;
      }
      if(cubeStyleSelected==8) rc.setSize(5);//particularité visuelle/physique du style n°9
      else reset();//rc.setSize(height/8); pour éviter le sur écartement cubie-cubie sur la globalité des style
    }
    void faceMove(char face){//mouvement de face
      char pVal;
      switch(face){//condition multiple sur la valeur de face
      case 'R': //mouvement R
        axis = 0;//premier axe
        slice = 2;//dernière tranche
        direction = 1;//sens des aiguïlles d'une montre
        pVal = 'r';//mouvement pour l'undo
        break;//evite la boucle dans switch()
      case 'r': 
        axis = 0;
        slice = 2;
        direction = -1;//sens inverse ..
        pVal = 'R';
        break;
      case 'M': 
        axis = 0;
        slice = 1;
        direction = -1;
        pVal = 'm';
        break;
      case 'm': 
        axis = 0;
        slice = 1;
        direction = 1;
        pVal = 'M';
        break;
      case 'L': 
        axis = 0;
        slice = 0;
        direction = -1;
        pVal = 'l';
        break;
      case 'l': 
        axis = 0;
        slice = 0;
        direction = 1;
        pVal = 'L';
        break;
      case 'X': 
        axis = 0;//R
        slice = 2;
        direction = 1;
        axis = 0;//M'
        slice = 1;
        direction = 1;
        axis = 0;//L'
        slice = 2;
        direction = 1;
        pVal = 'x';
        break;
      case 'x': 
        axis = 0;//R'
        slice = 2;
        direction = -1;
        axis = 0;//M
        slice = 1;
        direction = -1;
        axis = 0;//L
        slice = 2;
        direction = -1;
        pVal = 'X';
        break;
      case 'D': 
        axis = 1;
        slice = 0;
        direction = -1;
        pVal = 'd';
        break;
      case 'd': 
        axis = 1;
        slice = 0;
        direction = 1;
        pVal = 'D';
        break;
      case 'E': 
        axis = 1;
        slice = 1;
        direction = -1;
        pVal = 'e';
        break;
      case 'e': 
        axis = 1;
        slice = 1;
        direction = 1;
        pVal = 'E';
        break;
      case 'U': 
        axis = 1;
        slice = 2;
        direction = 1;
        pVal = 'u';
        break;
      case 'u': 
        axis = 1;
        slice = 2;
        direction = -1;
        pVal = 'U';
        break;
      case 'Y': 
        axis = 1;//U
        slice = 2;
        direction = 1;
        axis = 1;//E'
        slice = 1;
        direction = 1;
        axis = 1;//D'
        slice = 0;
        direction = 1;
        pVal = 'y';
        break;
      case 'y': 
        axis = 1;//U'
        slice = 2;
        direction = -1;
        axis = 1;//E
        slice = 1;
        direction = -1;
        axis = 1;//D
        slice = 0;
        direction = -1;
        pVal = 'Y';
        break;
      case 'B': 
        axis = 2;
        slice = 0;
        direction = -1;
        pVal = 'b';
        break;
      case 'b': 
        axis = 2;
        slice = 0;
        direction = 1;
        pVal = 'B';
        break;
      case 'S': 
        axis = 2;
        slice = 1;
        direction = 1;
        pVal = 's';
        break;
      case 's': 
        axis = 2;
        slice = 1;
        direction = -1;
        pVal = 'S';
        break;
      case 'F': 
        axis = 2;
        slice = 2;
        direction = 1;
        pVal = 'f';
        break;
      case 'f': 
        axis = 2;
        slice = 2;
        direction = -1;
        pVal = 'F';
        break;
      case 'Z': 
        axis = 2;//F
        slice = 2;
        direction = 1;
        axis = 2;//S
        slice = 1;
        direction = 1;
        axis = 2;//B'
        slice = 0;
        direction = 1;
        pVal = 'z';
        break;
      case 'z': 
        axis = 2;//F'
        slice = 2;
        direction = -1;
        axis = 2;//S'
        slice = 1;
        direction = -1;
        axis = 2;//B
        slice = 0;
        direction = -1;
        pVal = 'Z';
        break;
      default:
        return;
      }
      //undoStr[undoStr.length] = pVal;//undoStr.push(pVal);
      move(true);//autorise le mouvement
    }
    void undo(){//comme son nom l'indique
      if(!inMove){//pour éviter d'interrompre l'algorithme en cour
        char p = stackOfMoves.pop();//retire le dernier mouvements enregistré dans le stack
        faceMove(p);//refait les mouvements sans le dernier
        //moveStr = join(split(undoStr[undoStr.length-1]+"", ""), "");moveStrValid = true;// pour (char) pVal et (char[]) undoStr
        //undoStr.pop(undoStr.length-1);
        /*String poping = join(split(undoStr[undoStr.length-1]+"", ""), "").substring(0, undoStr.length-2);
        String[] popedStr = split(poping, "");*/
      }
    }
    
    void computeBoundaries(){//frontière du cube (pas important)
      PVector pt[] = new PVector[8];//tableau à 8 vecteur pour les premiers points
      PVector pt2[] = new PVector[8];//... les deuxièmes point
      for(int i=0;i<8;i++){//remplis les deux tableau en fonction de l'abscisse et de l'ordonné des points de frontière du cube apparaisant sur le plan 2D de l'écran à partir du plan 3D du cube
        pt[i] = new PVector(screenX(rc.boundary.points[i].x, rc.boundary.points[i].y, rc.boundary.points[i].z),
        screenY(rc.boundary.points[i].x, rc.boundary.points[i].y, rc.boundary.points[i].z), 0.0);
        pt2[i] = new PVector(screenX(rc.boundary2.points[i].x, rc.boundary2.points[i].y, rc.boundary2.points[i].z), 
        screenY(rc.boundary2.points[i].x, rc.boundary2.points[i].y, rc.boundary2.points[i].z), 0.0);
      }
      //points visible sur la vue avant
      //frontière du haut
      topBound = new PVector[4];
      topBound[0] = new PVector(pt[4].x, pt[4].y, pt[4].z);
      topBound[1] = new PVector(pt[5].x, pt[5].y, pt[5].z);
      topBound[2] = new PVector(pt[7].x, pt[7].y, pt[7].z);
      topBound[3] = new PVector(pt[6].x, pt[6].y, pt[6].z);
      //frontière du devant
      frontBound = new PVector[4];
      frontBound[0] = new PVector(pt[0].x, pt[0].y, pt[0].z);
      frontBound[1] = new PVector(pt[1].x, pt[1].y, pt[1].z);
      frontBound[2] = new PVector(pt[5].x, pt[5].y, pt[5].z);
      frontBound[3] = new PVector(pt[4].x, pt[4].y, pt[4].z);
      //frontière de droite
      rightBound = new PVector[4];
      rightBound[0] = new PVector(pt[0].x, pt[0].y, pt[0].z);
      rightBound[1] = new PVector(pt[2].x, pt[2].y, pt[2].z);
      rightBound[2] = new PVector(pt[6].x, pt[6].y, pt[6].z);
      rightBound[3] = new PVector(pt[4].x, pt[4].y, pt[4].z);
      //points visible sur la vue arrière
      //frontière du bas
      downBound = new PVector[4];
      downBound[0] = new PVector(pt2[0].x, pt2[0].y, pt2[0].z);
      downBound[1] = new PVector(pt2[2].x, pt2[2].y, pt2[2].z);
      downBound[2] = new PVector(pt2[3].x, pt2[3].y, pt2[3].z);
      downBound[3] = new PVector(pt2[1].x, pt2[1].y, pt2[1].z);
      //frontière de l'arrière
      backBound = new PVector[4];
      backBound[0] = new PVector(pt2[2].x, pt2[2].y, pt2[2].z);
      backBound[1] = new PVector(pt2[6].x, pt2[6].y, pt2[6].z);
      backBound[2] = new PVector(pt2[7].x, pt2[7].y, pt2[7].z);
      backBound[3] = new PVector(pt2[3].x, pt2[3].y, pt2[3].z);
      //frontière de gauche
      leftBound = new PVector[4];
      leftBound[0] = new PVector(pt2[1].x, pt2[1].y, pt2[1].z);
      leftBound[1] = new PVector(pt2[3].x, pt2[3].y, pt2[3].z);
      leftBound[2] = new PVector(pt2[7].x, pt2[7].y, pt2[7].z);
      leftBound[3] = new PVector(pt2[5].x, pt2[5].y, pt2[5].z);
    }
    void strOfMoves(){//algorithme
      if(!inMove){//si il n'y pas de risque de perturber l'algorithme en cour
        if(strMoveCount < moveStr.length()){//si le compte de mouvement est inférieur au nombre de mouvement
          faceMove(moveStr.charAt(strMoveCount));//se place au dernier mouvement comptabilisé par strMoveCount
          strMoveCount++;//incrémente strMoveCount de 1
          nbOfMoves++;
        }else{
          moveStrValid = false;//sinon l'ajout de mouvement est invalidé
          strMoveCount = 0;//remise à zero
        }
      }
    }
    int ms=00, s=00, min=00;
    void startTimer(){//chronomètre
      if(!rc.isSolved()){//si le cube est résolut ça n'a pas de sens
        ms++;//augmentation des milliseconde
        if(ms>=100){s++;ms=00;}//si t=100ms : t=1s
        if(s>=60){min++;s=00;}//si t=60s : t=1min
      }else if(ms>=0 && s>0){println("["+millis()+"] "+min+":"+s+"."+ms);min=00;s=00;ms=00;}//affiche temps et le moment où la résolution c'est terminée et aussi pour éviter d'affiche le temps alors qu'il n'y a pas eu de résolution
    }
  • why don't you ask the guy from the other thread?

  • @Chrisir: okay, but do you see other errors ?

  • @asimes can you help me ?

  • There is too much code to look for an unknown error, can you try to isolate it?

  • Okay:

    void solve(String method) {//méthode à utiliser pour résoudre le cube
      solverStat = "inspection ...";
      println(solverStat);
      if (!rc.isSolved()) {//si le cube n'est pas résolu
        println("code: "+rc.codeString());//affiche le code du cube
        if (method.toLowerCase().equals("undo") || method.toLowerCase().equals(solvingMethod[0])) {//méthode du robot
          println("lancement de la méthode undo, top="+stackOfMoves.top);
          while (stackOfMoves.top>=0) {//tant que le cube n'est pas résolue l'IA undo les mouvements
            undo();
          }
        }
        else if (method.toLowerCase().equals("beginner") || method.toLowerCase().equals("lbl") || method.toLowerCase().equals(solvingMethod[1])) {//méthode des débutant
          //Scanne du cube pour trouver les cubies
          solverStat = "scan pour trouver UF, UR, UB et UL";
          int[] UFpos = getCubie("UF"), URpos = getCubie("UR"), UBpos = getCubie("UB"), ULpos = getCubie("UL");//positions des 4 premières arrêtes ciblé par la 1er étape de cette méthode
          if (UFpos[0]>=3 || UFpos[0]<0) UFpos = getCubie("FU");//si le cubie n'est pas dans/sur le cube
          if (URpos[0]>=3 || URpos[0]<0) URpos = getCubie("RU");
          if (UBpos[0]>=3 || UBpos[0]<0) UBpos = getCubie("BU");
          if (ULpos[0]>=3 || ULpos[0]<0) ULpos = getCubie("LU");
          //indique les positions des cubies désirer
          solverStat = "recherche d'un solution ...\nUF("+UFpos[0]+", "+UFpos[1]+", "+UFpos[2]+"), UR("+URpos[0]+", "+URpos[1]+", "+URpos[2]+"), UB("+UBpos[0]+", "+UBpos[1]+", "+UBpos[2]+"), UL("+ULpos[0]+", "+ULpos[1]+", "+ULpos[2]+")";
          frame.setTitle("Rubik's Cube Simulator - Solveur: "+solverStat);
          println(solverStat);//affiche l'état du solveur
          solverStat = "1ère étape: la croix";
          //UF
          //whoIs("UF");//à quel place se trouve le cubie UF
          if (!cubieInPlace2(UFpos, "UF") || !cubieInPlace("UF")) {//si le cubie n'est pas à sa place
            solverStat = "place UF";
            frame.setTitle("Rubik's Cube Simulator - Solveur: "+solverStat);
            println(solverStat);
            if (cubieIsOriented("UF")) {//bonne arrête
              //recherche de l'emplacement du cubie (cf. fiche)
              solverStat = "UF est orienter";
              frame.setTitle("Rubik's Cube Simulator - Solveur: "+solverStat);
              println(solverStat);
              if (UFpos[0]==1 && UFpos[1]==0 && UFpos[2]==2) moveStr = "FF";//MDDm si les coins (UFR et ULF) sont résolu
              else if (UFpos[0]==0 && UFpos[1]==1 && UFpos[2]==2) moveStr = "Ulu";
              else if (UFpos[0]==2 && UFpos[1]==1 && UFpos[2]==2) moveStr = "uRU";
              else if (UFpos[0]==0 && UFpos[1]==0 && UFpos[2]==1) moveStr = "DFF";
              else if (UFpos[0]==2 && UFpos[1]==0 && UFpos[2]==1) moveStr = "dFF";
              else if (UFpos[0]==1 && UFpos[1]==0 && UFpos[2]==0) moveStr = "DDFF";
              else if (UFpos[0]==0 && UFpos[1]==2 && UFpos[2]==1) moveStr = "u";
              else solverStat = "je peux pas trouver UF";
              frame.setTitle("Rubik's Cube Simulator - Solveur: "+solverStat);
              println(solverStat);
              algorithm=moveStr;
              moveStrValid=true;
            }
            else {//mauvaise arrête (mal orienté)
              if (cubieInPlace2(UFpos, "FU") || cubieInPlace("FU")) solverStat = "UF in place but misoriented";
              else solverStat = "UF have a problem";
              solverStat = "UF isn't oriented";
              frame.setTitle("Rubik's Cube Simulator - Solveur: "+solverStat);
              println(solverStat);
              if (UFpos[0]==1 && UFpos[1]==0 && UFpos[2]==2) moveStr = "DMdm";//dMDm (mirroir)
              else if (UFpos[0]==0 && UFpos[1]==1 && UFpos[2]==2) moveStr = "F";
              else if (UFpos[0]==2 && UFpos[1]==1 && UFpos[2]==2) moveStr = "f";
              else if (UFpos[0]==0 && UFpos[1]==0 && UFpos[2]==1) moveStr = "lFl";
              else if (UFpos[0]==2 && UFpos[1]==0 && UFpos[2]==1) moveStr = "Rfr";
              else if (UFpos[0]==1 && UFpos[1]==2 && UFpos[2]==2) moveStr = "FuRU";//fUlu (mirroir) ou FFDMdm ou ffdMDm
              else if (UFpos[0]==0 && UFpos[1]==2 && UFpos[2]==1) moveStr = "u";
              else solverStat = "I can't find FU";
              frame.setTitle("Rubik's Cube Simulator - Solveur: "+solverStat);
              println(solverStat);
              algorithm=moveStr;
              moveStrValid=true;
            }
          }//else rc.rotU();//Y pour passer au cubie suivant
          algorithm = moveStr;
          frame.setTitle("Rubik's Cube Simulator - Solveur: "+solverStat);
          println(solverStat);
          /*//UR
           if(!cubieInPlace("UR")){
           solverStat = "placing UR";
           if(cubieIsOriented("UR")){//bonne arrêtes
           if(URpos[0]==1 && URpos[1]==0 && URpos[2]==2) moveStr = "FF";
           else if(URpos[0]==0 && URpos[1]==1 && URpos[2]==2) moveStr = "F";
           else if(URpos[0]==2 && URpos[1]==1 && URpos[2]==2) moveStr = "f";
           else if(URpos[0]==0 && URpos[1]==0 && URpos[2]==1) moveStr = "DFF";
           else if(URpos[0]==2 && URpos[1]==0 && URpos[2]==1) moveStr = "dFF";
           else solverStat = "I can't find UR";
           moveStrValid=true;
           }else{//mauvaise arrête
           if(URpos[0]==1 && URpos[1]==0 && URpos[2]==2) moveStr = "DMdm";
           else if(URpos[0]==0 && URpos[1]==1 && URpos[2]==2) moveStr = "Ulu";
           else if(URpos[0]==2 && URpos[1]==1 && URpos[2]==2) moveStr = "uRU";
           else if(URpos[0]==0 && URpos[1]==0 && URpos[2]==1) moveStr = "lFl";
           else if(URpos[0]==2 && URpos[1]==0 && URpos[2]==1) moveStr = "Rfr";
           else if(URpos[0]==1 && URpos[1]==2 && URpos[2]==2) moveStr = "FuRU";
           else solverStat = "I can't find RU";
           moveStrValid=true;
           }
           }else rc.rotU();
           algorithm = moveStr;moveStrValid = true;
           if(!cubieInPlace("UB")){
           solverStat = "placing UB";
           if(cubieIsOriented("UB")){
           if(UBpos[0]==1 && UBpos[1]==0 && UBpos[2]==2) moveStr = "FF";
           else if(UBpos[0]==0 && UBpos[1]==1 && UBpos[2]==2) moveStr = "F";
           else if(UBpos[0]==2 && UBpos[1]==1 && UBpos[2]==2) moveStr = "f";
           else if(UBpos[0]==0 && UBpos[1]==0 && UBpos[2]==1) moveStr = "DFF";
           else if(UBpos[0]==2 && UBpos[1]==0 && UBpos[2]==1) moveStr = "dFF";
           else solverStat = "I can't find UB";
           moveStrValid=true;
           }else{
           if(UBpos[0]==1 && UBpos[1]==0 && UBpos[2]==2) moveStr = "DMdm";
           else if(UBpos[0]==0 && UBpos[1]==1 && UBpos[2]==2) moveStr = "Ulu";
           else if(UBpos[0]==2 && UBpos[1]==1 && UBpos[2]==2) moveStr = "UBU";
           else if(UBpos[0]==0 && UBpos[1]==0 && UBpos[2]==1) moveStr = "lFl";
           else if(UBpos[0]==2 && UBpos[1]==0 && UBpos[2]==1) moveStr = "Rfr";
           else if(UBpos[0]==1 && UBpos[1]==2 && UBpos[2]==2) moveStr = "FUBU";
           else solverStat = "I can't find BU";
           moveStrValid=true;
           }
           }else rc.rotU();
           algorithm = moveStr;moveStrValid = true;
           if(!cubieInPlace("UL")){
           solverStat = "placing UL";
           if(cubieIsOriented("UL")){
           if(ULpos[0]==1 && ULpos[1]==0 && ULpos[2]==2) moveStr = "FF";
           else if(ULpos[0]==0 && ULpos[1]==1 && ULpos[2]==2) moveStr = "F";
           else if(ULpos[0]==2 && ULpos[1]==1 && ULpos[2]==2) moveStr = "f";
           else if(ULpos[0]==0 && ULpos[1]==0 && ULpos[2]==1) moveStr = "DFF";
           else if(ULpos[0]==2 && ULpos[1]==0 && ULpos[2]==1) moveStr = "dFF";
           else solverStat = "I can't find UL";
           moveStrValid=true;
           }else{
           if(ULpos[0]==1 && ULpos[1]==0 && ULpos[2]==2) moveStr = "DMdm";
           else if(ULpos[0]==0 && ULpos[1]==1 && ULpos[2]==2) moveStr = "Ulu";
           else if(ULpos[0]==2 && ULpos[1]==1 && ULpos[2]==2) moveStr = "ULU";
           else if(ULpos[0]==0 && ULpos[1]==0 && ULpos[2]==1) moveStr = "lFl";
           else if(ULpos[0]==2 && ULpos[1]==0 && ULpos[2]==1) moveStr = "Rfr";
           else if(ULpos[0]==1 && ULpos[1]==2 && ULpos[2]==2) moveStr = "FULU";
           else solverStat = "I can't find LU";
           moveStrValid=true;
           }
           }else rc.rotU();
           solverStat = "Cross finished";
           solverStat = "scanning to find UFR, URB, UBL and ULF";
           int[] UFRpos = getCubie("UFR"), URBpos = getCubie("URB"), UBLpos = getCubie("UBL"), ULFpos = getCubie("ULF");//positions des 4 premières coins ciblé par la 2ème étape de cette méthode*/
        }
        else if (method.toLowerCase().equals("fridrich") || method.toLowerCase().equals("cfop") || method.toLowerCase().equals(solvingMethod[2])) {//méthode utiliser par des speedcubers
        }
        else if (method.toLowerCase().equals("petrus") || method.toLowerCase().equals(solvingMethod[3])) {//méthode utiliser par des speedcubers
        }
        else if (method.toLowerCase().equals("roux") || method.toLowerCase().equals(solvingMethod[4])) {//...
        }
        else if (method.toLowerCase().equals("edgefirst") || method.toLowerCase().equals(solvingMethod[5])) {
        }
        else if (method.toLowerCase().equals("cornerfirst") || method.toLowerCase().equals(solvingMethod[6])) {
        }
        else if (method.toLowerCase().equals("zz") || method.toLowerCase().equals(solvingMethod[7])) {
        }
        else if (method.toLowerCase().equals("vh") || method.toLowerCase().equals(solvingMethod[8])) {
        }
        else if (method.toLowerCase().equals("m2 3op") || method.toLowerCase().equals(solvingMethod[9])) {//méthode utiliser par des speedcubers à l'aveugle
        }
        else {
          println("La méthode choisie pour résoudre le cube n'est pas disponible pour l'instant.\nLes méthodes disponible sont: "+solvingMethod);//indique que la méthode choisi n'est pas disponible et celles disponibles
        }
      }
      else {//si le cube est déjà résolu, ça l'annonce si ce n'était pas le cas et de modifie pas le cube
        solverStat = "cube solved";
        fill(255, 0, 0);
        textSize(24);
        text("Solved", 60, height/2);
        save("data/cubeStyle-"+cubeStyleSelected+".png");//pour garder un aperçu du style en cours
      }
      println(solverStat);//affiche l'état du solveur
      frame.setTitle("Rubik's Cube Simulator - Solveur: "+solverStat);
    }/*
    String[][][] getCubiePos(int[] fpos, String code){
     String[][][] gpos = {{{code}}};
     gpos[fpos[0]][fpos[1]][fpos[2]] = code;
     return gpos;
     }*/
    void whoIs(String ccode) {//qui est le cubie
      int[] gC = getCubie(ccode);
      if (cubieInPlace(ccode)) println(ccode+" is in is place");//si le cubie est lui-même (s'il est à sa place)
      else println(ccode+" is in the place of "+rc.grid[gC[0]][gC[1]][gC[2]].code);//sinon on indique quelle cubie appartient à la place où se trouve ce cubie
    }/*
    String[][][] findCubie(String ccode){
     int[] pos = {0};
     String[][][] cpos;
     for(int x=0; x<3; x++){
     for(int y=0; y<3; y++){
     for(int z=0; z<3; z++){
     //int[][][] pos = {x{y{z}}};
     if(rc.grid[x][y][z].code.equals(ccode)){pos[0] = x; pos[1] = y; pos[2] = z;}
     }
     }
     }
     cpos = getCubiePos(pos, ccode);
     return cpos;
     }*/
    int[] getCubie(String code) {//scanne pour trouver le cubie ayant le code
      println("getting cubie "+code+" ...");//debug+indication de l'action effectué par l'IA
      //recherche individuelle des coordonnées du cubie pour éviter de passer par 3 fonctions (celle-ci y compris, dont les deux autre servent à retourner 3 résultat ce qui est complexe à faire) pour savoir où se trouve le cubie (défaut des autres fonctions en commentaire)
      int x=findCubieX(code), y=findCubieY(code), z=findCubieZ(code);
      if (x>=3||x<0||y>=3||y<0||z>=3||z
    void undo() {//comme son nom l'indique
      println("entré dans undo() pile="+stackOfMoves+" top="+stackOfMoves.top);
      //if(!inMove){//pour éviter d'interrompre l'algorithme en cour
      //println("pas en mouvement");
      char p = stackOfMoves.pop();//retire le dernier mouvements enregistré dans le stack
      println("undo par "+moveUndo(p)+" donné: "+stackOfMoves.data[0]+stackOfMoves.data[1]+" top="+stackOfMoves.top);
      faceMove(moveUndo(p));//refait les mouvements sans le dernier
      //moveStr = join(split(undoStr[undoStr.length-1]+"", ""), "");moveStrValid = true;// pour (char) pVal et (char[]) undoStr
      //undoStr.pop(undoStr.length-1);
      /*String poping = join(split(undoStr[undoStr.length-1]+"", ""), "").substring(0, undoStr.length-2);
       String[] popedStr = split(poping, "");*/
      //}else println("en mouvement");
    }
    
  • edited May 2014

    When I said try to identify the unknown error I meant describe when / why it happens. I'm not going to spend hours looking through code when I don't know what I'm looking for

  • honestly the code is too long, the topic too complex and your description of your problem / error too vague. I don't think anybody here has a few hours to spend

    either you offer money here (job opportunity)

    or you find a more experienced fellow student at your university

    that is not meant as a offence, just an advice

    you could go to eclipse where you can better debug

    you could invent more println too see what's going on in your code and where the error lies

    you could describe your error more precise to asimes

    you could make test configurations like clean cube plus row 1 is off by one

    then test: does the solving work? ok.

    next: clean cube row 2

    row 3

    column 1

    column 2

    col 3

    etage 1,2,3

    now go over to more complex configs - thus you can find what's wrong.

    ;-)

  • edited May 2014

    i mean when you want help

    make comments in english not french

    explain how it works (I asked that weeks ago)

    explain what UF UL etc. means

  • in short : ask a fellow student

  • edited May 2014

    Okay:

    void solve(String method) {//method used to solve the cube
      solverStat = "inspection ...";
      println(solverStat);
      if (!rc.isSolved()) {//if the cube'sn't solved
        println("code: "+rc.codeString());//display the cube's code
        if (method.toLowerCase().equals("undo") || method.toLowerCase().equals(solvingMethod[0])) {//robot's method
          println("starting undo method, top="+stackOfMoves.top);
          while (stackOfMoves.top>=0) {//while the cube'sn't solved the AI undo the moves
            undo();
          }
        }
        else if (method.toLowerCase().equals("beginner") || method.toLowerCase().equals("lbl") || method.toLowerCase().equals(solvingMethod[1])) {//Beginner's method
          //Cube scanning to find cubies
          solverStat = "scan to find UF, UR, UB et UL";
          int[] UFpos = getCubie("UF"), URpos = getCubie("UR"), UBpos = getCubie("UB"), ULpos = getCubie("UL");//positions of the first 4 edges targeted by the 1st step of this method
          if (UFpos[0]>=3 || UFpos[0]<0) UFpos = getCubie("FU");//if the cubie isn't in/on the cube
          if (URpos[0]>=3 || URpos[0]<0) URpos = getCubie("RU");
          if (UBpos[0]>=3 || UBpos[0]<0) UBpos = getCubie("BU");
          if (ULpos[0]>=3 || ULpos[0]<0) ULpos = getCubie("LU");
          //give the desired cubies' position
          solverStat = "searching a solution ...\nUF("+UFpos[0]+", "+UFpos[1]+", "+UFpos[2]+"), UR("+URpos[0]+", "+URpos[1]+", "+URpos[2]+"), UB("+UBpos[0]+", "+UBpos[1]+", "+UBpos[2]+"), UL("+ULpos[0]+", "+ULpos[1]+", "+ULpos[2]+")";
          frame.setTitle("Rubik's Cube Simulator - Solver: "+solverStat);
          println(solverStat);//display the solver's stat
          solverStat = "1st step: cross";
          //UF
          //whoIs("UF");//at which place the UF cubie is
          if (!cubieInPlace2(UFpos, "UF") || !cubieInPlace("UF")) {//if the cubie isn't at his place
            solverStat = "placing UF";
            frame.setTitle("Rubik's Cube Simulator - Solver: "+solverStat);
            println(solverStat);
            if (cubieIsOriented("UF")) {//good edge
              //search of the place of the cubie
              solverStat = "UF is oriented";
              frame.setTitle("Rubik's Cube Simulator - Solver: "+solverStat);
              println(solverStat);
              if (UFpos[0]==1 && UFpos[1]==0 && UFpos[2]==2) moveStr = "FF";//MDDm if the corners (UFR and ULF) are solved
              else if (UFpos[0]==0 && UFpos[1]==1 && UFpos[2]==2) moveStr = "Ulu";
              else if (UFpos[0]==2 && UFpos[1]==1 && UFpos[2]==2) moveStr = "uRU";
              else if (UFpos[0]==0 && UFpos[1]==0 && UFpos[2]==1) moveStr = "DFF";
              else if (UFpos[0]==2 && UFpos[1]==0 && UFpos[2]==1) moveStr = "dFF";
              else if (UFpos[0]==1 && UFpos[1]==0 && UFpos[2]==0) moveStr = "DDFF";
              else if (UFpos[0]==0 && UFpos[1]==2 && UFpos[2]==1) moveStr = "u";
              else solverStat = "I can't find UF";
              frame.setTitle("Rubik's Cube Simulator - Solver: "+solverStat);
              println(solverStat);
              algorithm=moveStr;
              moveStrValid=true;
            }
            else {//bad edge (misoriented)
              if (cubieInPlace2(UFpos, "FU") || cubieInPlace("FU")) solverStat = "UF in place but misoriented";
              else solverStat = "UF have a problem";
              solverStat = "UF isn't oriented";
              frame.setTitle("Rubik's Cube Simulator - Solver: "+solverStat);
              println(solverStat);
              if (UFpos[0]==1 && UFpos[1]==0 && UFpos[2]==2) moveStr = "DMdm";//dMDm (mirror)
              else if (UFpos[0]==0 && UFpos[1]==1 && UFpos[2]==2) moveStr = "F";
              else if (UFpos[0]==2 && UFpos[1]==1 && UFpos[2]==2) moveStr = "f";
              else if (UFpos[0]==0 && UFpos[1]==0 && UFpos[2]==1) moveStr = "lFl";
              else if (UFpos[0]==2 && UFpos[1]==0 && UFpos[2]==1) moveStr = "Rfr";
              else if (UFpos[0]==1 && UFpos[1]==2 && UFpos[2]==2) moveStr = "FuRU";//fUlu (mirroir) or FFDMdm or ffdMDm
              else if (UFpos[0]==0 && UFpos[1]==2 && UFpos[2]==1) moveStr = "u";
              else solverStat = "I can't find FU";
              frame.setTitle("Rubik's Cube Simulator - Solver: "+solverStat);
              println(solverStat);
              algorithm=moveStr;
              moveStrValid=true;
            }
          }//else rc.rotU();//Y to go to the following cubie
          algorithm = moveStr;
          frame.setTitle("Rubik's Cube Simulator - Solver: "+solverStat);
          println(solverStat);
          /*//UR
           if(!cubieInPlace("UR")){
           solverStat = "placing UR";
           if(cubieIsOriented("UR")){//good edge
           if(URpos[0]==1 && URpos[1]==0 && URpos[2]==2) moveStr = "FF";
           else if(URpos[0]==0 && URpos[1]==1 && URpos[2]==2) moveStr = "F";
           else if(URpos[0]==2 && URpos[1]==1 && URpos[2]==2) moveStr = "f";
           else if(URpos[0]==0 && URpos[1]==0 && URpos[2]==1) moveStr = "DFF";
           else if(URpos[0]==2 && URpos[1]==0 && URpos[2]==1) moveStr = "dFF";
           else solverStat = "I can't find UR";
           moveStrValid=true;
           }else{//bad edge
           if(URpos[0]==1 && URpos[1]==0 && URpos[2]==2) moveStr = "DMdm";
           else if(URpos[0]==0 && URpos[1]==1 && URpos[2]==2) moveStr = "Ulu";
           else if(URpos[0]==2 && URpos[1]==1 && URpos[2]==2) moveStr = "uRU";
           else if(URpos[0]==0 && URpos[1]==0 && URpos[2]==1) moveStr = "lFl";
           else if(URpos[0]==2 && URpos[1]==0 && URpos[2]==1) moveStr = "Rfr";
           else if(URpos[0]==1 && URpos[1]==2 && URpos[2]==2) moveStr = "FuRU";
           else solverStat = "I can't find RU";
           moveStrValid=true;
           }
           }else rc.rotU();
           algorithm = moveStr;moveStrValid = true;
           if(!cubieInPlace("UB")){
           solverStat = "placing UB";
           if(cubieIsOriented("UB")){
           if(UBpos[0]==1 && UBpos[1]==0 && UBpos[2]==2) moveStr = "FF";
           else if(UBpos[0]==0 && UBpos[1]==1 && UBpos[2]==2) moveStr = "F";
           else if(UBpos[0]==2 && UBpos[1]==1 && UBpos[2]==2) moveStr = "f";
           else if(UBpos[0]==0 && UBpos[1]==0 && UBpos[2]==1) moveStr = "DFF";
           else if(UBpos[0]==2 && UBpos[1]==0 && UBpos[2]==1) moveStr = "dFF";
           else solverStat = "I can't find UB";
           moveStrValid=true;
           }else{
           if(UBpos[0]==1 && UBpos[1]==0 && UBpos[2]==2) moveStr = "DMdm";
           else if(UBpos[0]==0 && UBpos[1]==1 && UBpos[2]==2) moveStr = "Ulu";
           else if(UBpos[0]==2 && UBpos[1]==1 && UBpos[2]==2) moveStr = "UBU";
           else if(UBpos[0]==0 && UBpos[1]==0 && UBpos[2]==1) moveStr = "lFl";
           else if(UBpos[0]==2 && UBpos[1]==0 && UBpos[2]==1) moveStr = "Rfr";
           else if(UBpos[0]==1 && UBpos[1]==2 && UBpos[2]==2) moveStr = "FUBU";
           else solverStat = "I can't find BU";
           moveStrValid=true;
           }
           }else rc.rotU();
           algorithm = moveStr;moveStrValid = true;
           if(!cubieInPlace("UL")){
           solverStat = "placing UL";
           if(cubieIsOriented("UL")){
           if(ULpos[0]==1 && ULpos[1]==0 && ULpos[2]==2) moveStr = "FF";
           else if(ULpos[0]==0 && ULpos[1]==1 && ULpos[2]==2) moveStr = "F";
           else if(ULpos[0]==2 && ULpos[1]==1 && ULpos[2]==2) moveStr = "f";
           else if(ULpos[0]==0 && ULpos[1]==0 && ULpos[2]==1) moveStr = "DFF";
           else if(ULpos[0]==2 && ULpos[1]==0 && ULpos[2]==1) moveStr = "dFF";
           else solverStat = "I can't find UL";
           moveStrValid=true;
           }else{
           if(ULpos[0]==1 && ULpos[1]==0 && ULpos[2]==2) moveStr = "DMdm";
           else if(ULpos[0]==0 && ULpos[1]==1 && ULpos[2]==2) moveStr = "Ulu";
           else if(ULpos[0]==2 && ULpos[1]==1 && ULpos[2]==2) moveStr = "ULU";
           else if(ULpos[0]==0 && ULpos[1]==0 && ULpos[2]==1) moveStr = "lFl";
           else if(ULpos[0]==2 && ULpos[1]==0 && ULpos[2]==1) moveStr = "Rfr";
           else if(ULpos[0]==1 && ULpos[1]==2 && ULpos[2]==2) moveStr = "FULU";
           else solverStat = "I can't find LU";
           moveStrValid=true;
           }
           }else rc.rotU();
           solverStat = "Cross finished";
           solverStat = "scanning to find UFR, URB, UBL and ULF";
           int[] UFRpos = getCubie("UFR"), URBpos = getCubie("URB"), UBLpos = getCubie("UBL"), ULFpos = getCubie("ULF");//positions of the 4 first corners targeted by the 2nd step of this method*/
        }
        else if (method.toLowerCase().equals("fridrich") || method.toLowerCase().equals("cfop") || method.toLowerCase().equals(solvingMethod[2])) {//speedcubers' method
        }
        else if (method.toLowerCase().equals("petrus") || method.toLowerCase().equals(solvingMethod[3])) {//speedcubers' method
        }
        else if (method.toLowerCase().equals("roux") || method.toLowerCase().equals(solvingMethod[4])) {//...
        }
        else if (method.toLowerCase().equals("edgefirst") || method.toLowerCase().equals(solvingMethod[5])) {
        }
        else if (method.toLowerCase().equals("cornerfirst") || method.toLowerCase().equals(solvingMethod[6])) {
        }
        else if (method.toLowerCase().equals("zz") || method.toLowerCase().equals(solvingMethod[7])) {
        }
        else if (method.toLowerCase().equals("vh") || method.toLowerCase().equals(solvingMethod[8])) {
        }
        else if (method.toLowerCase().equals("m2 3op") || method.toLowerCase().equals(solvingMethod[9])) {//blindfolded speedcubers' method
        }
        else {
          println("The choosen method to solve it isn't available for the moment.\nThe available methods are: "+solvingMethod);//tell that the choosen method isn't available and which ones are
        }
      }
      else {//if the cube is already solved, it annouce it if it wasn't the case and don't edit the cubie
        solverStat = "cube solved";
        fill(255, 0, 0);
        textSize(24);
        text("Solved", 60, height/2);
        save("data/cubeStyle-"+cubeStyleSelected+".png");//to keep a snapshot of the current style
      }
      println(solverStat);//display the solver's stat
      frame.setTitle("Rubik's Cube Simulator - Solver: "+solverStat);
    }/*
    String[][][] getCubiePos(int[] fpos, String code){
     String[][][] gpos = {{{code}}};
     gpos[fpos[0]][fpos[1]][fpos[2]] = code;
     return gpos;
     }*/
    void whoIs(String ccode) {//who is the cubie
      int[] gC = getCubie(ccode);
      if (cubieInPlace(ccode)) println(ccode+" is in is place");//if the cubie is it-self (if it's in place)
      else println(ccode+" is in the place of "+rc.grid[gC[0]][gC[1]][gC[2]].code);//else we tell which cubie belong to this place
    }/*
    String[][][] findCubie(String ccode){
     int[] pos = {0};
     String[][][] cpos;
     for(int x=0; x<3; x++){
     for(int y=0; y<3; y++){
     for(int z=0; z<3; z++){
     //int[][][] pos = {x{y{z}}};
     if(rc.grid[x][y][z].code.equals(ccode)){pos[0] = x; pos[1] = y; pos[2] = z;}
     }
     }
     }
     cpos = getCubiePos(pos, ccode);
     return cpos;
     }*/
    int[] getCubie(String code) {//scan to find the cubie with the corresponding code
      println("getting cubie "+code+" ...");//debug+action of the AI
      //individual search of the cubie's coords to avoid passing through 3 functions (including this one, when the 2 others serve to return 3 results which is complexe to do) to know where's the cubie (drawback of the others function in comment)
      int x=findCubieX(code), y=findCubieY(code), z=findCubieZ(code);
      if (x>=3||x<0||y>=3||y<0||z>=3||z
    void undo() {//as it name says
      println("entered in undo() stack="+stackOfMoves+" top="+stackOfMoves.top);
      //if(!inMove){//to avoid interrupt the current algorithm
      //println("not moving");
      char p = stackOfMoves.pop();//pop out the last move saved in stackOfMoves
      println("undo by "+moveUndo(p)+" data: "+stackOfMoves.data[0]+stackOfMoves.data[1]+" top="+stackOfMoves.top);
      faceMove(moveUndo(p));//re do the algorithm without the last move 
      //moveStr = join(split(undoStr[undoStr.length-1]+"", ""), "");moveStrValid = true;// for (char) pVal and (char[]) undoStr
      //undoStr.pop(undoStr.length-1);
      /*String poping = join(split(undoStr[undoStr.length-1]+"", ""), "").substring(0, undoStr.length-2);
       String[] popedStr = split(poping, "");*/
      //}else println("moving");
    }
    

    The problem is that when the solver use Undo method it undo only one move and a bad one, when it's Beginner's method the AI is unable to execute the desired algorithms depending on the cubies' positions but the scanning is done so the code goes well until the execution

Sign In or Register to comment.