Created
December 7, 2014 16:44
-
-
Save Berkmann18/cbee913aa2fba14c3c21 to your computer and use it in GitHub Desktop.
My Rubik's Cube Simulator made on Processing for my final ISN exam
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Projet final d'ISN 2013-2014 | |
auteur: Berkmann Maximilian | |
*/ | |
//import java.processing.opengl; | |
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 | |
text("scramble: "+algorithm, 20, 40);//affiche le mélange | |
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[999]; | |
for (int i=0; i<data.length; i++) { | |
data[i] = ' '; | |
} | |
} | |
void push(char v) {//ajout d'un caractère | |
println("push"); | |
top++; | |
if (top < 999) data[top] = v;//si le seuil n'est pas au maximum | |
} | |
char pop() {//enl����ve un caractère | |
println("pop top="+top); | |
char tmp = ' '; | |
if (top>=0) { | |
tmp = data[top]; | |
top--; | |
} | |
println("pop après top="+top); | |
return tmp; | |
} | |
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; | |
for (int i=0; i<data.length; i++) { | |
data[i] = ' '; | |
} | |
} | |
} | |
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("URRFBRBBRUULBBRudRRFrLBBUUFF"), //superflip | |
new String("FRUFRUFRU"), new String("MMEESS")/*damier*/, 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[11];//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 = "inspection ..."; | |
println(solverStat); | |
if (!rc.isSolved()) {//si le cube n'est pas résolu | |
println("code: "+rc.codeString());//affiche le code du cube | |
if (method.toLowerCase().equals("undo") || method.toLowerCase().equals(solvingMethod[0])) {//méthode du robot | |
println("lancement de la méthode undo, top="+stackOfMoves.top); | |
while (stackOfMoves.top>=0) {//tant que le cube n'est pas résolue l'IA undo les mouvements | |
undo(); | |
} | |
} | |
else if (method.toLowerCase().equals("beginner") || method.toLowerCase().equals("lbl") || method.toLowerCase().equals(solvingMethod[1])) {//méthode des débutant | |
//Scanne du cube pour trouver les cubies | |
solverStat = "scan pour trouver UF, UR, UB et UL"; | |
int[] UFpos = getCubie("UF"), URpos = getCubie("UR"), UBpos = getCubie("UB"), ULpos = getCubie("UL");//positions des 4 premières arrêtes ciblé par la 1er étape de cette méthode | |
if (UFpos[0]>=3 || UFpos[0]<0) UFpos = getCubie("FU");//si le cubie n'est pas dans/sur le cube | |
if (URpos[0]>=3 || URpos[0]<0) URpos = getCubie("RU"); | |
if (UBpos[0]>=3 || UBpos[0]<0) UBpos = getCubie("BU"); | |
if (ULpos[0]>=3 || ULpos[0]<0) ULpos = getCubie("LU"); | |
//indique les positions des cubies désirer | |
solverStat = "recherche d'un solution ...\nUF("+UFpos[0]+", "+UFpos[1]+", "+UFpos[2]+"), UR("+URpos[0]+", "+URpos[1]+", "+URpos[2]+"), UB("+UBpos[0]+", "+UBpos[1]+", "+UBpos[2]+"), UL("+ULpos[0]+", "+ULpos[1]+", "+ULpos[2]+")"; | |
//frame.setTitle("Rubik's Cube Simulator - Solveur: "+solverStat); | |
println(solverStat);//affiche l'état du solveur | |
solverStat = "1ère étape: la croix"; | |
//UF | |
//whoIs("UF");//à quel place se trouve le cubie UF | |
if (!cubieInPlace2(UFpos, "UF") || !cubieInPlace("UF")) {//si le cubie n'est pas à sa place | |
solverStat = "place UF"; | |
//frame.setTitle("Rubik's Cube Simulator - Solveur: "+solverStat); | |
println(solverStat); | |
if (cubieIsOriented("UF")) {//bonne arrête | |
//recherche de l'emplacement du cubie (cf. fiche) | |
solverStat = "UF est orienter"; | |
//frame.setTitle("Rubik's Cube Simulator - Solveur: "+solverStat); | |
println(solverStat); | |
if (UFpos[0]==1 && UFpos[1]==0 && UFpos[2]==2) moveStr = "FF";//MDDm si les coins (UFR et ULF) sont résolu | |
else if (UFpos[0]==0 && UFpos[1]==1 && UFpos[2]==2) moveStr = "Ulu"; | |
else if (UFpos[0]==2 && UFpos[1]==1 && UFpos[2]==2) moveStr = "uRU"; | |
else if (UFpos[0]==0 && UFpos[1]==0 && UFpos[2]==1) moveStr = "DFF"; | |
else if (UFpos[0]==2 && UFpos[1]==0 && UFpos[2]==1) moveStr = "dFF"; | |
else if (UFpos[0]==1 && UFpos[1]==0 && UFpos[2]==0) moveStr = "DDFF"; | |
else if (UFpos[0]==0 && UFpos[1]==2 && UFpos[2]==1) moveStr = "u"; | |
else solverStat = "je peux pas trouver UF"; | |
//frame.setTitle("Rubik's Cube Simulator - Solveur: "+solverStat); | |
println(solverStat); | |
algorithm=moveStr; | |
moveStrValid=true; | |
} | |
else {//mauvaise arrête (mal orienté) | |
if (cubieInPlace2(UFpos, "FU") || cubieInPlace("FU")) solverStat = "UF in place but misoriented"; | |
else solverStat = "UF have a problem"; | |
solverStat = "UF isn't oriented"; | |
//frame.setTitle("Rubik's Cube Simulator - Solveur: "+solverStat); | |
println(solverStat); | |
if (UFpos[0]==1 && UFpos[1]==0 && UFpos[2]==2) moveStr = "DMdm";//dMDm (mirroir) | |
else if (UFpos[0]==0 && UFpos[1]==1 && UFpos[2]==2) moveStr = "F"; | |
else if (UFpos[0]==2 && UFpos[1]==1 && UFpos[2]==2) moveStr = "f"; | |
else if (UFpos[0]==0 && UFpos[1]==0 && UFpos[2]==1) moveStr = "lFl"; | |
else if (UFpos[0]==2 && UFpos[1]==0 && UFpos[2]==1) moveStr = "Rfr"; | |
else if (UFpos[0]==1 && UFpos[1]==2 && UFpos[2]==2) moveStr = "FuRU";//fUlu (mirroir) ou FFDMdm ou ffdMDm | |
else if (UFpos[0]==0 && UFpos[1]==2 && UFpos[2]==1) moveStr = "u"; | |
else solverStat = "I can't find FU"; | |
//frame.setTitle("Rubik's Cube Simulator - Solveur: "+solverStat); | |
println(solverStat); | |
algorithm=moveStr; | |
moveStrValid=true; | |
} | |
}//else rc.rotU();//Y pour passer au cubie suivant | |
algorithm = moveStr; | |
//frame.setTitle("Rubik's Cube Simulator - Solveur: "+solverStat); | |
println(solverStat); | |
/*//UR | |
if(!cubieInPlace("UR")){ | |
solverStat = "placing UR"; | |
if(cubieIsOriented("UR")){//bonne arrêtes | |
if(URpos[0]==1 && URpos[1]==0 && URpos[2]==2) moveStr = "FF"; | |
else if(URpos[0]==0 && URpos[1]==1 && URpos[2]==2) moveStr = "F"; | |
else if(URpos[0]==2 && URpos[1]==1 && URpos[2]==2) moveStr = "f"; | |
else if(URpos[0]==0 && URpos[1]==0 && URpos[2]==1) moveStr = "DFF"; | |
else if(URpos[0]==2 && URpos[1]==0 && URpos[2]==1) moveStr = "dFF"; | |
else solverStat = "I can't find UR"; | |
moveStrValid=true; | |
}else{//mauvaise arrête | |
if(URpos[0]==1 && URpos[1]==0 && URpos[2]==2) moveStr = "DMdm"; | |
else if(URpos[0]==0 && URpos[1]==1 && URpos[2]==2) moveStr = "Ulu"; | |
else if(URpos[0]==2 && URpos[1]==1 && URpos[2]==2) moveStr = "uRU"; | |
else if(URpos[0]==0 && URpos[1]==0 && URpos[2]==1) moveStr = "lFl"; | |
else if(URpos[0]==2 && URpos[1]==0 && URpos[2]==1) moveStr = "Rfr"; | |
else if(URpos[0]==1 && URpos[1]==2 && URpos[2]==2) moveStr = "FuRU"; | |
else solverStat = "I can't find RU"; | |
moveStrValid=true; | |
} | |
}else rc.rotU(); | |
algorithm = moveStr;moveStrValid = true; | |
if(!cubieInPlace("UB")){ | |
solverStat = "placing UB"; | |
if(cubieIsOriented("UB")){ | |
if(UBpos[0]==1 && UBpos[1]==0 && UBpos[2]==2) moveStr = "FF"; | |
else if(UBpos[0]==0 && UBpos[1]==1 && UBpos[2]==2) moveStr = "F"; | |
else if(UBpos[0]==2 && UBpos[1]==1 && UBpos[2]==2) moveStr = "f"; | |
else if(UBpos[0]==0 && UBpos[1]==0 && UBpos[2]==1) moveStr = "DFF"; | |
else if(UBpos[0]==2 && UBpos[1]==0 && UBpos[2]==1) moveStr = "dFF"; | |
else solverStat = "I can't find UB"; | |
moveStrValid=true; | |
}else{ | |
if(UBpos[0]==1 && UBpos[1]==0 && UBpos[2]==2) moveStr = "DMdm"; | |
else if(UBpos[0]==0 && UBpos[1]==1 && UBpos[2]==2) moveStr = "Ulu"; | |
else if(UBpos[0]==2 && UBpos[1]==1 && UBpos[2]==2) moveStr = "UBU"; | |
else if(UBpos[0]==0 && UBpos[1]==0 && UBpos[2]==1) moveStr = "lFl"; | |
else if(UBpos[0]==2 && UBpos[1]==0 && UBpos[2]==1) moveStr = "Rfr"; | |
else if(UBpos[0]==1 && UBpos[1]==2 && UBpos[2]==2) moveStr = "FUBU"; | |
else solverStat = "I can't find BU"; | |
moveStrValid=true; | |
} | |
}else rc.rotU(); | |
algorithm = moveStr;moveStrValid = true; | |
if(!cubieInPlace("UL")){ | |
solverStat = "placing UL"; | |
if(cubieIsOriented("UL")){ | |
if(ULpos[0]==1 && ULpos[1]==0 && ULpos[2]==2) moveStr = "FF"; | |
else if(ULpos[0]==0 && ULpos[1]==1 && ULpos[2]==2) moveStr = "F"; | |
else if(ULpos[0]==2 && ULpos[1]==1 && ULpos[2]==2) moveStr = "f"; | |
else if(ULpos[0]==0 && ULpos[1]==0 && ULpos[2]==1) moveStr = "DFF"; | |
else if(ULpos[0]==2 && ULpos[1]==0 && ULpos[2]==1) moveStr = "dFF"; | |
else solverStat = "I can't find UL"; | |
moveStrValid=true; | |
}else{ | |
if(ULpos[0]==1 && ULpos[1]==0 && ULpos[2]==2) moveStr = "DMdm"; | |
else if(ULpos[0]==0 && ULpos[1]==1 && ULpos[2]==2) moveStr = "Ulu"; | |
else if(ULpos[0]==2 && ULpos[1]==1 && ULpos[2]==2) moveStr = "ULU"; | |
else if(ULpos[0]==0 && ULpos[1]==0 && ULpos[2]==1) moveStr = "lFl"; | |
else if(ULpos[0]==2 && ULpos[1]==0 && ULpos[2]==1) moveStr = "Rfr"; | |
else if(ULpos[0]==1 && ULpos[1]==2 && ULpos[2]==2) moveStr = "FULU"; | |
else solverStat = "I can't find LU"; | |
moveStrValid=true; | |
} | |
}else rc.rotU(); | |
solverStat = "Cross finished"; | |
solverStat = "scanning to find UFR, URB, UBL and ULF"; | |
int[] UFRpos = getCubie("UFR"), URBpos = getCubie("URB"), UBLpos = getCubie("UBL"), ULFpos = getCubie("ULF");//positions des 4 premières coins ciblé par la 2������������������me étape de cette méthode*/ | |
} | |
else if (method.toLowerCase().equals("fridrich") || method.toLowerCase().equals("cfop") || method.toLowerCase().equals(solvingMethod[2])) {//méthode utiliser par des speedcubers | |
} | |
else if (method.toLowerCase().equals("petrus") || method.toLowerCase().equals(solvingMethod[3])) {//méthode utiliser par des speedcubers | |
} | |
else if (method.toLowerCase().equals("roux") || method.toLowerCase().equals(solvingMethod[4])) {//... | |
} | |
else if (method.toLowerCase().equals("edgefirst") || method.toLowerCase().equals(solvingMethod[5])) { | |
} | |
else if (method.toLowerCase().equals("cornerfirst") || method.toLowerCase().equals(solvingMethod[6])) { | |
} | |
else if (method.toLowerCase().equals("zz") || method.toLowerCase().equals(solvingMethod[7])) { | |
} | |
else if (method.toLowerCase().equals("vh") || method.toLowerCase().equals(solvingMethod[8])) { | |
} | |
else if (method.toLowerCase().equals("m2 3op") || method.toLowerCase().equals(solvingMethod[9])) {//méthode utiliser par des speedcubers à l'aveugle | |
} | |
else { | |
println("La méthode choisie pour résoudre le cube n'est pas disponible pour l'instant.\nLes méthodes disponible sont: "+solvingMethod);//indique que la méthode choisi n'est pas disponible et celles disponibles | |
} | |
} | |
else {//si le cube est déjà résolu, ça l'annonce si ce n'était pas le cas et de modifie pas le cube | |
solverStat = "cube solved"; | |
fill(255, 0, 0); | |
textSize(24); | |
text("Solved", 60, height/2); | |
save("data/cubeStyle-"+cubeStyleSelected+".png");//pour garder un aperçu du style en cours | |
} | |
println(solverStat);//affiche l'état du solveur | |
//frame.setTitle("Rubik's Cube Simulator - Solveur: "+solverStat); | |
}/* | |
String[][][] getCubiePos(int[] fpos, String code){ | |
String[][][] gpos = {{{code}}}; | |
gpos[fpos[0]][fpos[1]][fpos[2]] = code; | |
return gpos; | |
}*/ | |
void whoIs(String ccode) {//qui est le cubie | |
int[] gC = getCubie(ccode); | |
if (cubieInPlace(ccode)) println(ccode+" is in is place");//si le cubie est lui-même (s'il est à sa place) | |
else println(ccode+" is in the place of "+rc.grid[gC[0]][gC[1]][gC[2]].code);//sinon on indique quelle cubie appartient à la place où se trouve ce cubie | |
}/* | |
String[][][] findCubie(String ccode){ | |
int[] pos = {0}; | |
String[][][] cpos; | |
for(int x=0; x<3; x++){ | |
for(int y=0; y<3; y++){ | |
for(int z=0; z<3; z++){ | |
//int[][][] pos = {x{y{z}}}; | |
if(rc.grid[x][y][z].code.equals(ccode)){pos[0] = x; pos[1] = y; pos[2] = z;} | |
} | |
} | |
} | |
cpos = getCubiePos(pos, ccode); | |
return cpos; | |
}*/ | |
int[] getCubie(String code) {//scanne pour trouver le cubie ayant le code | |
println("getting cubie "+code+" ...");//debug+indication de l'action effectué par l'IA | |
//recherche individuelle des coordonnées du cubie pour éviter de passer par 3 fonctions (celle-ci y compris, dont les deux autre servent à retourner 3 résultat ce qui est complexe à faire) pour savoir où se trouve le cubie (défaut des autres fonctions en commentaire) | |
int x=findCubieX(code), y=findCubieY(code), z=findCubieZ(code); | |
if (x>=3||x<0||y>=3||y<0||z>=3||z<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 cubieInPlace2(int[] p, String c) {//Si le cubie à besoin d'être permuter ou non (si c'est en place) | |
if (rc.grid[p[0]][p[1]][p[2]].code.equals(c)) return true;//s'il est à sa place alors ��a retourne vrai | |
else if (c.length()==2 && rc.flipEdge(rc.grid[p[0]][p[1]][p[2]].code).equals(c)) return true; | |
else if (c.length()==3 && rc.rotateStr(rc.grid[p[0]][p[1]][p[2]].code, 1).equals(c)) return true; | |
else if (c.length()==3 && rc.rotateStr(rc.grid[p[0]][p[1]][p[2]].code, 2).equals(c)) 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 | |
algorithm = ""; | |
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 || keyCode == 75 || keyCode == 44 || keyCode == 53 || keyCode == 54) { | |
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' | |
/* | |
if (nbOfMoves>0 && algorithm != "" && inMove) println("moves: "+nbOfMoves);//dans la console | |
if (inMove) println("scramble: "+algorithm);//affiche le mélange dans la console*/ | |
moveStrValid = true; | |
algorithm += moveStr;//bien sur en conserve une trace écrite des mouvements fait | |
println("moveStr="+moveStr); | |
stackOfMoves.push(moveStr.charAt(0)); | |
println("moveStr="+moveStr+" après"); | |
println("pile="+stackOfMoves.data[0]+stackOfMoves.data[1]+" top="+stackOfMoves.top); | |
} | |
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 && keyCode != 49) chCubeStyle(1);//va plus haut dans la table à style | |
else if (key == DOWN || keyCode == 40 && keyCode != 53) 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; | |
} | |
println(pVal); | |
//undoStr[undoStr.length] = pVal;//undoStr.push(pVal); | |
move(true);//autorise le mouvement | |
} | |
void undo() {//comme son nom l'indique | |
println("entré dans undo() pile="+stackOfMoves+" top="+stackOfMoves.top); | |
//if(!inMove){//pour éviter d'interrompre l'algorithme en cour | |
//println("pas en mouvement"); | |
char p = stackOfMoves.pop();//retire le dernier mouvements enregistré dans le stack | |
println("undo par "+moveUndo(p)+" donné: "+stackOfMoves.data[0]+stackOfMoves.data[1]+" top="+stackOfMoves.top); | |
faceMove(moveUndo(p));//refait les mouvements sans le dernier | |
//moveStr = join(split(undoStr[undoStr.length-1]+"", ""), "");moveStrValid = true;// pour (char) pVal et (char[]) undoStr | |
//undoStr.pop(undoStr.length-1); | |
/*String poping = join(split(undoStr[undoStr.length-1]+"", ""), "").substring(0, undoStr.length-2); | |
String[] popedStr = split(poping, "");*/ | |
//}else println("en mouvement"); | |
} | |
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 | |
} | |
char moveUndo(char move) { | |
String str = move+""; | |
if (str.equals(str.toLowerCase())) { | |
return str.toUpperCase().charAt(0); | |
} | |
else return str.toLowerCase().charAt(0); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment