Rubikcubesolver fuer Dummies
Theo Boehm & Eliah Hueber
#include <Keypad.h>
#include "rgb_lcd.h"
rgb_lcd lcd;
// Die Verschiedenen Farben bekommen alle eine Zahl zugeordnet
// Weiss ist die 0
// Blau = 1
// Rot = 2
// Gruen = 3
// Orange = 4
// Gelb ist die 5
// Cube wird "leer" definiert und spaeter "gefuehlt"
int Cube[6][3][3] ={ {{6,6,6},{6,6,6},{6,6,6}},{{6,6,6},{6,6,6},{6,6,6}} ,{{6,6,6},{6,6,6},{6,6,6}} ,{{6,6,6},{6,6,6},{6,6,6}} ,{{6,6,6},{6,6,6},{6,6,6}} ,{{6,6,6},{6,6,6},{6,6,6}} };
int seite[3][3];
char farben[7] = {'W','B','R','G','O','Y','X'};
// Das Tastfeld wird Initialisiert
const byte ROWS = 4; //four rows
const byte COLS = 4; //three columns
char keys[ROWS][COLS] = {
{'0','1','2','6'},
{'3','4','5','6' },
{'6','6','6','6'},
{'6','6','6','6'}
};
byte rowPins[ROWS] = {9, 8, 7, 6}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {5, 4, 3, 2}; //connect to the column pinouts of the keypad
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
// Programm um alles einzulesen
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------
// Befor das eigenliche Programm kommt, wird noch eine Funktion definiert, welche Pfeile darstellen sollte beim Einlesen
void Pfeilprint(){
byte Pfeilobenlinks[8] = {
0b00000,
0b11100,
0b11000,
0b10100,
0b00010,
0b00001,
0b00000,
0b00000
};
byte Pfeilobenmitte[8] = {
0b00100,
0b01110,
0b11111,
0b00100,
0b00100,
0b00100,
0b00000,
0b00000
};
byte Pfeilobenrechts[8] = {
0b00000,
0b00111,
0b00011,
0b00101,
0b01000,
0b10000,
0b00000,
0b00000
};
byte Pfeilmittelinks[8] = {
0b00000,
0b00100,
0b01100,
0b11111,
0b01100,
0b00100,
0b00000,
0b00000
};
byte Pfeilmittemitte[8] = {
0b00000,
0b00100,
0b01110,
0b11111,
0b01110,
0b00100,
0b00000,
0b00000
};
byte Pfeilmitterechts[8] = {
0b00000,
0b00100,
0b00110,
0b11111,
0b00110,
0b00100,
0b00000,
0b00000
};byte Pfeiluntenlinks[8] = {
0b00000,
0b00000,
0b00001,
0b00010,
0b10100,
0b11000,
0b11100,
0b00000
};
byte Pfeiluntenmitte[8] = {
0b00000,
0b00000,
0b00100,
0b00100,
0b00100,
0b11111,
0b01110,
0b00100
};
byte Pfeiluntenrechts[8] = {
0b00000,
0b00000,
0b10000,
0b01000,
0b00101,
0b00011,
0b00111,
0b00000
};
lcd.createChar(0, Pfeilobenlinks);
lcd.createChar(1, Pfeilobenmitte);
lcd.createChar(2, Pfeilobenrechts);
lcd.createChar(3, Pfeilmittelinks);
lcd.createChar(4, Pfeilmittemitte);
lcd.createChar(5, Pfeilmitterechts);
lcd.createChar(6, Pfeiluntenlinks);
lcd.createChar(7, Pfeiluntenmitte);
lcd.setCursor(0, 0);
for (int i = 0; i<8;i++)
{
lcd.write((unsigned char)i);
}
lcd.createChar(4, Pfeiluntenrechts);
lcd.setCursor(8, 0);
lcd.write((unsigned char)4);
lcd.setCursor(4, 0);
lcd.print("o");
}
void Farbeneinlesen(){
bool schleifenvariabel = true;
for (int x = 0; x<3;x++)
{
for (int y = 0; y<3;y++)
{
schleifenvariabel = true;
while(schleifenvariabel)
{
char key = keypad.getKey();
if (key != NO_KEY){
seite[x][y] = key - 48; // ein Char wird ein Int umgewandelt, nicht besonders schoen, sollte aber funktionieren
lcd.setCursor(3*x + y, 1);
lcd.print(farben[seite[x][y]]);
Serial.println("Ich bin hier");
schleifenvariabel = false;
}
}
}
}
}
void Seiteeinspeichern()
{
for (int x = 0; x<3;x++)
{
for (int y = 0; y<3;y++)
{
Cube[seite[1][1]][y][x] = seite[y][x];
}
}
}
bool uberpruferoballeseiteneingetipptsind()
{
for (int z = 0; z<6; z++)
{
for (int x = 0; x<3;x++)
{
for (int y = 0; y<3;y++)
{
if (Cube[z][y][x] == 6)
{
return true;
}
}
}
}
Serial.println("Hier ist es noch falsch");
return false;
}
void Einlesenmain()
{
Pfeilprint();
while (uberpruferoballeseiteneingetipptsind()) {
Farbeneinlesen();
Seiteeinspeichern();
delay (1000);
//Alles wird wieder von dem Display gesloescht
lcd.setCursor(0, 1);
lcd.print(" ");
}
for (int z = 0; z<6; z++)
{
for (int x = 0; x<3;x++)
{
for (int y = 0; y<3;y++)
{
Serial.print(Cube[z][x][y]);
}
Serial.print("||");
}
Serial.println();
}
lcd.setCursor(0, 0);
lcd.print(" ");
}
// Programm um alles einzulesen ist fertig
// ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
// Programm fuer Seitenorientierungsalgorythmus
//--------------------------------------------------------------------------------------------------------------------------------------------------------------------
// Cube und Seitenflaechen werden von vorher uebernommen
// wird als ueberpruefungsvariabel benoetigt
bool Teile[20];
//
int Seitenflache[3][3]; // Variabel welche zum Drehen des "virtuellen" Cube benuetzt wird
//
void Seitendreher(int seite) {
// Kopiere
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
Seitenflache[i][j] = Cube[seite][i][j];
}
}
// Abaenderung von A zum passenden, mit einer Rechtsdrehung
Cube[seite][0][0] = Seitenflache[0][2];
Cube[seite][0][2] = Seitenflache[2][2];
Cube[seite][2][2] = Seitenflache[2][0];
Cube[seite][2][0] = Seitenflache[0][0];
Cube[seite][0][1] = Seitenflache[1][2];
Cube[seite][1][2] = Seitenflache[2][1];
Cube[seite][2][1] = Seitenflache[1][0];
Cube[seite][1][0] = Seitenflache[0][1];
}
bool theswitch(int input) {
switch (input) {
case 6:
if (Teile[0] == false)
{
Teile[0] = true;
return true;
}
return false;
// code block
break;
case 10:
if (Teile[1] == false)
{
Teile[1] = true;
return true;
}
return false;
break;
case 14:
if (Teile[2] == false)
{
Teile[2] = true;
return true;
}
return false;
break;
case 22:
if (Teile[3] == false)
{
Teile[3] = true;
return true;
}
return false;
break;
case 39:
if (Teile[4] == false)
{
Teile[4] = true;
return true;
}
return false;
break;
case 65:
if (Teile[5] == false)
{
Teile[5] = true;
return true;
}
return false;
break;
case 91:
if (Teile[6] == false)
{
Teile[6] = true;
return true;
}
return false;
break;
case 143:
if (Teile[7] == false)
{
Teile[7] = true;
return true;
}
return false;
break;
case 15:
if (Teile[8] == false)
{
Teile[8] = true;
return true;
}
return false;
break;
case 35:
if (Teile[9] == false)
{
Teile[9] = true;
return true;
}
return false;
break;
case 77:
if (Teile[10] == false)
{
Teile[10] = true;
return true;
}
return false;
break;
case 33:
if (Teile[11] == false)
{
Teile[11] = true;
return true;
}
return false;
break;
case 30:
if (Teile[12] == false)
{
Teile[12] = true;
return true;
}
return false;
break;
case 70:
if (Teile[13] == false)
{
Teile[13] = true;
return true;
}
return false;
break;
case 154:
if (Teile[14] == false)
{
Teile[14] = true;
return true;
}
return false;
break;
case 66:
if (Teile[15] == false)
{
Teile[15] = true;
return true;
}
return false;
break;
case 195:
if (Teile[16] == false)
{
Teile[16] = true;
return true;
}
return false;
break;
case 455:
if (Teile[17] == false)
{
Teile[17] = true;
return true;
}
return false;
break;
case 1001:
if (Teile[18] == false)
{
Teile[18] = true;
return true;
}
return false;
break;
case 429:
if (Teile[19] == false)
{
Teile[19] = true;
return true;
}
return false;
break;
default:
return false;
}
}
bool uberprufer() {
// Array initialisieren
for (int i = 0; i < 20; i++)
{
Teile[i] = false;
}
if (!theswitch(Cube[0][0][0] * Cube[1][2][0] * Cube[4][2][2]))
{
return false;
}
if (!theswitch(Cube[0][0][2] * Cube[1][2][2] * Cube[2][2][0]))
{
return false;
}
if (!theswitch(Cube[0][2][2] * Cube[2][2][2] * Cube[3][2][0]))
{
return false;
}
if (!theswitch(Cube[0][2][0] * Cube[3][2][2] * Cube[4][2][0]))
{
return false;
}
if (!theswitch(Cube[5][2][0] * Cube[1][0][0] * Cube[4][0][2]))
{
return false;
}
if (!theswitch(Cube[5][2][2] * Cube[1][0][2] * Cube[2][0][0]))
{
return false;
}
if (!theswitch(Cube[5][0][2] * Cube[2][0][2] * Cube[3][0][0]))
{
return false;
}
if (!theswitch(Cube[5][0][0] * Cube[3][0][2] * Cube[4][0][0]))
{
return false;
}
if (!theswitch(Cube[0][0][1] * Cube[1][2][1]))
{
return false;
}
if (!theswitch(Cube[0][1][2] * Cube[2][2][1]))
{
return false;
}
if (!theswitch(Cube[0][2][1] * Cube[3][2][1]))
{
return false;
}
if (!theswitch(Cube[0][1][0] * Cube[4][2][1]))
{
return false;
}
if (!theswitch(Cube[5][0][1] * Cube[3][0][1]))
{
return false;
}
if (!theswitch(Cube[5][1][2] * Cube[2][0][1]))
{
return false;
}
if (!theswitch(Cube[5][2][1] * Cube[1][0][1]))
{
return false;
}
if (!theswitch(Cube[5][1][0] * Cube[4][0][1]))
{
return false;
}
if (!theswitch(Cube[1][1][2] * Cube[2][1][0]))
{
return false;
}
if (!theswitch(Cube[2][1][2] * Cube[3][1][0]))
{
return false;
}
if (!theswitch(Cube[3][1][2] * Cube[4][1][0]))
{
return false;
}
if (!theswitch(Cube[4][1][2] * Cube[1][1][0]))
{
return false;
}
// Zuerst Ecksteine Pruefen und dann Mittelsteine
// Danach Mittelsteine ueberpruefen
return true;
}
int Seitenflachenanordungsalgorythmus()
{
for (int t = 0; t < 6; t++)
{
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
switch (Cube[t][i][j]) {
case 0:
Cube[t][i][j] = 2;
break;
case 1:
Cube[t][i][j] = 3;
break;
case 2:
Cube[t][i][j] = 5;
break;
case 3:
Cube[t][i][j] = 7;
break;
case 4:
Cube[t][i][j] = 11;
break;
case 5:
Cube[t][i][j] = 13;
break;
}
}
}
}
for (int a = 0; a < 4; a++)
{
for (int b = 0; b < 4; b++)
{
for (int c = 0; c < 4; c++)
{
for (int d = 0; d < 4; d++)
{
for (int e = 0; e < 4; e++)
{
for (int f = 0; f < 4; f++)
{
if (uberprufer()) {
goto endloop;
}
Seitendreher(0);
}
Seitendreher(1);
}
Seitendreher(2);
}
Seitendreher(3);
}
Seitendreher(4);
}
Seitendreher(5);
}
Serial.println("Es gibt keine eine Loesung");
Fehlermeldungeingabe();
goto sprung;
endloop:
Serial.println("Es gibt eine Loesung");
sprung:
for (int t = 0; t < 6; t++)
{
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
switch (Cube[t][i][j]) {
case 2:
Cube[t][i][j] = 0;
break;
case 3:
Cube[t][i][j] = 1;
break;
case 5:
Cube[t][i][j] = 2;
break;
case 7:
Cube[t][i][j] = 3;
break;
case 11:
Cube[t][i][j] = 4;
break;
case 13:
Cube[t][i][j] = 5;
break;
}
}
}
}
for (int t = 0; t < 6; t++)
{
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
Serial.print(Cube[t][i][j]);
}
Serial.println(" ");
}
Serial.println("\n");
}
return 0;
}
// Program fur Seitenflaechenanordungsalgorythmus sind nun fertig
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
// Start des Programmes Rubiccubesolver
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------
// Spezielle Figuren welche fur die Gelben flaechen gebraucht werden
int Fischvariante1[3][3] = { {0,5,0},{5,5,5},{5,5,0} };
int Fischvariante2[3][3] = { {0,5,0},{5,5,5},{0,5,5} };
int Plus[3][3] = { {0,5,0},{5,5,5},{0,5,0} };
int Acht[3][3] = { {5,5,0},{5,5,5},{0,5,5} };
int Raumschiffgeradelaser[3][3] = { {5,5,5},{5,5,5},{0,5,0} };
int Raumschiffseitenlaser[3][3] = { {0,5,5},{5,5,5},{0,5,5} };
int rotationszeiger = 0;
char personalmoves[500];
int movesarrayzeiger = 0;
// Um immer genau zu wissen auf welcher seite wir uns befinden, braucht man einen rotationszeiger
// Dieser rotationszeiger beginnt bei 0 (normalsicht) und jede drehung nach rechts laesst die Zahl um eins steigen
void Rotation(){
rotationszeiger += 1;
if (rotationszeiger==4)
{
rotationszeiger = 0;
}
return;
}
// Wir wollen nicht, dass die Leute jedesmal den Cube umdrehen, sondern, dass sie immer die gleiche Seite anschauen koennen, da es Profis selbst auch so machen wuerden
void Rotationsprofil1(char move){
switch (move)
{
case 'R':
personalmoves[movesarrayzeiger] = 'B';
movesarrayzeiger += 1;
break;
case 'r':
personalmoves[movesarrayzeiger] = 'b';
movesarrayzeiger += 1;
break;
case 'F':
personalmoves[movesarrayzeiger] = 'R';
movesarrayzeiger += 1;
break;
case 'f':
personalmoves[movesarrayzeiger] = 'r';
movesarrayzeiger += 1;
break;
case 'B':
personalmoves[movesarrayzeiger] = 'L';
movesarrayzeiger += 1;
break;
case 'b':
personalmoves[movesarrayzeiger] = 'l';
movesarrayzeiger += 1;
break;
case 'L':
personalmoves[movesarrayzeiger] = 'F';
movesarrayzeiger += 1;
break;
case 'l':
personalmoves[movesarrayzeiger] = 'f';
movesarrayzeiger += 1;
break;
}
}
void Rotationsprofil2(char move){
switch (move)
{
case 'R':
personalmoves[movesarrayzeiger] = 'L';
movesarrayzeiger += 1;
break;
case 'r':
personalmoves[movesarrayzeiger] = 'l';
movesarrayzeiger += 1;
break;
case 'F':
personalmoves[movesarrayzeiger] = 'B';
movesarrayzeiger += 1;
break;
case 'f':
personalmoves[movesarrayzeiger] = 'b';
movesarrayzeiger += 1;
break;
case 'B':
personalmoves[movesarrayzeiger] = 'F';
movesarrayzeiger += 1;
break;
case 'b':
personalmoves[movesarrayzeiger] = 'f';
movesarrayzeiger += 1;
break;
case 'L':
personalmoves[movesarrayzeiger] = 'R';
movesarrayzeiger += 1;
break;
case 'l':
personalmoves[movesarrayzeiger] = 'r';
movesarrayzeiger += 1;
break;
}
}
void Rotationsprofil3(char move){
switch (move)
{
case 'R':
personalmoves[movesarrayzeiger] = 'F';
movesarrayzeiger += 1;
break;
case 'r':
personalmoves[movesarrayzeiger] = 'f';
movesarrayzeiger += 1;
break;
case 'F':
personalmoves[movesarrayzeiger] = 'L';
movesarrayzeiger += 1;
break;
case 'f':
personalmoves[movesarrayzeiger] = 'l';
movesarrayzeiger += 1;
break;
case 'B':
personalmoves[movesarrayzeiger] = 'R';
movesarrayzeiger += 1;
break;
case 'b':
personalmoves[movesarrayzeiger] = 'r';
movesarrayzeiger += 1;
break;
case 'L':
personalmoves[movesarrayzeiger] = 'B';
movesarrayzeiger += 1;
break;
case 'l':
personalmoves[movesarrayzeiger] = 'b';
movesarrayzeiger += 1;
break;
}
}
void Personalmovesmain(char input){
if (input == 'M')
{
return;
}
if(input == 'U'|| input == 'u'|| input == 'D'|| input == 'd')
{
personalmoves[movesarrayzeiger] = input;
movesarrayzeiger += 1;
return;
}
if (rotationszeiger == 0)
{
personalmoves[movesarrayzeiger] = input;
movesarrayzeiger += 1;
}
if (rotationszeiger == 1)
{
Rotationsprofil1(input);
return;
}
if (rotationszeiger == 2)
{
Rotationsprofil2(input);
return;
}
if (rotationszeiger == 3)
{
Rotationsprofil3(input);
return;
}
return;
}
// Die Verschiedenen Überpruefkonstanten, um zu schauen, ob ein Zwischenziel erreicht wurde
bool uberpruferkreuz() {
// Weisseskreuz
if (0 == Cube[0][1][1] && Cube[0][0][1] == 0 && Cube[0][2][1] == 0 && Cube[0][1][0] == 0 && Cube[0][1][2] == 0)
{
//Farben werden ueberprueft
if (Cube[1][1][1] == Cube[1][2][1] && Cube[2][1][1] == Cube[2][2][1] && Cube[3][1][1] == Cube[3][2][1] && Cube[4][1][1] == Cube[4][2][1])
{
return true;
}
}
return false;
}
bool uberpruferfirstlayer() {
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
if (Cube[0][i][j] != 0)
{
return false;
}
}
}
for (int i = 1; i < 5; i++)
{
if (Cube[i][2][0] != Cube[i][1][1] || Cube[i][2][2] != Cube[i][1][1] || Cube[i][1][1] != Cube[i][2][1])
{
return false;
}
}
return true;
}
bool uberprufertwolayer() {
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
if (Cube[0][i][j] != 0)
{
return false;
}
}
}
for (int i = 1; i < 5; i++)
{
if (Cube[i][2][0] != Cube[i][1][1] || Cube[i][2][2] != Cube[i][1][1] || Cube[i][1][1] != Cube[i][2][1])
{
return false;
}
if (Cube[i][1][0] != Cube[i][1][1] || Cube[i][1][2] != Cube[i][1][1])
{
return false;
}
}
return true;
}
bool uberprufergelbeflache() {
if (uberprufertwolayer() == false)
{
return false;
}
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
if (Cube[5][i][j] != 5)
{
return false;
}
}
}
return true;
}
bool uberpruferfinishcube() {
for (int t = 0; t < 6; t++)
{
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
if (Cube[t][i][j] != Cube[t][1][1])
{
return false;
}
}
}
}
return true;
}
void Rechts() {
// Wuerfel Kopieren
int zwischenspeicher[6][3][3];
for (int t = 0; t < 6; t++)
{
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
zwischenspeicher[t][i][j] = Cube[t][i][j];
}
}
}
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
Cube[4][i][j] = zwischenspeicher[1][i][j];
}
}
for (int t = 1; t < 4; t++)
{
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
Cube[t][i][j] = zwischenspeicher[t+1][i][j];
}
}
}
Cube[5][0][1] = zwischenspeicher[5][1][0];
Cube[5][1][0] = zwischenspeicher[5][2][1];
Cube[5][2][1] = zwischenspeicher[5][1][2];
Cube[5][1][2] = zwischenspeicher[5][0][1];
Cube[5][0][0] = zwischenspeicher[5][2][0];
Cube[5][0][2] = zwischenspeicher[5][0][0];
Cube[5][2][2] = zwischenspeicher[5][0][2];
Cube[5][2][0] = zwischenspeicher[5][2][2];
Cube[0][0][1] = zwischenspeicher[0][1][2];
Cube[0][1][0] = zwischenspeicher[0][0][1];
Cube[0][2][1] = zwischenspeicher[0][1][0];
Cube[0][1][2] = zwischenspeicher[0][2][1];
Cube[0][0][0] = zwischenspeicher[0][0][2];
Cube[0][0][2] = zwischenspeicher[0][2][2];
Cube[0][2][2] = zwischenspeicher[0][2][0];
Cube[0][2][0] = zwischenspeicher[0][0][0];
// um die Orientierung abzudatet wird die aenderung bei der Variabel erfasst
Rotation();
}
void Rechtsmove() {
// Wuerfel Kopieren
int zwischenspeicher[6][3][3];
for (int t = 0; t < 6; t++)
{
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
zwischenspeicher[t][i][j] = Cube[t][i][j];
}
}
}
Cube[1][0][2] = zwischenspeicher[0][0][2];
Cube[1][1][2] = zwischenspeicher[0][1][2];
Cube[1][2][2] = zwischenspeicher[0][2][2];
Cube[0][0][2] = zwischenspeicher[3][2][0];
Cube[0][1][2] = zwischenspeicher[3][1][0];
Cube[0][2][2] = zwischenspeicher[3][0][0];
Cube[3][0][0] = zwischenspeicher[5][2][2];
Cube[3][1][0] = zwischenspeicher[5][1][2];
Cube[3][2][0] = zwischenspeicher[5][0][2];
Cube[5][0][2] = zwischenspeicher[1][0][2];
Cube[5][1][2] = zwischenspeicher[1][1][2];
Cube[5][2][2] = zwischenspeicher[1][2][2];
Cube[2][0][0] = zwischenspeicher[2][2][0];
Cube[2][0][2] = zwischenspeicher[2][0][0];
Cube[2][2][2] = zwischenspeicher[2][0][2];
Cube[2][2][0] = zwischenspeicher[2][2][2];
Cube[2][0][1] = zwischenspeicher[2][1][0];
Cube[2][1][2] = zwischenspeicher[2][0][1];
Cube[2][2][1] = zwischenspeicher[2][1][2];
Cube[2][1][0] = zwischenspeicher[2][2][1];
}
void Rechtsmovereversed() {
Rechtsmove();
Rechtsmove();
Rechtsmove();
}
void Frontmove() {
Rechts();
Rechts();
Rechts();
Rechtsmove();
Rechts();
}
void Frontmovereversed() {
Rechts();
Rechts();
Rechts();
Rechtsmovereversed();
Rechts();
}
void backmove() {
Rechts();
Rechtsmove();
Rechts();
Rechts();
Rechts();
}
void backmovereversed() {
Rechts();
Rechtsmovereversed();
Rechts();
Rechts();
Rechts();
}
void Linksmove() {
Rechts();
Rechts();
Rechtsmove();
Rechts();
Rechts();
}
void Linksmovereversed() {
Rechts();
Rechts();
Rechtsmovereversed();
Rechts();
Rechts();
}
// Das ist U
void ObenmoveUhrzeiger() {
// Wuerfel Kopieren
int zwischenspeicher[6][3][3];
for (int t = 0; t < 6; t++)
{
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
zwischenspeicher[t][i][j] = Cube[t][i][j];
}
}
}
for (int j = 0; j < 3; j++)
{
Cube[4][0][j] = zwischenspeicher[1][0][j];
}
for (int t = 1; t < 4; t++)
{
for (int j = 0; j < 3; j++)
{
Cube[t][0][j] = zwischenspeicher[t + 1][0][j];
}
}
Cube[5][0][0] = zwischenspeicher[5][2][0];
Cube[5][0][2] = zwischenspeicher[5][0][0];
Cube[5][2][2] = zwischenspeicher[5][0][2];
Cube[5][2][0] = zwischenspeicher[5][2][2];
Cube[5][0][1] = zwischenspeicher[5][1][0];
Cube[5][1][2] = zwischenspeicher[5][0][1];
Cube[5][2][1] = zwischenspeicher[5][1][2];
Cube[5][1][0] = zwischenspeicher[5][2][1];
}
void ObenmoveGegenuhrzeiger() {
ObenmoveUhrzeiger();
ObenmoveUhrzeiger();
ObenmoveUhrzeiger();
}
void UntenUhrzeiger() {
// Wuerfel Kopieren
int zwischenspeicher[6][3][3];
for (int t = 0; t < 6; t++)
{
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
zwischenspeicher[t][i][j] = Cube[t][i][j];
}
}
}
for (int j = 0; j < 3; j++)
{
Cube[4][2][j] = zwischenspeicher[1][2][j];
}
for (int t = 1; t < 4; t++)
{
for (int j = 0; j < 3; j++)
{
Cube[t][2][j] = zwischenspeicher[t + 1][2][j];
}
}
Cube[0][0][0] = zwischenspeicher[0][0][2];
Cube[0][0][2] = zwischenspeicher[0][2][2];
Cube[0][2][2] = zwischenspeicher[0][2][0];
Cube[0][2][0] = zwischenspeicher[0][0][0];
Cube[0][0][1] = zwischenspeicher[0][1][2];
Cube[0][1][2] = zwischenspeicher[0][2][1];
Cube[0][2][1] = zwischenspeicher[0][1][0];
Cube[0][1][0] = zwischenspeicher[0][0][1];
}
// Das ist D
void UntenGegenuhrzeiger() {
UntenUhrzeiger();
UntenUhrzeiger();
UntenUhrzeiger();
}
void Moves(char Eingabe[]) {
delay(1);
for (int i = 0; i < 8; i++)
{
// Der Move wird gespeichert um ihn spaeter fuer die Display ausgabe zu gebrauchen
Personalmovesmain(Eingabe[i]);
switch (Eingabe[i])
{
case 'R':
Rechtsmove();
Serial.println("R");
break;
case 'r':
Rechtsmovereversed();
Serial.println("r");
break;
case 'F':
Frontmove();
Serial.println("F");
break;
case 'f':
Frontmovereversed();
Serial.println("f");
break;
case 'B':
backmove();
Serial.println("B");
break;
case 'b':
backmovereversed();
Serial.println("b");
break;
case 'L':
Linksmove();
Serial.println("L");
break;
case 'l':
Linksmovereversed();
Serial.println("l");
break;
case 'U':
ObenmoveUhrzeiger();
Serial.println("U");
break;
case 'u':
ObenmoveGegenuhrzeiger();
Serial.println("u");
break;
case 'D':
UntenGegenuhrzeiger();
Serial.println("D");
break;
case 'd':
UntenUhrzeiger();
Serial.println("d");
break;
}
}
}
void Weisseblume() {
while (Cube[5][0][1] != 0 || Cube[5][1][0] != 0 || Cube[5][1][2] != 0 || Cube[5][2][1] != 0)
{
if (Cube[0][0][1] == 0)
{
while (Cube[5][2][1] == 0)
{
char moves[] = "UMMMMMMM";
Moves(moves);
}
char moves[] = "FFMMMMMM";
Moves(moves);
}
if (Cube[1][1][0] == 0)
{
while (Cube[5][1][0] == 0)
{
char moves[] = "UMMMMMMM";
Moves(moves);
}
char moves[] = "lMMMMMMM";
Moves(moves);
}
if (Cube[1][1][2] == 0)
{
while (Cube[5][1][2] == 0)
{
char moves[] = "UMMMMMMM";
Moves(moves);
}
char moves[] = "RMMMMMMM";
Moves(moves);
}
if (Cube[1][0][1] == 0)
{
char moves[] = "FuRMMMMM";
Moves(moves);
}
if (Cube[1][2][1] == 0)
{
while (Cube[5][1][2] == 0)
{
char moves[] = "UMMMMMMM";
Moves(moves);
}
char moves[] = "frFRRMMM";
Moves(moves);
}
Rechts();
}
}
void Weisseskreuz() {
for (int i = 0; i < 4; i++)
{
while (Cube[5][2][1] != 0 || Cube[1][0][1] != Cube[1][1][1])
{
char moves[] = "UMMMMMMM";
Moves(moves);
}
char moves[] = "FFMMMMMM";
Moves(moves);
Rechts();
}
}
void Weisseecken() {
//
//Alle Weissen Ecken nach oben
for (int i = 0; i < 4; i++)
{
if (Cube[1][2][2]*Cube[0][0][2]*Cube[2][2][0] == 0)
{
while (Cube[1][0][2]*Cube[5][2][2]*Cube[2][0][0] == 0)
{
char moves[] = "UMMMMMMM";
Moves(moves);
}
char moves[] = "RUrMMMMM";
Moves(moves);
}
Rechts();
}
Serial.println("alle Weisen Seiten sind oben");
//return;
// Alle Richtig nach unten Drehen
while (!uberpruferfirstlayer())
{
for (int i = 0; i < 4; i++)
{
if (Cube[2][0][0] == 0)
{
if (Cube[1][0][2] * Cube[5][2][2] == Cube[1][1][1] * Cube[2][1][1])
{
char moves[] = "RUrMMMMM";
Moves(moves);
}
}
if (Cube[1][0][2] == 0)
{
if (Cube[5][2][2] * Cube[2][0][0] == Cube[1][1][1] * Cube[2][1][1])
{
char moves[] = "RUUruRUU";
Moves(moves);
char moves2[] = "ruRUrMMM";
Moves(moves2);
}
}
if (Cube[5][2][2] == 0)
{
if (Cube[1][0][2] * Cube[2][0][0] == Cube[1][1][1] * Cube[2][1][1])
{
char moves[] = "RUUruRUr";
Moves(moves);
}
}
Rechts();
}
char moves[] = "UMMMMMMM";
Moves(moves);
}
}
void Mittelsteine() {
//Alle Mittelsteine werden herausgenommen
for (int i = 0; i < 4; i++)
{
if (Cube[1][1][2] != 5 && Cube[2][1][0] != 5)
{
while (!(Cube[1][0][1] == 5 || Cube[5][2][1] == 5))
{
char moves[] = "UMMMMMMM";
Moves(moves);
}
char moves[] = "URurufUF";
Moves(moves);
}
Rechts();
}
while (!uberprufertwolayer())
{
for (int i = 0; i < 4; i++)
{
if (Cube[1][0][1] == Cube[1][1][1])
{
if (Cube[5][2][1] == Cube[2][1][1])
{
char moves[] = "URurufUF";
Moves(moves);
}
if (Cube[5][2][1] == Cube[4][1][1])
{
char moves[] = "ulULUFuf";
Moves(moves);
}
}
Rechts();
}
char moves[] = "UMMMMMMM";
Moves(moves);
}
}
// ueberpruefen
int Seitenuberprufer(int zuteste[3][3])
{
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
if (zuteste[i][j] == 5)
{
if (Cube[5][i][j] != 5)
{
return 1;
}
}
else
{
if (Cube[5][i][j] == 5)
{
return 1;
}
}
}
}
// Der Wert fuer true
return 0;
}
void Gelbeseite() {
//
while (!uberprufergelbeflache())
{
begin:
//Fisch
for (int i = 0; i < 4; i++)
{
if (Cube[1][0][0] == 5)
{
if (Seitenuberprufer(Fischvariante2) == 0)
{
char moves[] = "luLulUUL";
Moves(moves);
goto exit;
}
}
if (Cube[1][0][2] == 5)
{
if (Seitenuberprufer(Fischvariante1) == 0)
{
char moves[] = "RUrURUUr";
Moves(moves);
goto exit;
}
}
Rechts();
}
// Acht
for (int i = 0; i < 4; i++)
{
if (Cube[1][0][0] == 5)
{
if (Seitenuberprufer(Acht) == 0)
{
char moves[] = "RUrURUUr";
Moves(moves);
Rechts();
Rechts();
Rechts();
char moves1[] = "luLulUUL";
Moves(moves1);
goto exit;
}
}
Rechts();
}
// Plus
for (int i = 0; i < 4; i++)
{
if (Cube[1][0][2] == 5 && Cube[1][0][0] != 5)
{
if (Seitenuberprufer(Plus) == 0)
{
char moves[] = "RUrURUUr";
Moves(moves);
Rechts();
Rechts();
Rechts();
Moves(moves);
goto exit;
}
}
if (Cube[1][0][0] == 5 && Cube[1][0][2] == 5 && Cube[2][0][2] != 5)
{
if (Seitenuberprufer(Plus) == 0)
{
Rechts();
char moves[] = "RUrURUUr";
Moves(moves);
Moves(moves);
goto exit;
}
}
Rechts();
}
// Raumschiff
for (int i = 0; i < 4; i++)
{
if (Cube[1][0][0] == 5 && Cube[1][0][2] == 5)
{
if (Seitenuberprufer(Raumschiffgeradelaser) == 0)
{
char moves[] = "RUrURUUr";
Moves(moves);
Rechts();
Rechts();
char moves1[] = "luLulUUL";
Moves(moves1);
goto exit;
}
}
if (Cube[1][0][0] == 5 && Cube[1][0][2] != 5)
{
if (Seitenuberprufer(Raumschiffseitenlaser) == 0)
{
char moves[] = "RUrURUUr";
Moves(moves);
char moves3[] = "luLulUUL";
Moves(moves3);
goto exit;
}
}
Rechts();
}
// Balcken
if (Cube[5][1][0] == 5 && Cube[5][1][2] == 5)
{
char moves[] = "FRUrufMM";
Moves(moves);
goto begin;
}
if (Cube[5][0][1] == 5 && Cube[5][2][1] == 5)
{
char moves[] = "FRUrufMM";
Moves(moves);
goto begin;
}
// Punkt
for (int i = 0; i < 4; i++)
{
if (Cube[5][1][0] == 5 && Cube[5][0][1] == 5)
{
char moves[] = "FRUrufMM";
Moves(moves);
goto begin;
}
Rechts();
}
char moves[] = "FRUrufMM";
Moves(moves);
}
exit:
Serial.println("Testueberhaupt");
}
void lastlayer() {
// Zuerst die Ecksteine Orientieren
anfang:
for (int i = 0; i < 4; i++)
{
if (Cube[1][0][0] != Cube[1][0][2] && Cube[4][0][0] == Cube[4][0][2])
{
char moves[] = "RUrurFRR";
Moves(moves);
char moves2[] = "uruRUrfM";
Moves(moves2);
goto Mittelsteine;
}
Rechts();
}
for (int i = 0; i < 4; i++)
{
if (Cube[1][0][1] == Cube[1][0][2] && Cube[2][0][0] == Cube[2][0][1] && Cube[1][0][0] != Cube[1][0][1])
{
Rechts();
Rechts();
char moves[] = "RbRFFrBR";
Moves(moves);
char moves2[] = "FFRRMMMM";
Moves(moves2);
goto anfang;
}
Rechts();
}
if (Cube[1][0][0] != Cube[1][0][2] || Cube[2][0][0] != Cube[2][0][2])
{
char moves[] = "RbRFFrBR";
Moves(moves);
char moves2[] = "FFRRMMMM";
Moves(moves2);
goto anfang;
}
// Mittelsteine Orientieren
Mittelsteine:
if (Cube[1][0][0] != Cube[1][0][2] || Cube[2][0][0] != Cube[2][0][2])
{
Fehlermeldungcubesolve();
return;
}
if (uberpruferfinishcube())
{
return;
}
// Seitenorientierung, falls mann einfach mit einem Drehen, alles loesen kann
if (Cube[1][0][0] == Cube[1][0][2] && Cube[1][0][1] == Cube[1][0][0] && Cube[2][0][0] == Cube[2][0][2] && Cube[2][0][0] == Cube[2][0][1])
{
if (Cube[1][0][0] == Cube[2][1][1])
{
char moves[] = "uMMMMMMM";
Moves(moves);
return;
}
if (Cube[1][0][0] == Cube[4][1][1])
{
char moves[] = "UMMMMMMM";
Moves(moves);
return;
}
char moves[] = "UUMMMMMM";
Moves(moves);
return;
}
for (int i = 0; i < 4; i++)
{
if (Cube[1][0][0] == Cube[1][0][1])
{
if (Cube[2][0][0] == Cube[4][0][1])
{
char moves[] = "LuLULULu";
Moves(moves);
char moves2[] = "luLLMMMM";
Moves(moves2);
goto Mittelsteine;
}
if (Cube[4][0][0] == Cube[2][0][1])
{
char moves[] = "rUrururU";
Moves(moves);
char moves2[] = "RURRMMMM";
Moves(moves2);
goto Mittelsteine;
}
}
Rechts();
}
char moves[] = "rUrururU";
Moves(moves);
char moves2[] = "RURRMMMM";
Moves(moves2);
goto Mittelsteine;
}
// def Main wird ausgefuehrt, fuer Adruido wird
int RubicCubesolver()
{
Serial.println("Das Rechnen beginnt!!!");
Serial.println("Weisseblume beginnt");
Weisseblume();
Serial.println("Weissekreuz beginnt");
Weisseskreuz();
Serial.println("Weisseecken beginnt");
Weisseecken();
Serial.println("Mittelsteine beginnt");
Mittelsteine();
Serial.println("Gelbeseitee beginnt");
Gelbeseite();
Serial.println("Pll beginnt");
lastlayer();
if (uberpruferkreuz())
{
Serial.println("Kreuz Stimmt");
}
if (uberpruferfirstlayer())
{
Serial.println("erster Layer und Weisse Flache stimmt");
}
if (uberprufertwolayer())
{
Serial.println("zweiter Layer stimmt");
}
if (uberprufergelbeflache())
{
Serial.println("Gelbe flache stimmt");
}
if (uberpruferfinishcube())
{
Serial.println("Cube Stimmt vollkommen");
}
for (int t = 0; t < 6; t++)
{
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
Serial.print(Cube[t][i][j]);
}
Serial.println(" ");
}
}
}
// Das Rubikcubesolverprogram ist nun fertig
//--------------------------------------------------------------------------------------------------------------------------------------------------------------
// Um Die Anzahl Moves zu optimieren wird vor dem Ausgeben der Moves zuerst noch Optimieralgorythmen dazwischengeschalten
//------------------------------------------------------------------------------------------------------------------------
int arraylangevonverbessertenmoves;
int verbessertenmoves[500];
void loeschen(int anfang, int wieviel) {
for (int i = anfang; i < arraylangevonverbessertenmoves-wieviel; i++)
{
verbessertenmoves[i] = verbessertenmoves[i + wieviel];
}
arraylangevonverbessertenmoves = arraylangevonverbessertenmoves - wieviel;
}
void moveszuinteger() {
for (int i = 0; i < movesarrayzeiger; i++)
{
switch (personalmoves[i]) {
case 'R':
verbessertenmoves[i] = 0;
break;
case 'r':
verbessertenmoves[i] = 1;
break;
case 'L':
verbessertenmoves[i] = 2;
break;
case 'l':
verbessertenmoves[i] = 3;
break;
case 'F':
verbessertenmoves[i] = 4;
break;
case 'f':
verbessertenmoves[i] = 5;
break;
case 'B':
verbessertenmoves[i] = 6;
break;
case 'b':
verbessertenmoves[i] = 7;
break;
case 'U':
verbessertenmoves[i] = 8;
break;
case 'u':
verbessertenmoves[i] = 9;
break;
case 'D':
verbessertenmoves[i] = 10;
break;
case 'd':
verbessertenmoves[i] = 11;
break;
default:
verbessertenmoves[i] = 100;
break;
}
}
}
void integerzumoves() {
for (int i = 0; i < arraylangevonverbessertenmoves; i++)
{
if (verbessertenmoves[i] == 100) {
loeschen(i, 1);
}
}
for (int i = 0; i < arraylangevonverbessertenmoves; i++)
{
switch (verbessertenmoves[i]) {
case 0:
personalmoves[i] = 'R';
break;
case 1:
personalmoves[i] = 'r';
break;
case 2:
personalmoves[i] = 'L';
break;
case 3:
personalmoves[i] = 'l';
break;
case 4:
personalmoves[i] = 'F';
break;
case 5:
personalmoves[i] = 'f';
break;
case 6:
personalmoves[i] = 'B';
break;
case 7:
personalmoves[i] = 'b';
break;
case 8:
personalmoves[i] = 'U';
break;
case 9:
personalmoves[i] = 'u';
break;
case 10:
personalmoves[i] = 'D';
break;
case 11:
personalmoves[i] = 'd';
break;
}
}
movesarrayzeiger = arraylangevonverbessertenmoves;
}
void vierfachzahlen() {
for (int i = 0; i < arraylangevonverbessertenmoves-3; i++)
{
if (verbessertenmoves[i] == verbessertenmoves[i + 1] && verbessertenmoves[i] == verbessertenmoves[i + 2] && verbessertenmoves[i] == verbessertenmoves[i + 3])
{
loeschen(i, 4);
}
}
}
void dreifachzahlen() {
for (int i = 0; i < arraylangevonverbessertenmoves - 2; i++)
{
if (verbessertenmoves[i] == verbessertenmoves[i + 1] && verbessertenmoves[i] == verbessertenmoves[i + 2])
{
if (verbessertenmoves[i] % 2 == 0)
{
verbessertenmoves[i] = verbessertenmoves[i] + 1;
}
else if (verbessertenmoves[i] % 2 == 1)
{
verbessertenmoves[i] = verbessertenmoves[i] - 1;
}
loeschen(i+1, 2);
}
}
}
void moveandprimemove() {
for (int i = 0; i < arraylangevonverbessertenmoves - 1; i++)
{
if (verbessertenmoves[i] % 2 == 0)
{
if (verbessertenmoves[i + 1] == verbessertenmoves[i] + 1)
{
loeschen(i, 2);
}
}
if (verbessertenmoves[i] % 2 == 1)
{
if (verbessertenmoves[i + 1] == verbessertenmoves[i] - 1)
{
loeschen(i, 2);
}
}
}
}
void Movesverbesserungsmain()
{
arraylangevonverbessertenmoves = movesarrayzeiger;
Serial.println("Moveverbesserungsmain hat angefangen");
Serial.println(arraylangevonverbessertenmoves);
moveszuinteger();
for (int i = 0; i < 5; i++)
{
vierfachzahlen();
vierfachzahlen();
dreifachzahlen();
dreifachzahlen();
moveandprimemove();
}
integerzumoves();
Serial.println(arraylangevonverbessertenmoves);
Serial.println("Moveverbesserungsmain ist fertig");
}
// Effizienzsteigerung ist nun fertig
//-------------------------------------------------------------------------------------------------------------------------
// Nun kommt der letze Teil des Programmes, in dem das Loesen des Rubik Cube in Verbindung mit dem Display programmiert wird
void Movesanzeigenmain(){
Serial.println("Ich beginne mit Anzeigen");
lcd.setCursor(0,0);
lcd.print("Program ist fertig");
lcd.setCursor(0,1);
lcd.print("Pedal druecken!");
bool Pedalalt;
bool Pedalneu;
for(int i = 120; i < movesarrayzeiger; i++)
{
do {
Pedalalt = Pedalneu;
Pedalneu = digitalRead(12);
}
while (!(Pedalalt == HIGH && Pedalneu == LOW));
Pedalalt = Pedalneu;
lcd.clear();
Serial.print(i+1);
Serial.print(" : ");
Serial.print(personalmoves[i]);
Serial.println(" ");
lcd.setCursor(0, 1);
lcd.print(i + 1);
lcd.setCursor(0, 0);
lcd.print(personalmoves[i]);
delay(500);
}
do {
Pedalalt = Pedalneu;
Pedalneu = digitalRead(12);
}
while (!(Pedalalt == HIGH && Pedalneu == LOW));
finish:
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Cube Geloest");
delay(10000);
}
// Programm zum Darstellen mit dem Display ist nun fertig
//----------------------------------------------------------------------------------------------------------------
// Fehlermeldungen
//-------------------------------------------------------------------------------------------------------------------------------------------
// Da die Auszufuehrende Person auch Fehler machen kann oder im Program etwas schieflaufen koennte, braucht es Fehlermeldungen
void Fehlermeldungcubesolve()
{
Serial.println("Es gab ein Fehler beim Loesen des Cubes");
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("FEHLER");
lcd.setCursor(0, 1);
lcd.print("Cubeloesen");
delay(10000000000);
}
void Fehlermeldungeingabe()
{
Serial.println("Es gab ein Fehler beim Eintippen des Cubes");
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("FEHLER");
lcd.setCursor(0, 1);
lcd.print("Eingabe");
delay(10000000000);
}
// Fehlermeldungen sind fertig
//--------------------------------------------------------------------------------------------------------------------------------------------
void setup() {
Serial.begin(9600);
lcd.begin(16, 2);
pinMode(12,INPUT_PULLUP);
}
void loop() {
Einlesenmain();
if (uberpruferfinishcube())
{
Movesanzeigenmain();
goto finish;
}
Seitenflachenanordungsalgorythmus();
RubicCubesolver();
Movesverbesserungsmain();
Movesanzeigenmain();
finish:
// Alle Werte welche als Global initialisiert wurden, muessen wieder in ihren Anfangszustand gebraucht werden um das Program nochmals von vorne zu gebrauchen
for (int t = 0; t < 6; t++)
{
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
Cube[t][i][j] = 6;
}
}
}
arraylangevonverbessertenmoves = 0;
movesarrayzeiger = 0;
lcd.clear();
}