User:Tisane/Rubik's cube program
| This program still doesn't work completely yet; see User:Tisane/Rubik's cube saga. |
<!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>
Content Disclaimer
Informasi ini disarikan dari Wikipedia dan disajikan kembali untuk tujuan edukasi. Konten tersedia di bawah lisensi CC BY-SA 3.0. Kami tidak bertanggung jawab atas ketidakakuratan data yang bersumber dari kontribusi publik tersebut.
- The information displayed on this website is sourced in part or in whole from Wikipedia and has been adapted for the purpose of restating it. We strive to provide accurate and relevant information, however:
- There is no guarantee of absolute accuracy. Wikipedia is an open, collaborative project that can be edited by anyone, so information is subject to change.
- It is not intended to constitute professional advice. The content displayed is for informational and educational purposes only. For important decisions (e.g., medical, legal, or financial), please consult a professional.
- Content copyright. Wikipedia is licensed under the Creative Commons Attribution-ShareAlike License (CC BY-SA). This means that content may be reused with appropriate attribution and shared under a similar license.
- Responsible use. Any risk arising from the use of information from this website is entirely the responsibility of the user.