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();
      
    }