User:Tisane/Rubik's cube program

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title></title>
    </head>
    <body>
        <?php
                   $myHistory=new history; // Global function
                   $solvedCube=new cube; // Global function
        // Each face has 9 squares, arranged like this:
        // 1 2 3
        // 4 5 6
        // 7 8 9
        class square {
            private $color;
            // Return the color of this square
            public function displayColor() {
                return $this->color;
            }
            // Set the color of this square
            public function setColor($inputcolor) {
                $this->color=$inputcolor;
            }
        }

        // Each cube has 6 faces, arranged like this:
        // Face 1: Top
        // Face 2: Front
        // Face 3: Right side
        // Face 4: Back
        // Face 5: Left side
        // Face 6: Bottom
        class face {
            // Create 9 new squares
            function __construct() {
                for ($squareCount=1; $squareCount<=9; $squareCount++) {
                    $this->thisSquare[$squareCount]=new square;
                }
            }


            // Return the color of a square on this face
            public function displaySquare($whichSquare) {
                return $this->thisSquare[$whichSquare]->displayColor();
            }
            // Set the color of a square on this face
            public function setSquare($whichSquare,$whatValue) {
                $this->thisSquare[$whichSquare]->setColor($whatValue);
                return;
            }
        }

        class cube {
            private $thisMove;

            function __construct() {
                for ($faceCount=1; $faceCount<=6; $faceCount++) {
                    $this->thisFace[$faceCount]=new face;
                }
            }

            // Return the move associated with this cube
            public function displayMove()
            {
                return $this->thisMove;
            }

            public function setMove($whichMove){
                $this->thisMove=$whichMove;
            }

            // Return the color of a square on this cube
            public function displaySquare($whichFace,$whichSquare) {
                return $this->thisFace[$whichFace]->displaySquare($whichSquare);
            }

            // Set the color of a square on this cube
            public function setSquare($whichFace,$whichSquare,$whatValue) {
                $this->thisFace[$whichFace]->setSquare($whichSquare,$whatValue);
            }
            // Make this cube equal to another
            public function duplicateCube($whichCube) {
                for ($faceCount=1; $faceCount<=6; $faceCount++) {
                    for ($squareCount=1; $squareCount<=9; $squareCount++) {
                        $this->setSquare($faceCount,$squareCount,$whichCube->displaySquare($faceCount,$squareCount));


                    }
                }
            }
            // See if this cube is identical to another
            public function compareCube(cube $whichCube) {
                
                for ($faceCount=1; $faceCount<=6; $faceCount++) {
                    for ($squareCount=1; $squareCount<=9; $squareCount++) {
                        if ($this->displaySquare($faceCount,$squareCount)!=$whichCube->displaySquare($faceCount,$squareCount))
                            return false; // They are different
                    }
                }
                return true; // They are the same
            }
            // Rotate a row to the right
            public function rotateRight($whichRow) // $whichRow ranges from 1 to 3
            {
                $escrow=new cube;
                $escrow->duplicateCube($this);
                if ($whichRow!=2) { // If it's not the middle row
                    // Let's do the top or bottom of the cube
                    // As this face turns, each square ends up in a different place. For instance, the 7 moves to where the 1 is.
                    // $sub means substitute
                    for ($squareCount=1; $squareCount<=9; $squareCount++) {
                        switch ($squareCount) {
                            case 1:
                                $sub=7;
                                break;
                            case 2:
                                $sub=4;
                                break;
                            case 3:
                                $sub=1;
                                break;
                            case 4:
                                $sub=8;
                                break;
                            case 5:
                                $sub=5;
                                break;
                            case 6:
                                $sub=2;
                                break;
                            case 7:
                                $sub=9;
                                break;
                            case 8:
                                $sub=6;
                                break;
                            case 9:
                                $sub=3;
                                break;
                        }
                        switch ($whichRow) {
                            case 1:
                                $whichFaceToRotate=1; // The top
                                break;
                            case 3:
                                $whichFaceToRotate=6; // The bottom
                                break;
                        }
                        $escrow->setSquare($whichFaceToRotate,$squareCount,$this->displaySquare($whichFaceToRotate,$sub));

                    }

                }

                // Now the four faces (faces 2 through 5)
                for ($faceCount=2; $faceCount<=5; $faceCount++) {
                    for ($squareCount=$whichRow*3-2; $squareCount<=$whichRow*3; $squareCount++) // Each row has three squares
                    {
                        $fromFace=$faceCount+1; // Get color data from the face to the right
                        if ($fromFace==6) { // If we've circled all the way around, go back to face 2
                            $fromFace=2;
                        }
                        $escrow->setSquare($faceCount,$squareCount,$this->displaySquare($fromFace,$squareCount));
                    }
                }
                $this->duplicateCube($escrow);


            }


            // Rotate a column down
            public function rotateDown($whichColumn) // $whichColumn ranges from 1 to 3
            {
                $escrow=new cube;
                $escrow->duplicateCube($this);
                if ($whichColumn!=2) { // If it's not the middle row
                    // Let's do the left and right sides of the cube
                    for ($squareCount=1; $squareCount<=9; $squareCount++) {
                        switch ($squareCount) {
                            case 1:
                                $sub=7;
                                break;
                            case 2:
                                $sub=4;
                                break;
                            case 3:
                                $sub=1;
                                break;
                            case 4:
                                $sub=8;
                                break;
                            case 5:
                                $sub=5;
                                break;
                            case 6:
                                $sub=2;
                                break;
                            case 7:
                                $sub=9;
                                break;
                            case 8:
                                $sub=6;
                                break;
                            case 9:
                                $sub=3;
                                break;
                        }
                        switch ($whichColumn) {
                            case 1:
                                $whichFaceToRotate=5; // The left face
                                break;
                            case 3:
                                $whichFaceToRotate=3; // The right face
                                break;
                        }
                        $escrow->setSquare($whichFaceToRotate,$squareCount,$this->displaySquare($whichFaceToRotate,$sub));

                    }

                }

                // Now the four faces (faces 1, 4, 6, and 2 - i.e., top, back, bottom, and front
                $toFace=array(1 => 1,4,6,2);
                $fromFace=array(1 => 4,6,2,1);



                for ($faceCount=1; $faceCount<=4; $faceCount++) {
                    $substituteColumn=$whichColumn;
                    
                    for ($squareCount=$substituteColumn; $squareCount<=$substituteColumn+6; $squareCount+=3){
                        $fromSquare=$squareCount;
                        $toSquare=$squareCount;
                        
                        if ($toFace[$faceCount]==4){
                            if ($whichColumn==1)
                                $toSquare+=2;
                            if ($whichColumn==3)
                                $toSquare-=2;
                            
                                }
                                if ($toFace[$faceCount]==1 || $toFace[$faceCount]==4)
                            $fromSquare=10-$toSquare;
                    $escrow->setSquare($toFace[$faceCount],$toSquare,$this->displaySquare($fromFace[$faceCount],$fromSquare));
                    
                    }
                }

              //  for ($faceCount=1; $faceCount<=4; $faceCount++) {
                    // Every face but face 4 uses these instructions.
                //            if ($toFace[$faceCount]!=4) {
                                // We need to reverse these so they show up in the proper places.
                        //if ($whichColumn==1)
                          //       $substituteColumn=3;
                        //if ($whichColumn==3)
                          //      $substituteColumn=1;
                 //           $substituteColumn=$whichColumn;
               //     for ($squareCount=$substituteColumn; $squareCount<=$substituteColumn+6; $squareCount+=3) {
                        
                    //    if ($toFace[$faceCount]==1)
                      //  $substituteSquare=10-$squareCount;

                  //      $escrow->setSquare($toFace[$faceCount],$squareCount,$this->displaySquare($fromFace[$faceCount],$substituteSquare));
                       //           }
                 //   }
                 //        else {
                    // Face 4 uses these special instructions
                   //        $substituteColumn=$whichColumn;
                     //        for ($squareCount=$substituteColumn; $squareCount<=$substituteColumn+6; $squareCount+=3) {
                                 // We need to reverse these so they show up in the proper places.
                     //            $substituteSquare=$squareCount;
                       //          $substituteSquare=10-$squareCount;
                        // Square 1 is a special case.
                        

                   //     }
                            
                        //         $escrow->setSquare($toFace[$faceCount],$squareCount,$this->displaySquare($fromFace[$faceCount],$substituteSquare));
                     //      }
                       //   }
                

                $this->duplicateCube($escrow);
            }



            public function showMeTheCube() {
                print '<table><tr>';
                for ($faceCount=1; $faceCount<=6; $faceCount++) {
           //         print 'Face ';
           //         print $faceCount;
           //         print '<br />';
                    
                    

                    for ($squareCount=1; $squareCount<=9; $squareCount++) {
                        print '<td width="30">';
                       echo $this->displaySquare($faceCount,$squareCount);
                        print '</td>';
                 //       if ($squareCount%3==0)
          //                  print '<br />';
                    }
                    
               }
               print '</table>';
               //print '<br />';
             //   for ($faceCount=1; $faceCount<=6; $faceCount++) {
             //       print 'Face'.$faceCount;
                    
                    
               //                     }
            }

            // Make this cube perfectly solved
            public function createDefaultCube() {
                for ($faceCount=1; $faceCount<=6; $faceCount++) {
                    // Each color is associated with a letter. E.g., W is White.
                    for ($squareCount=1; $squareCount<=9; $squareCount++) {

                        switch ($faceCount) {
                            case 1:
                                $color='W';
                                break;
                            case 2:
                                $color='O';
                                break;
                            case 3:
                                $color='G';
                                break;
                            case 4:
                                $color='R';
                                break;
                            case 5:
                                $color='B';
                                break;
                            case 6:
                                $color='Y';
                                break;
                        }
                        // Add square numbers
                        $this->setSquare($faceCount,$squareCount,$color.$squareCount);

                    }
                }
                return;
            }


            public function solveCube(){
                global $solvedCube;
                global $myHistory;
                $solvedCube->createDefaultCube();
     
                //$solvedIt=$this->compareCube($solvedCube);
                //if ($solvedIt==false)
              
                    $this->anotherMove();
                    $myHistory->showMeTheHistory();


            }
            
            public function manipulateCube($whichMove){
                switch ($whichMove){
                    case 1:
                        $this->rotateRight(1);
                    
                    break;
                case 2:
                    $this->rotateRight(2);
                break;
                case 3:
                    $this->rotateRight(3);
                    break;
                case 4:
                    $this->rotateDown(1);
                break;
                case 5:
                    $this->rotateDown(2);
                break;
                case 6:
                    $this->rotateDown(3);
                break;
                }
            }
            public function anotherMove(){

                global $myHistory;
                global $solvedCube;
                $solvedIt=$this->compareCube($solvedCube); // Have we solved it?
             // $this->showMeTheCube();
              
                if ($solvedIt==true){
                  
                    return true; // We're done! Now let's get out of this recursion.
                }
                else
                    {
                    if ($myHistory->isItInTheHistory($this)==true)
                            return false; // We've been here before
                    
                    for ($count=1; $count<=6 && $solvedIt==false; $count++){
                        $this->manipulateCube($count); // Manipulate the cube
                       $this->showMeTheCube();
                    $myHistory->storeThisCube($this,$count); // Store the current cube and move info
                        
                        $solvedIt=$this->anotherMove(); // Now try manipulating the cube a different way
                        if ($solvedIt==false)
                            
                            $myHistory->eraseThisCube(); // Go back
                    }
                    if ($solvedIt==true)
                        return true; // Again, let's GTFO

                    else
                        return false; // We'll have to retrace our steps
                }
                }
            }
        
class history{
    private $historyNumber=0;
    private $highestWeHaveBeen=0;
    public function storeThisCube($whichCube,$whichMove)
    {
        
        $this->historyNumber++;
        if ($this->historyNumber>$this->highestWeHaveBeen)
            {
            $this->historyCube[$this->historyNumber]=new cube;
            $this->highestWeHaveBeen++;
            }
        $this->historyCube[$this->historyNumber]->duplicateCube($whichCube);
        $this->historyCube[$this->historyNumber]->setMove($whichMove);
    }

    public function eraseThisCube()
    {
        $this->historyNumber--;
    }

    public function isItInTheHistory($whichCube){
        for ($count=1; $count<$this->historyNumber; $count++){ // Notice the operator is <, not <=
            if ($this->historyCube[$count]->compareCube($whichCube)==true){
                return true;
            }
        }
        return false;
    }

    public function showMeTheHistory(){
        for ($count=1; $count<=$this->historyNumber; $count++){
            echo $this->historyCube[$count]->displayMove();
        }
    }
}



// Main program
        $myCube=  new cube();
        $myCube->createDefaultCube();
        //$myCube->showMeTheCube();
        $myCube->rotateDown(1);
 //       $myCube->rotateRight(1);
   //     $myCube->rotateRight(1);
        //$myCube->showMeTheCube();
        //$myCube->rotateDown(1);
        //$myCube->showMeTheCube();
        $myCube->solveCube();
        ?>
    </body>
</html>