Go back to Richel Bilderbeek's homepage.

Go back to Richel Bilderbeek's C++ page.

 

 

 

 

 

(C++) Rubik's Clock Simulator source code (version 1.0)

 

Rubik's Clock Simulator version 1.0 source code.

 

Operating system: Windows XP

IDE: C++ Builder 6.0 Enterprise Edition

Project type: GUI application

Compiler: supplied with C++ Builder 6.0 Enterprise Edition

Libraries used:

 

 

 

 

 

ProjectRubiksClock.cpp

 

//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop
//---------------------------------------------------------------------------
USEFORM("UnitFormRubiksClockMain.cpp", FormRubiksClockMain);
USEFORM("UnitFormRubiksClockAbout.cpp", FormRubiksClockAbout);
//---------------------------------------------------------------------------
WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
        try
        {
                 Application->Initialize();
                 Application->Title = "Rubik's Clock Simulator";
                 Application->CreateForm(__classid(TFormRubiksClockMain), &FormRubiksClockMain);
                 Application->Run();
        }
        catch (Exception &exception)
        {
                 Application->ShowException(&exception);
        }
        catch (...)
        {
                 try
                 {
                         throw Exception("");
                 }
                 catch (Exception &exception)
                 {
                         Application->ShowException(&exception);
                 }
        }
        return 0;
}
//---------------------------------------------------------------------------

 

 

 

 

 

UnitFormRubiksClockAbout.cpp

 

