We are about to switch to a new forum software. Until then we have removed the registration on this forum.
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:
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 ==.
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; }@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
@PhiLho where's the error ? Is this for debugging or what ?
line 5, 9, 38, 40 ... everywhere ;-)
as he wrote: every string must be compared with equals -- never use == for string pls
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
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
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 }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||zvoid 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"); }So ?
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.
;-)
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
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||zvoid 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