//---------------------------------------------------------------------------
/*
  Rubik's Clock Simulator. Simulates Rubik's Clock.
  Copyright (C) 2007  Richel Bilderbeek

  This program is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
//---------------------------------------------------------------------------
// From http://www.richelbilderbeek.nl
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop

#include "UnitFormRubiksClockAbout.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TFormRubiksClockAbout *FormRubiksClockAbout;
//---------------------------------------------------------------------------
__fastcall TFormRubiksClockAbout::TFormRubiksClockAbout(TComponent* Owner)
        : TForm(Owner)
{
}
//---------------------------------------------------------------------------

 

 

 

 

 

UnitFormRubiksClockAbout.h

 

//---------------------------------------------------------------------------
/*
  Rubik's Clock Simulator. Simulates Rubik's Clock.
  Copyright (C) 2007  Richel Bilderbeek

  This program is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
//---------------------------------------------------------------------------
// From http://www.richelbilderbeek.nl
//---------------------------------------------------------------------------
#ifndef UnitFormRubiksClockAboutH
#define UnitFormRubiksClockAboutH
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <ComCtrls.hpp>
#include <ExtCtrls.hpp>
#include <jpeg.hpp>
//---------------------------------------------------------------------------
class TFormRubiksClockAbout : public TForm
{
__published: // IDE-managed Components
        TRichEdit *RichEdit1;
        TPanel *Panel1;
        TImage *Image1;
        TPanel *Panel2;
        TLabel *Label1;
        TLabel *Label2;
        TLabel *Label3;
        TLabel *Label4;
        TLabel *Label5;
        TLabel *Label6;
        TLabel *Label7;
        TLabel *Label8;
        TLabel *Label9;
        TLabel *Label10;
        TLabel *Label11;
        TLabel *Label12;
private: // User declarations
public: // User declarations
        __fastcall TFormRubiksClockAbout(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TFormRubiksClockAbout *FormRubiksClockAbout;
//---------------------------------------------------------------------------
#endif

 

 

 

 

 

UnitFormRubiksClockMain.cpp

 

//---------------------------------------------------------------------------
/*
  Rubik's Clock Simulator. Simulates Rubik's Clock.
  Copyright (C) 2007  Richel Bilderbeek

  This program is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
//---------------------------------------------------------------------------
// From http://www.richelbilderbeek.nl
//---------------------------------------------------------------------------
#include <cmath>
#include <cassert>
#include <memory>
#include <vcl.h>
#pragma hdrstop

#include "UnitFormRubiksClockMain.h"
#include "UnitFormRubiksClockAbout.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TFormRubiksClockMain *FormRubiksClockMain;
//---------------------------------------------------------------------------
__fastcall TFormRubiksClockMain::TFormRubiksClockMain(TComponent* Owner)
        : TForm(Owner)
{
  OnResize(0);
}
//---------------------------------------------------------------------------
void __fastcall TFormRubiksClockMain::FormResize(TObject *Sender)
{
  ImageClockFront->Picture->Bitmap->Width  = ClientWidth / 2;
  ImageClockFront->Picture->Bitmap->Height = ClientHeight - Panel1->Height;
  ImageClockBack->Left = ImageClockFront->Picture->Bitmap->Width;
  ImageClockBack->Picture->Bitmap->Width  = ClientWidth - ImageClockFront->Picture->Bitmap->Width;
  ImageClockBack->Picture->Bitmap->Height = ClientHeight - Panel1->Height;
  DrawScreen();
}
//---------------------------------------------------------------------------
void TFormRubiksClockMain::DrawScreen()
{
  ImageClockFront->Visible = false;
  ImageClockBack->Visible = false;
  DrawRubiksClock(
    mClock.GetFrontTimes(),
    mClock.GetFrontPegs(),
    static_cast<TColor>(RGB(255,96,96)),
    static_cast<TColor>(RGB(255,64,64)),
    ImageClockFront);
  DrawRubiksClock(
    mClock.GetBackTimes(),
    mClock.GetBackPegs(),
    static_cast<TColor>(RGB(96,96,255)),
    static_cast<TColor>(RGB(64,64,255)),
    ImageClockBack);
  ImageClockFront->Visible = true;
  ImageClockBack->Visible = true;
}
//---------------------------------------------------------------------------
void DrawRubiksClock(
  const RubiksClockTimes& times,
  const RubiksClockPegs& pegs,
  const TColor colorCasing,
  const TColor colorClock,
  TImage * const image)
{

  const int maxx = image->Picture->Bitmap->Width;
  const int maxy = image->Picture->Bitmap->Height;
  PaintVcl(image,0,0,0);

  //Draw main clock ring
  image->Canvas->Pen->Color = clBlack;
  image->Canvas->Brush->Color = colorCasing;
  image->Canvas->Ellipse(0,0,maxx,maxy);

  //Draw the clocks and pegs
  {
    const double dX = static_cast<double>(maxx) / 3.0;
    const double dY = static_cast<double>(maxy) / 3.0;
    const double dXtenth = 0.1 * dX;
    const double dYtenth = 0.1 * dY;
    for (int y=0; y!=3; ++y)
    {
      for (int x=0; x!=3; ++x)
      {
        //Draw outer ring
        image->Canvas->Pen->Width = 1;
        image->Canvas->Brush->Color = colorCasing;
        image->Canvas->Pen->Color = colorClock;
        image->Canvas->Ellipse(
          static_cast<double>(x+0) * dX,
          static_cast<double>(y+0) * dY,
          static_cast<double>(x+1) * dX,
          static_cast<double>(y+1) * dY);
        //Draw clock ring
        image->Canvas->Brush->Color = colorClock;
        image->Canvas->Ellipse(
          static_cast<double>(x+0) * dX + dXtenth,
          static_cast<double>(y+0) * dY + dYtenth,
          static_cast<double>(x+1) * dX - dXtenth,
          static_cast<double>(y+1) * dY - dYtenth);
        //Draw time
        image->Canvas->Pen->Color = clBlack;
        image->Canvas->Pen->Width = 5;
        const double angle = (2.0 * M_PI)
          *(static_cast<double>(times.times[x][y]) / 12.0);
        image->Canvas->MoveTo(
          (static_cast<double>(x)+0.5) * dX,
          (static_cast<double>(y)+0.5) * dY );
        image->Canvas->LineTo(
          ( (static_cast<double>(x)+0.5) * dX) + (std::sin(angle) * ((0.5 * dX) - dXtenth) ),
          ( (static_cast<double>(y)+0.5) * dY) - (std::cos(angle) * ((0.5 * dY) - dYtenth) ) );
      }
    }
    image->Canvas->Pen->Width = 3;
    //Draw the pegs
    for (int y=0; y!=2; ++y)
    {
      for (int x=0; x!=2; ++x)
      {
        image->Canvas->Pen->Color = clBlack;
        image->Canvas->Brush->Color = clYellow;
        const int delta = (pegs.pegs[x][y] == false ? 10 : 1);
        for (int i=0; i!=delta; ++i)
        {
          image->Canvas->Ellipse(
            ( i + ((static_cast<double>(x)+1.0) * dX) + dXtenth),
            ( i + ((static_cast<double>(y)+1.0) * dY) + dYtenth),
            ( i + ((static_cast<double>(x)+1.0) * dX) - dXtenth),
            ( i + ((static_cast<double>(y)+1.0) * dY) - dYtenth) );

        }
      }
    }
  }

}
//---------------------------------------------------------------------------
//From http://www.richelbilderbeek.nl/CppPaint.htm
void PaintVcl(TImage * const image,
  const unsigned char red,
  const unsigned char green,
  const unsigned char blue  )
{
  assert(image!=0);
  assert(image->Picture->Bitmap != 0);
  assert(image->Picture->Bitmap->PixelFormat == pf24bit);

  const int maxx = image->Picture->Bitmap->Width;
  const int maxy = image->Picture->Bitmap->Height;
  for (int y = 0; y != maxy; ++y)
  {
    unsigned char * const myLine
      = static_cast<unsigned char*>(image->Picture->Bitmap->ScanLine[y]);
    for (int x = 0; x != maxx; ++x)
    {
      myLine[x*3+2] = red  ; //Red
      myLine[x*3+1] = green; //Green
      myLine[x*3+0] = blue ; //Blue
    }
  }
}
//---------------------------------------------------------------------------


void __fastcall TFormRubiksClockMain::ImageClockFrontMouseDown(TObject *Sender,
      TMouseButton Button, TShiftState Shift, int X, int Y)
{
  const int maxx = ImageClockFront->Picture->Bitmap->Width;
  const int maxy = ImageClockFront->Picture->Bitmap->Height;
  if ( X < maxx / 6 && Y < maxy / 6)
  {
    if (Button == mbLeft)
    {
      mClock.TurnWheel(topLeft,1);
    }
    else if (Button == mbRight)
    {
      mClock.TurnWheel(topLeft,11);
    }
  }
  else if ( X > 5 * (maxx / 6) && Y < maxy / 6)
  {
    if (Button == mbLeft)
    {
      mClock.TurnWheel(topRight,1);
    }
    else if (Button == mbRight)
    {
      mClock.TurnWheel(topRight,11);
    }
  }
  else if ( X < maxx / 6 && Y > 5 * (maxy / 6) )
  {
    //Wheel bottom left
    if (Button == mbLeft)
    {
      mClock.TurnWheel(bottomLeft,1);
    }
    else if (Button == mbRight)
    {
      mClock.TurnWheel(bottomLeft,11);
    }
  }
  else if ( X > 5 * (maxx / 6) && Y > 5 * (maxy / 6) )
  {
    //Wheel bottom right
    if (Button == mbLeft)
    {
      mClock.TurnWheel(bottomRight,1);
    }
    else if (Button == mbRight)
    {
      mClock.TurnWheel(bottomRight,11);
    }
  }
  else if ( X > (maxx / 3) - (maxx / 10)
    && X < (maxx / 3) + (maxx / 10)
    && Y > (maxy / 3) - (maxy / 10)
    && Y < (maxy / 3) + (maxy / 10) )
  {
    mClock.ChangePeg(topLeft, !mClock.GetFrontPegs().pegs[0][0]);
  }
  else if ( X > (2 *(maxx / 3)) - (maxx / 10)
    && X < (2 * (maxx / 3)) + (maxx / 10)
    && Y > (maxy / 3) - (maxy / 10)
    && Y < (maxy / 3) + (maxy / 10) )
  {
    mClock.ChangePeg(topRight, !mClock.GetFrontPegs().pegs[1][0]);
  }
  else if ( X > (maxx / 3) - (maxx / 10)
    && X < (maxx / 3) + (maxx / 10)
    && Y > (2 * (maxy / 3)) - (maxy / 10)
    && Y < (2 * (maxy / 3)) + (maxy / 10) )
  {
    mClock.ChangePeg(bottomLeft, !mClock.GetFrontPegs().pegs[0][1]);
  }
  else if ( X > (2 * (maxx / 3)) - (maxx / 10)
    && X < (2 * (maxx / 3)) + (maxx / 10)
    && Y > (2 * (maxy / 3)) - (maxy / 10)
    && Y < (2 * (maxy / 3)) + (maxy / 10) )
  {
    mClock.ChangePeg(bottomRight, !mClock.GetFrontPegs().pegs[1][1]);
  }

  DrawScreen();

}
//---------------------------------------------------------------------------
void __fastcall TFormRubiksClockMain::ImageClockBackMouseDown(
      TObject *Sender, TMouseButton Button, TShiftState Shift, int X,
      int Y)
{
  const int maxx = ImageClockFront->Picture->Bitmap->Width;
  const int maxy = ImageClockFront->Picture->Bitmap->Height;
  if ( X < maxx / 6 && Y < maxy / 6)
  {
    if (Button == mbLeft)
    {
      mClock.TurnWheel(topRight,11);
    }
    else if (Button == mbRight)
    {
      mClock.TurnWheel(topRight,1);
    }
  }
  else if ( X > 5 * (maxx / 6) && Y < maxy / 6)
  {
    if (Button == mbLeft)
    {
      mClock.TurnWheel(topLeft,11);
    }
    else if (Button == mbRight)
    {
      mClock.TurnWheel(topLeft,1);
    }
  }
  else if ( X < maxx / 6 && Y > 5 * (maxy / 6) )
  {
    //Wheel bottom left
    if (Button == mbLeft)
    {
      mClock.TurnWheel(bottomRight,11);
    }
    else if (Button == mbRight)
    {
      mClock.TurnWheel(bottomRight,1);
    }
  }
  else if ( X > 5 * (maxx / 6) && Y > 5 * (maxy / 6) )
  {
    //Wheel bottom right
    if (Button == mbLeft)
    {
      mClock.TurnWheel(bottomLeft,11);
    }
    else if (Button == mbRight)
    {
      mClock.TurnWheel(bottomLeft,1);
    }
  }
  else if ( X > (maxx / 3) - (maxx / 10)
    && X < (maxx / 3) + (maxx / 10)
    && Y > (maxy / 3) - (maxy / 10)
    && Y < (maxy / 3) + (maxy / 10) )
  {
    mClock.ChangePeg(topRight, !mClock.GetFrontPegs().pegs[1][0]);
  }
  else if ( X > (2 *(maxx / 3)) - (maxx / 10)
    && X < (2 * (maxx / 3)) + (maxx / 10)
    && Y > (maxy / 3) - (maxy / 10)
    && Y < (maxy / 3) + (maxy / 10) )
  {
    mClock.ChangePeg(topLeft, !mClock.GetFrontPegs().pegs[0][0]);
  }
  else if ( X > (maxx / 3) - (maxx / 10)
    && X < (maxx / 3) + (maxx / 10)
    && Y > (2 * (maxy / 3)) - (maxy / 10)
    && Y < (2 * (maxy / 3)) + (maxy / 10) )
  {
    mClock.ChangePeg(bottomRight, !mClock.GetFrontPegs().pegs[1][1]);
  }
  else if ( X > (2 * (maxx / 3)) - (maxx / 10)
    && X < (2 * (maxx / 3)) + (maxx / 10)
    && Y > (2 * (maxy / 3)) - (maxy / 10)
    && Y < (2 * (maxy / 3)) + (maxy / 10) )
  {
    mClock.ChangePeg(bottomLeft, !mClock.GetFrontPegs().pegs[0][1]);
  }

  DrawScreen();
}
//---------------------------------------------------------------------------


void __fastcall TFormRubiksClockMain::ButtonAboutClick(TObject *Sender)
{
  std::auto_ptr<TFormRubiksClockAbout> f(new TFormRubiksClockAbout(0));
  f->ShowModal();        
}
//---------------------------------------------------------------------------
void __fastcall TFormRubiksClockMain::ButtonShuffleClick(TObject *Sender)
{
  for (int i=0; i!=10000; ++i)
  {
    //Set a random peg
    mClock.ChangePeg(
      static_cast<RubiksClockSide>(std::rand() >> 4% 4),
      ((std::rand() >> 4) % 2 == 0 ? true : false) );
    //Turn a random wheel
    mClock.TurnWheel(
      static_cast<RubiksClockSide>(std::rand() >> 4 % 4),
      std::rand() % 12);
  }
  DrawScreen();
}
//---------------------------------------------------------------------------


 

 

 

 

 

UnitFormRubiksClockMain.h

 

//---------------------------------------------------------------------------
/*
  Rubik's Clock Simulator. Simulates Rubik's Clock.
  Copyright (C) 2007  Richel Bilderbeek

  This program is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
//---------------------------------------------------------------------------
// From http://www.richelbilderbeek.nl
//---------------------------------------------------------------------------
#ifndef UnitFormRubiksClockMainH
#define UnitFormRubiksClockMainH
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <ExtCtrls.hpp>
#include <Graphics.hpp>
//---------------------------------------------------------------------------
#include "UnitRubiksClock.h"
//---------------------------------------------------------------------------
class TFormRubiksClockMain : public TForm
{
__published: // IDE-managed Components
        TImage *ImageClockFront;
        TImage *ImageClockBack;
        TPanel *Panel1;
        TButton *ButtonAbout;
        TButton *ButtonShuffle;
        void __fastcall FormResize(TObject *Sender);
        void __fastcall ImageClockFrontMouseDown(TObject *Sender,
          TMouseButton Button, TShiftState Shift, int X, int Y);
        void __fastcall ImageClockBackMouseDown(TObject *Sender,
          TMouseButton Button, TShiftState Shift, int X, int Y);
        void __fastcall ButtonAboutClick(TObject *Sender);
        void __fastcall ButtonShuffleClick(TObject *Sender);
private: // User declarations
  RubiksClock mClock;
  void DrawScreen();
public: // User declarations
        __fastcall TFormRubiksClockMain(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TFormRubiksClockMain *FormRubiksClockMain;
//---------------------------------------------------------------------------
void DrawRubiksClock(
  const RubiksClockTimes& times,
  const RubiksClockPegs& pegs,
  const TColor colorCasing,
  const TColor colorClock,
  TImage * const image);

void PaintVcl(TImage * const image,
  const unsigned char red,
  const unsigned char green,
  const unsigned char blue  );

#endif

 

 

 

 

 

UnitRubiksClock.cpp

 

//---------------------------------------------------------------------------
/*
  Rubik's Clock Simulator. Simulates Rubik's Clock.
  Copyright (C) 2007  Richel Bilderbeek

  This program is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
//---------------------------------------------------------------------------
// From http://www.richelbilderbeek.nl
//---------------------------------------------------------------------------
#include <cassert>

#pragma hdrstop

#include "UnitRubiksClock.h"

//---------------------------------------------------------------------------
RubiksClockTimes::RubiksClockTimes()
{
  for (int y=0; y!=3; ++y)
  {
    for (int x=0; x!=3; ++x)
    {
      times[x][y] = 0;
    }
  }
}
//---------------------------------------------------------------------------
bool operator==(const RubiksClockTimes& lhs, const RubiksClockTimes& rhs)
{
  for (int y=0; y!=3; ++y)
  {
    for (int x=0; x!=3; ++x)
    {
      if (lhs.times[x][y] != rhs.times[x][y]) return false;
    }
  }
  return true;
}
//---------------------------------------------------------------------------
RubiksClockPegs::RubiksClockPegs()
{
  for (int y=0; y!=2; ++y)
  {
    for (int x=0; x!=2; ++x)
    {
      pegs[x][y] = 0;
    }
  }
}
//---------------------------------------------------------------------------
bool operator==(const RubiksClockPegs& lhs, const RubiksClockPegs& rhs)
{
  for (int y=0; y!=2; ++y)
  {
    for (int x=0; x!=2; ++x)
    {
      if (lhs.pegs[x][y] != rhs.pegs[x][y]) return false;
    }
  }
  return true;
}
//---------------------------------------------------------------------------
RubiksClockPegs CreatePegsFromIndex(const int index)
{
  //Index 0: (p = pressed, u = unpressed)
  // u u
  // u u
  //Index 1: (p = pressed, u = unpressed)
  // p u
  // u u
  //Index 2: (p = pressed, u = unpressed)
  // u p
  // u u
  //Index 3: (p = pressed, u = unpressed)
  // p p
  // u u
  //Index 4: (p = pressed, u = unpressed)
  // u u
  // p u
  //Index 5: (p = pressed, u = unpressed)
  // p u
  // p u
  //Index 6: (p = pressed, u = unpressed)
  // u p
  // p u
  //Index 7: (p = pressed, u = unpressed)
  // p p
  // p u
  //Index 8: (p = pressed, u = unpressed)
  // u u
  // u p
  //Index 9: (p = pressed, u = unpressed)
  // p u
  // u p
  //Index 10: (p = pressed, u = unpressed)
  // u p
  // u p
  //Index 11: (p = pressed, u = unpressed)
  // p p
  // u p
  //Index 12: (p = pressed, u = unpressed)
  // u u
  // p p
  //Index 13: (p = pressed, u = unpressed)
  // p u
  // p p
  //Index 14: (p = pressed, u = unpressed)
  // u p
  // p p
  //Index 15: (p = pressed, u = unpressed)
  // p p
  // p p

  RubiksClockPegs pegs;
  pegs.pegs[0][0] = ( index &amp; 1 == 1 ? true : false);
  pegs.pegs[1][0] = ( index &amp; 2 == 2 ? true : false);
  pegs.pegs[0][1] = ( index &amp; 4 == 4 ? true : false);
  pegs.pegs[1][1] = ( index &amp; 8 == 8 ? true : false);
  return pegs;


}
//---------------------------------------------------------------------------
RubiksClock::RubiksClock()
{
  Check();
}
//---------------------------------------------------------------------------
void RubiksClock::ChangePeg(const RubiksClockSide side, const bool press)
{
  const int x = (side == topLeft || side == bottomLeft ? 0 : 1);
  const int y = (side == topLeft || side == topRight ? 0 : 1);
  mPegs.pegs[x][y] = press;
}
//---------------------------------------------------------------------------
void RubiksClock::TurnWheel(const RubiksClockSide side, const int nSteps)
{
  switch (side)
  {
    case topLeft: TurnWheelTopLeft(nSteps); break;
    case topRight: TurnWheelTopRight(nSteps); break;
    case bottomLeft: TurnWheelBottomLeft(nSteps); break;
    case bottomRight: TurnWheelBottomRight(nSteps); break;
  }
}
//---------------------------------------------------------------------------
void RubiksClock::TurnWheelTopLeft(const int nSteps)
{
  bool turnFront[3][3];
  bool turnBack[3][3];

  turnFront[0][0] = true;
  turnFront[1][0] = (mPegs.pegs[0][0] == false ? true: false);
  turnFront[2][0] = (mPegs.pegs[0][0] == mPegs.pegs[1][0] ? true: false);
  turnFront[0][1] = (mPegs.pegs[0][0] == false ? true: false);
  turnFront[1][1] = (mPegs.pegs[0][0] == false ? true: false);
  turnFront[2][1] = (
    mPegs.pegs[0][0] == false
    && (  mPegs.pegs[1][0] == false
       || mPegs.pegs[1][1] == false )
    ? true: false);
  turnFront[0][2] = (mPegs.pegs[0][0] == mPegs.pegs[0][1] ? true : false);
  turnFront[1][2] = (
    mPegs.pegs[0][0] == false
    && (  mPegs.pegs[0][1] == false
       || mPegs.pegs[1][1] == false )
    ? true: false);
  turnFront[2][2] = (mPegs.pegs[0][0] == mPegs.pegs[1][1] ? true : false);

  turnBack[0][0] = (mPegs.pegs[0][0] == mPegs.pegs[1][0] ? true: false);
  turnBack[1][0] = (mPegs.pegs[0][0] == true ? true: false);
  turnBack[2][0] = true;

  turnBack[0][1] = (
    mPegs.pegs[0][0] == true
    && (    mPegs.pegs[1][0] == true
       ||   mPegs.pegs[1][1] == true )
    ? true: false);
  turnBack[1][1] = (mPegs.pegs[0][0] == true ? true: false);
  turnBack[2][1] = (mPegs.pegs[0][0] == true ? true: false);

  turnBack[0][2] = (mPegs.pegs[0][0] == mPegs.pegs[1][1] ? true: false);
  turnBack[1][2] = (
    mPegs.pegs[0][0] == true
    && (  mPegs.pegs[0][1] == true
       || mPegs.pegs[1][1] == true )
    ? true: false);
  turnBack[2][2] = (mPegs.pegs[0][0] == mPegs.pegs[0][1] ? true: false);

  for (int y=0; y!=3; ++y)
  {
    for (int x=0; x!=3; ++x)
    {
      if (turnFront[x][y] == true) { mFront.times[x][y] += nSteps     ; mFront.times[x][y]%=12; }
      if (turnBack[x][y]  == true) { mBack.times[x][y]  += (12-nSteps); mBack.times[x][y] %=12; }
    }
  }

}
//---------------------------------------------------------------------------
void RubiksClock::TurnWheelTopRight(const int nSteps)
{
  bool turnFront[3][3];
  bool turnBack[3][3];

  turnFront[2][0] = true;
  turnFront[1][0] = (mPegs.pegs[1][0] == false ? true: false);
  turnFront[0][0] = (mPegs.pegs[0][0] == mPegs.pegs[1][0] ? true: false);
  turnFront[2][1] = (mPegs.pegs[1][0] == false ? true: false);
  turnFront[1][1] = (mPegs.pegs[1][0] == false ? true: false);
  turnFront[0][1] = (
    mPegs.pegs[1][0] == false
    && (  mPegs.pegs[0][0] == false
       || mPegs.pegs[0][1] == false )
    ? true: false);
  turnFront[2][2] = (mPegs.pegs[1][0] == mPegs.pegs[1][1] ? true : false);
  turnFront[1][2] = (
    mPegs.pegs[1][0] == false
    && (  mPegs.pegs[1][1] == false
       || mPegs.pegs[0][1] == false )
    ? true: false);
  turnFront[0][2] = (mPegs.pegs[1][0] == mPegs.pegs[0][1] ? true : false);

  turnBack[2][0] = (mPegs.pegs[1][0] == mPegs.pegs[0][0] ? true: false);
  turnBack[1][0] = (mPegs.pegs[1][0] == true ? true: false);
  turnBack[0][0] = true;

  turnBack[2][1] = (
    mPegs.pegs[1][0] == true
    && (    mPegs.pegs[0][0] == true
       ||   mPegs.pegs[0][1] == true )
    ? true: false);
  turnBack[1][1] = (mPegs.pegs[1][0] == true ? true: false);
  turnBack[0][1] = (mPegs.pegs[1][0] == true ? true: false);

  turnBack[2][2] = (mPegs.pegs[1][0] == mPegs.pegs[0][1] ? true: false);
  turnBack[1][2] = (
    mPegs.pegs[1][0] == true
    && (  mPegs.pegs[1][1] == true
       || mPegs.pegs[0][1] == true )
    ? true: false);
  turnBack[0][2] = (mPegs.pegs[1][0] == mPegs.pegs[1][1] ? true: false);

  for (int y=0; y!=3; ++y)
  {
    for (int x=0; x!=3; ++x)
    {
      if (turnFront[x][y] == true) { mFront.times[x][y] += nSteps     ; mFront.times[x][y]%=12; }
      if (turnBack[x][y]  == true) { mBack.times[x][y]  += (12-nSteps); mBack.times[x][y] %=12; }
    }
  }
}
//---------------------------------------------------------------------------
void RubiksClock::TurnWheelBottomLeft(const int nSteps)
{
  bool turnFront[3][3];
  bool turnBack[3][3];

  turnFront[0][2] = true;
  turnFront[1][2] = (mPegs.pegs[0][1] == false ? true: false);
  turnFront[2][2] = (mPegs.pegs[0][1] == mPegs.pegs[1][1] ? true: false);
  turnFront[0][1] = (mPegs.pegs[0][1] == false ? true: false);
  turnFront[1][1] = (mPegs.pegs[0][1] == false ? true: false);
  turnFront[2][1] = (
    mPegs.pegs[0][1] == false
    && (  mPegs.pegs[1][1] == false
       || mPegs.pegs[1][0] == false )
    ? true: false);
  turnFront[0][0] = (mPegs.pegs[0][1] == mPegs.pegs[0][0] ? true : false);
  turnFront[1][0] = (
    mPegs.pegs[0][1] == false
    && (  mPegs.pegs[0][0] == false
       || mPegs.pegs[1][0] == false )
    ? true: false);
  turnFront[2][0] = (mPegs.pegs[0][1] == mPegs.pegs[1][0] ? true : false);

  turnBack[0][2] = (mPegs.pegs[0][1] == mPegs.pegs[1][1] ? true: false);
  turnBack[1][2] = (mPegs.pegs[0][1] == true ? true: false);
  turnBack[2][2] = true;

  turnBack[0][1] = (
    mPegs.pegs[0][1] == true
    && (    mPegs.pegs[1][1] == true
       ||   mPegs.pegs[1][0] == true )
    ? true: false);
  turnBack[1][1] = (mPegs.pegs[0][1] == true ? true: false);
  turnBack[2][1] = (mPegs.pegs[0][1] == true ? true: false);

  turnBack[0][0] = (mPegs.pegs[0][1] == mPegs.pegs[1][0] ? true: false);
  turnBack[1][0] = (
    mPegs.pegs[0][1] == true
    && (  mPegs.pegs[0][0] == true
       || mPegs.pegs[1][0] == true )
    ? true: false);
  turnBack[2][0] = (mPegs.pegs[0][1] == mPegs.pegs[0][0] ? true: false);

  for (int y=0; y!=3; ++y)
  {
    for (int x=0; x!=3; ++x)
    {
      if (turnFront[x][y] == true) { mFront.times[x][y] += nSteps     ; mFront.times[x][y]%=12; }
      if (turnBack[x][y]  == true) { mBack.times[x][y]  += (12-nSteps); mBack.times[x][y] %=12; }
    }
  }
}
//---------------------------------------------------------------------------
void RubiksClock::TurnWheelBottomRight(const int nSteps)
{


  bool turnFront[3][3];
  bool turnBack[3][3];

  turnFront[2][2] = true;
  turnFront[1][2] = (mPegs.pegs[1][1] == false ? true: false);
  turnFront[0][2] = (mPegs.pegs[0][1] == mPegs.pegs[1][1] ? true: false);
  turnFront[2][1] = (mPegs.pegs[1][1] == false ? true: false);
  turnFront[1][1] = (mPegs.pegs[1][1] == false ? true: false);
  turnFront[0][1] = (
    mPegs.pegs[1][1] == false
    && (  mPegs.pegs[0][1] == false
       || mPegs.pegs[0][0] == false )
    ? true: false);
  turnFront[2][0] = (mPegs.pegs[1][1] == mPegs.pegs[1][0] ? true : false);
  turnFront[1][0] = (
    mPegs.pegs[1][1] == false
    && (  mPegs.pegs[1][0] == false
       || mPegs.pegs[0][0] == false )
    ? true: false);
  turnFront[0][0] = (mPegs.pegs[1][1] == mPegs.pegs[0][0] ? true : false);

  turnBack[2][2] = (mPegs.pegs[1][1] == mPegs.pegs[0][1] ? true: false);
  turnBack[1][2] = (mPegs.pegs[1][1] == true ? true: false);
  turnBack[0][2] = true;

  turnBack[2][1] = (
    mPegs.pegs[1][1] == true
    && (    mPegs.pegs[0][1] == true
       ||   mPegs.pegs[0][0] == true )
    ? true: false);
  turnBack[1][1] = (mPegs.pegs[1][1] == true ? true: false);
  turnBack[0][1] = (mPegs.pegs[1][1] == true ? true: false);

  turnBack[2][0] = (mPegs.pegs[1][1] == mPegs.pegs[0][0] ? true: false);
  turnBack[1][0] = (
    mPegs.pegs[1][1] == true
    && (  mPegs.pegs[1][0] == true
       || mPegs.pegs[0][0] == true )
    ? true: false);
  turnBack[0][0] = (mPegs.pegs[1][1] == mPegs.pegs[1][0] ? true: false);

  for (int y=0; y!=3; ++y)
  {
    for (int x=0; x!=3; ++x)
    {
      if (turnFront[x][y] == true) { mFront.times[x][y] += nSteps     ; mFront.times[x][y]%=12; }
      if (turnBack[x][y]  == true) { mBack.times[x][y]  += (12-nSteps); mBack.times[x][y] %=12; }
    }
  }




}
//---------------------------------------------------------------------------
const RubiksClockTimes& RubiksClock::GetFrontTimes() const
{
  return mFront;
}
//---------------------------------------------------------------------------
const RubiksClockTimes& RubiksClock::GetBackTimes() const
{
  return mBack;
}
//---------------------------------------------------------------------------
const RubiksClockPegs& RubiksClock::GetFrontPegs() const
{
  return mPegs;
}
//---------------------------------------------------------------------------
const RubiksClockPegs RubiksClock::GetBackPegs() const
{
  RubiksClockPegs back;
  back.pegs[0][0] = !mPegs.pegs[1][0];
  back.pegs[1][0] = !mPegs.pegs[0][0];
  back.pegs[0][1] = !mPegs.pegs[1][1];
  back.pegs[1][1] = !mPegs.pegs[0][1];
  return back;
}
//---------------------------------------------------------------------------
void RubiksClock::Check()
{
  #ifndef NDEBUG
  const RubiksClockTimes originalFront = mFront;
  const RubiksClockTimes originalBack = mBack;
  const RubiksClockPegs originalPegs = mPegs;

  //Check the corner clocks
  assert( mFront.times[0][0] + mBack.times[2][0] == 0 || mFront.times[0][0] + mBack.times[2][0] == 12);
  assert( mFront.times[2][0] + mBack.times[0][0] == 0 || mFront.times[2][0] + mBack.times[0][0] == 12);
  assert( mFront.times[0][2] + mBack.times[2][2] == 0 || mFront.times[0][2] + mBack.times[2][2] == 12);
  assert( mFront.times[2][2] + mBack.times[0][2] == 0 || mFront.times[2][2] + mBack.times[0][2] == 12);
  //Check all peg combinations
  for (int i=0; i!=16; ++i)
  {
    mPegs = CreatePegsFromIndex(i);
    //Check all wheels
    for (int j=0; j!=4; ++j)
    {
      //Check if after turning around in two steps, everything stays the same
      const RubiksClockTimes front = mFront;
      const RubiksClockTimes back = mBack;

      const RubiksClockSide side = static_cast<RubiksClockSide>(j);
      const int nSteps = std::rand() % 12;
      //Turn 1
      this->TurnWheel(side,nSteps);
      //Turn 11
      this->TurnWheel(side,12-nSteps);
      assert( mFront == front);
      assert( mBack == back);
    }
  }

  #endif
}
//---------------------------------------------------------------------------



#pragma package(smart_init)

 

 

 

 

 

UnitRubiksClock.h

 

//---------------------------------------------------------------------------
/*
  Rubik's Clock Simulator. Simulates Rubik's Clock.
  Copyright (C) 2007  Richel Bilderbeek

  This program is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
//---------------------------------------------------------------------------
// From http://www.richelbilderbeek.nl
//---------------------------------------------------------------------------
#ifndef UnitRubiksClockH
#define UnitRubiksClockH
//---------------------------------------------------------------------------
#include <vector>
//---------------------------------------------------------------------------
struct RubiksClockTimes
{
  RubiksClockTimes();
  int times[3][3];
};

bool operator==(const RubiksClockTimes& lhs, const RubiksClockTimes& rhs);

struct RubiksClockPegs
{
  RubiksClockPegs();
  bool pegs[2][2]; //Is peg pressed?
};

bool operator==(const RubiksClockPegs& lhs, const RubiksClockPegs& rhs);

RubiksClockPegs CreatePegsFromIndex(const int index);

enum RubiksClockSide
{
  topLeft, topRight, bottomLeft, bottomRight
};


struct RubiksClock
{
  RubiksClock();

  void ChangePeg(const RubiksClockSide side, const bool press); //Seen from front
  void TurnWheel(const RubiksClockSide side, const int nSteps); //Seen from front
  void TurnWheelTopLeft(const int nSteps); //Seen from front
  void TurnWheelTopRight(const int nSteps); //Seen from front
  void TurnWheelBottomLeft(const int nSteps); //Seen from front
  void TurnWheelBottomRight(const int nSteps); //Seen from front

  void Check();

  const RubiksClockTimes& GetFrontTimes() const;
  const RubiksClockTimes& GetBackTimes() const;
  const RubiksClockPegs& GetFrontPegs() const;
  const RubiksClockPegs GetBackPegs() const;

  private:
  RubiksClockTimes mFront;
  RubiksClockTimes mBack;
  RubiksClockPegs mPegs;
};


#endif

 

 

 

 

 

 

 

 

 

 

Go back to Richel Bilderbeek's C++ page.

Go back to Richel Bilderbeek's homepage.

 

Valid XHTML 1.0 Strict