Go back to Richel Bilderbeek's homepage.

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

 

 

 

 

 

(C++) RefrigeratorPuzzleSolverVcl

 

Technical facts

 

 

 

 

 

 

./ToolRefrigeratorPuzzleSolverVcl/ProjectSolvePuzzle.cpp

 

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

#include <vcl.h>
#pragma hdrstop
//---------------------------------------------------------------------------
USEFORM("UnitFormSolvePuzzle.cpp", FormSolvePuzzle);
USEFORM("UnitFormAbout.cpp", FormAbout);
//---------------------------------------------------------------------------
WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
  try
  {
     Application->Initialize();
     Application->Title = "The Refrigerator Puzzle Solver";
     Application->CreateForm(__classid(TFormSolvePuzzle), &FormSolvePuzzle);
                 Application->Run();
  }
  catch (Exception &exception)
  {
     Application->ShowException(&exception);
  }
  catch (...)
  {
     try
     {
       throw Exception("");
     }
     catch (Exception &exception)
     {
       Application->ShowException(&exception);
     }
  }
  return 0;
}
//---------------------------------------------------------------------------

 

 

 

 

 

./ToolRefrigeratorPuzzleSolverVcl/UnitFormAbout.h

 

//---------------------------------------------------------------------------
/*
  The Refrigerator Puzzle Solver, program to solve a refrigerator puzzle
  Copyright (C) 2008  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 UnitFormAboutH
#define UnitFormAboutH
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <ComCtrls.hpp>
#include <ExtCtrls.hpp>
#include <jpeg.hpp>
#include <Grids.hpp>
#include <ValEdit.hpp>
//---------------------------------------------------------------------------
class TFormAbout : public TForm
{
__published: // IDE-managed Components
        TImage *ImagePuzzle;
        TPanel *PanelTop;
        TRichEdit *RichEditLicence;
        TPanel *PanelTopRight;
        TPanel *PanelLicence;
        TPanel *PanelTitle;
        TPanel *PanelCopyright;
        TPanel *PanelDate;
        TPanel *PanelAuthor;
        TPanel *PanelUrl;
        TValueListEditor *ValueListEditor1;
private: // User declarations
public: // User declarations
        __fastcall TFormAbout(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TFormAbout *FormAbout;
//---------------------------------------------------------------------------
#endif

 

 

 

 

 

./ToolRefrigeratorPuzzleSolverVcl/UnitFormAbout.cpp

 

//---------------------------------------------------------------------------
/*
  The Refrigerator Puzzle Solver, program to solve a refrigerator puzzle
  Copyright (C) 2008  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 "UnitFormAbout.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TFormAbout *FormAbout;
//---------------------------------------------------------------------------
__fastcall TFormAbout::TFormAbout(TComponent* Owner)
        : TForm(Owner)
{
}
//---------------------------------------------------------------------------

 

 

 

 

 

./ToolRefrigeratorPuzzleSolverVcl/UnitFormSolvePuzzle.h

 

//---------------------------------------------------------------------------
/*
  The Refrigerator Puzzle Solver, program to solve a refrigerator puzzle
  Copyright (C) 2008  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 UnitFormSolvePuzzleH
#define UnitFormSolvePuzzleH
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <ComCtrls.hpp>
#include <Grids.hpp>
//---------------------------------------------------------------------------
#include <vector>
#include "UnitPuzzlePiece.h"
//---------------------------------------------------------------------------
class TFormSolvePuzzle : public TForm
{
__published: // IDE-managed Components
        TProgressBar *ProgressBar;
  TButton *ButtonQuit;
  TStringGrid *StringGrid;
  TCheckBox *CheckBoxDisplay;
        TButton *ButtonSolve;
        TButton *ButtonAbout;
  void __fastcall ButtonQuitClick(TObject *Sender);
  void __fastcall ButtonSolveClick(TObject *Sender);
        void __fastcall ButtonAboutClick(TObject *Sender);
private: // User declarations
  bool mQuit;
  void ShowSolution(const std::vector<PuzzlePiece>& v);
  const std::vector<PuzzlePiece> SolvePuzzle(
    const std::vector<PuzzlePiece>& piecesUsed,
    const std::vector<PuzzlePiece>& piecesLeft);
public: // User declarations
  __fastcall TFormSolvePuzzle(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TFormSolvePuzzle *FormSolvePuzzle;
//---------------------------------------------------------------------------
const int IntPower(const int base, const int exponent);
const int Factorial(const int n);
//---------------------------------------------------------------------------
#endif

 

 

 

 

 

./ToolRefrigeratorPuzzleSolverVcl/UnitFormSolvePuzzle.cpp

 

//---------------------------------------------------------------------------
/*
  The Refrigerator Puzzle Solver, program to solve a refrigerator puzzle
  Copyright (C) 2008  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 <cmath>
#include <cassert>
#include <vector>
#include <string>
#include <algorithm>
#include <boost/scoped_ptr.hpp>
#include "UnitPuzzlePiece.h"

#include "UnitFormSolvePuzzle.h"
#include "UnitFormAbout.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TFormSolvePuzzle *FormSolvePuzzle;
//---------------------------------------------------------------------------
__fastcall TFormSolvePuzzle::TFormSolvePuzzle(TComponent* Owner)
  : TForm(Owner), mQuit(false)
{
  //Tests
  assert(IntPower(2,2)== 4);
  assert(IntPower(2,3)== 8);
  assert(IntPower(2,4)==16);
  assert(IntPower(3,2)== 9);
  assert(IntPower(3,3)==27);
  assert(IntPower(3,4)==81);
  //More tests
  PuzzlePiece p0(
    greenBeetleHead,
    greenBeetleTail,
    brownBeetleHead,
    brownBeetleTail);
  PuzzlePiece p1 = p0;
  assert(p0 == p1);
  p1.Rotate();
  assert(p0 != p1);
  PuzzlePiece p2 = p1;
  assert(p1 == p2);
  p2.Rotate();
  assert(p1 != p2);
  PuzzlePiece p3 = p2;
  assert(p2 == p3);
  p3.Rotate();
  assert(p2 != p3);
  PuzzlePiece p4 = p3;
  assert(p3 == p4);
  p4.Rotate();
  assert(p3 != p4);
  assert(p0 == p4);
}
//---------------------------------------------------------------------------
const int IntPower(const int base, const int exponent)
{
  assert(exponent >= 0);
  int result = 1;
  for (int i=0; i!=exponent; ++i)
  {
    result *= base;
  }
  return result;
}
//---------------------------------------------------------------------------
const int Factorial(const int n)
{
  assert(n>=0);
  int result = 1;
  for (int i=1; i<=n; ++i)
  {
    result*=i;
  }
  return result;
}
//---------------------------------------------------------------------------
void __fastcall TFormSolvePuzzle::ButtonQuitClick(TObject *Sender)
{
  mQuit = true;
  Close();
}
//---------------------------------------------------------------------------
void TFormSolvePuzzle::ShowSolution(const std::vector<PuzzlePiece>& v)
{
  const int n = static_cast<int>(v.size());
  for (int i=0; i!=n; ++i)
  {
    const int x = (i % 3) * 3;
    const int y = (i / 3) * 3;
    StringGrid->Cells[x+1][y  ] = ToStr(v[i].mTop).c_str();
    StringGrid->Cells[x+2][y+1] = ToStr(v[i].mRight).c_str();
    StringGrid->Cells[x+1][y+2] = ToStr(v[i].mBottom).c_str();
    StringGrid->Cells[x  ][y+1] = ToStr(v[i].mLeft).c_str();
  }
  for (int i=n; i!=9; ++i)
  {
    const int x = (i % 3) * 3;
    const int y = (i / 3) * 3;
    StringGrid->Cells[x+1][y  ] = "";
    StringGrid->Cells[x+2][y+1] = "";
    StringGrid->Cells[x+1][y+2] = "";
    StringGrid->Cells[x  ][y+1] = "";
  }
}
//---------------------------------------------------------------------------
void __fastcall TFormSolvePuzzle::ButtonSolveClick(TObject *Sender)
{
  const std::vector<PuzzlePiece> piecesOriginal = GetPieces();
  std::vector<PuzzlePiece> pieces1d = piecesOriginal;
  std::sort(pieces1d.begin(),pieces1d.end());

  ProgressBar->Max = IntPower(4,9);
  ProgressBar->Hint = ProgressBar->Max;

  const int maxI = IntPower(4,9);
  for (int i = 1; i!=maxI; ++i)
  {
    const std::vector<PuzzlePiece> solution = SolvePuzzle(std::vector<PuzzlePiece>(),pieces1d);
    if (solution.empty() == false)
    {
      ShowSolution(solution);
      ShowMessage("Solved!");
      return;
    }

    Application->ProcessMessages();
    if (mQuit == true) return;
    ProgressBar->Position = i;

    //Rotate a piece or more pieces
    for (int index = 0; index != 9; ++index)
    {
      pieces1d[index].Rotate();
      if (pieces1d[index].mNrotations != 0) break;
    }
  }

  ShowMessage("Not solved...");
}
//---------------------------------------------------------------------------
const std::vector<PuzzlePiece> TFormSolvePuzzle::SolvePuzzle(
  const std::vector<PuzzlePiece>& piecesUsed,
  const std::vector<PuzzlePiece>& piecesLeft)
{
  if (CheckBoxDisplay->Checked == true)
  {
    ShowSolution(piecesUsed);
    Application->ProcessMessages();
    this->Refresh();
    Sleep(100);
  }
  if (piecesLeft.empty() == true) return piecesUsed;
  assert(piecesUsed.size() + piecesLeft.size() == 9);
  const int nUsed = static_cast<int>(piecesUsed.size());
  const int nLeft = static_cast<int>(piecesLeft.size());
  const int newIndex = nUsed;
  for (int i=0; i!=nLeft; ++i)
  {
    //Check if the newcomer will fit
    if (newIndex > 2
      && DoesFit(piecesUsed[newIndex-3].mBottom,piecesLeft[i].mTop)==false)
    {
      continue;
    }
    if (newIndex % 3 != 0
      && DoesFit(piecesUsed[newIndex-1].mRight,piecesLeft[i].mLeft)==false)
    {
      continue;
    }
    //Newcomer fits!
    std::vector<PuzzlePiece> newPiecesUsed = piecesUsed;
    std::vector<PuzzlePiece> newPiecesLeft = piecesLeft;
    newPiecesUsed.push_back(newPiecesLeft[i]);
    std::swap(newPiecesLeft[i],newPiecesLeft.back());
    newPiecesLeft.pop_back();
    const std::vector<PuzzlePiece> solution = SolvePuzzle(newPiecesUsed,newPiecesLeft);
    if (solution.empty() == false) return solution;
  }
  return std::vector<PuzzlePiece>();
}
//---------------------------------------------------------------------------
void __fastcall TFormSolvePuzzle::ButtonAboutClick(TObject *Sender)
{
  boost::scoped_ptr<TFormAbout> f(new TFormAbout(0));
  f->ShowModal();
}
//---------------------------------------------------------------------------

 

 

 

 

 

./ToolRefrigeratorPuzzleSolverVcl/UnitPuzzlePiece.h

 

//---------------------------------------------------------------------------
/*
  The Refrigerator Puzzle Solver, program to solve a refrigerator puzzle
  Copyright (C) 2008  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 UnitPuzzlePieceH
#define UnitPuzzlePieceH
//---------------------------------------------------------------------------
#include <vector>
//---------------------------------------------------------------------------
enum EnumPicture
{
  greenBeetleHead,
  greenBeetleTail,
  brownBeetleHead,
  brownBeetleTail,
  wormShort,
  wormLong,
  hairyWormHead,
  hairyWormTail
};
//---------------------------------------------------------------------------
const std::string ToStr(const EnumPicture p);
//---------------------------------------------------------------------------
struct PuzzlePiece
{
  PuzzlePiece(
    const EnumPicture top,
    const EnumPicture right,
    const EnumPicture bottom,
    const EnumPicture left);
  EnumPicture mLeft;
  EnumPicture mRight;
  EnumPicture mTop;
  EnumPicture mBottom;
  void Rotate();
  int mNrotations;
  private:
  int mValue;
  friend const bool operator<(const PuzzlePiece& p1, const PuzzlePiece& p2);
  friend const bool operator!=(const PuzzlePiece& p1, const PuzzlePiece& p2);
  friend const bool operator==(const PuzzlePiece& p1, const PuzzlePiece& p2);

};
//---------------------------------------------------------------------------
const bool operator<(const PuzzlePiece& p1, const PuzzlePiece& p2);
const bool operator!=(const PuzzlePiece& p1, const PuzzlePiece& p2);
const bool operator==(const PuzzlePiece& p1, const PuzzlePiece& p2);
//---------------------------------------------------------------------------
const bool DoesFit(const EnumPicture a, const EnumPicture b);
//---------------------------------------------------------------------------
// Y-X ordered vector
const bool DoesFit(const std::vector<std::vector<PuzzlePiece> >& v);
const bool DoesFit(const std::vector<PuzzlePiece>& v);
//---------------------------------------------------------------------------
const std::vector<PuzzlePiece> GetPieces();
//---------------------------------------------------------------------------
const int ConvertToInt(const PuzzlePiece& p);
//---------------------------------------------------------------------------

#endif

 

 

 

 

 

./ToolRefrigeratorPuzzleSolverVcl/UnitPuzzlePiece.cpp

 

//---------------------------------------------------------------------------
/*
  The Refrigerator Puzzle Solver, program to solve a refrigerator puzzle
  Copyright (C) 2008  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
//---------------------------------------------------------------------------
#pragma hdrstop
//---------------------------------------------------------------------------
#include <cassert>
#include <stdexcept>
#include <string>
#include "UnitPuzzlePiece.h"

//---------------------------------------------------------------------------
const std::string ToStr(const EnumPicture p)
{
  switch (p)
  {
    case greenBeetleHead: return "GH";
    case greenBeetleTail: return "GT";
    case brownBeetleHead: return "BH";
    case brownBeetleTail: return "BT";
    case wormShort:       return "WS";
    case wormLong:        return "WL";
    case hairyWormHead:   return "HH";
    case hairyWormTail:   return "HT";
  }
  assert(!"Should not get here");
  throw std::logic_error("Unkown picture in function ToStr");
}
//---------------------------------------------------------------------------
PuzzlePiece::PuzzlePiece(
  const EnumPicture top,
  const EnumPicture right,
  const EnumPicture bottom,
  const EnumPicture left)
: mTop(top),
  mRight(right),
  mBottom(bottom),
  mLeft(left),
  mValue(ConvertToInt(*this)),
  mNrotations(0)

{

}
//---------------------------------------------------------------------------
void PuzzlePiece::Rotate()
{
  const EnumPicture oldTop = mTop;
  mTop = mRight;
  mRight = mBottom;
  mBottom = mLeft;
  mLeft = oldTop;
  mValue = ConvertToInt(*this);
  mNrotations = (mNrotations + 1) % 4;
}
//---------------------------------------------------------------------------
const bool DoesFit(const EnumPicture a, const EnumPicture b)
{
  switch (a)
  {
    case greenBeetleHead: return (b == greenBeetleTail);
    case greenBeetleTail: return (b == greenBeetleHead);
    case brownBeetleHead: return (b == brownBeetleTail);
    case brownBeetleTail: return (b == brownBeetleHead);
    case wormShort: return (b == wormLong);
    case wormLong: return (b == wormShort);
    case hairyWormHead: return (b == hairyWormTail);
    case hairyWormTail: return (b == hairyWormHead);
  }
  assert(!"Should not get here");
  throw std::logic_error("Unkown picture in function DoesFit");
}
//---------------------------------------------------------------------------
// Y-X ordered vector
const bool DoesFit(const std::vector<std::vector<PuzzlePiece> >& v)
{
  assert(v.size() == 3);
  assert(v[0].size() == 3);
  return (
       DoesFit(v[0][0].mBottom,v[1][0].mTop)
    && DoesFit(v[1][0].mBottom,v[2][0].mTop)
    && DoesFit(v[0][1].mBottom,v[1][1].mTop)
    && DoesFit(v[1][1].mBottom,v[2][1].mTop)
    && DoesFit(v[0][2].mBottom,v[1][2].mTop)
    && DoesFit(v[1][2].mBottom,v[2][2].mTop)
    && DoesFit(v[0][0].mRight ,v[0][1].mLeft)
    && DoesFit(v[0][1].mRight ,v[0][2].mLeft)
    && DoesFit(v[1][0].mRight ,v[1][1].mLeft)
    && DoesFit(v[1][1].mRight ,v[1][2].mLeft)
    && DoesFit(v[2][0].mRight ,v[2][1].mLeft)
    && DoesFit(v[2][1].mRight ,v[2][2].mLeft)
  );
}
//---------------------------------------------------------------------------
const bool DoesFit(const std::vector<PuzzlePiece>& v)
{
  assert(v.size() == 9);
  return (
       DoesFit(v[0].mBottom,v[3].mTop)
    && DoesFit(v[1].mBottom,v[4].mTop)
    && DoesFit(v[2].mBottom,v[5].mTop)
    && DoesFit(v[3].mBottom,v[6].mTop)
    && DoesFit(v[4].mBottom,v[7].mTop)
    && DoesFit(v[5].mBottom,v[8].mTop)
    && DoesFit(v[0].mRight ,v[1].mLeft)
    && DoesFit(v[1].mRight ,v[2].mLeft)
    && DoesFit(v[3].mRight ,v[4].mLeft)
    && DoesFit(v[4].mRight ,v[5].mLeft)
    && DoesFit(v[6].mRight ,v[7].mLeft)
    && DoesFit(v[7].mRight ,v[8].mLeft)
  );
}
//---------------------------------------------------------------------------
const std::vector<PuzzlePiece> GetPieces()
{
  std::vector<PuzzlePiece> v;
  v.push_back(PuzzlePiece(hairyWormTail,wormLong,greenBeetleTail,hairyWormTail));
  v.push_back(PuzzlePiece(hairyWormHead,greenBeetleTail,wormLong,wormLong));
  v.push_back(PuzzlePiece(greenBeetleTail,wormLong,hairyWormHead,greenBeetleHead));
  v.push_back(PuzzlePiece(greenBeetleHead,brownBeetleHead,greenBeetleTail,hairyWormHead));
  v.push_back(PuzzlePiece(greenBeetleTail,brownBeetleTail,wormShort,brownBeetleTail));
  v.push_back(PuzzlePiece(brownBeetleTail,brownBeetleHead,hairyWormTail,wormLong));
  v.push_back(PuzzlePiece(greenBeetleHead,hairyWormTail,wormShort,brownBeetleTail));
  v.push_back(PuzzlePiece(brownBeetleHead,wormShort,wormShort,greenBeetleHead));
  v.push_back(PuzzlePiece(wormShort,greenBeetleHead,brownBeetleHead,greenBeetleHead));
  assert(v.size() == 9);
  return v;
}
//---------------------------------------------------------------------------
const int ConvertToInt(const PuzzlePiece& p)
{
  return (
      ( 1 * static_cast<int>(p.mTop))
    + ( 4 * static_cast<int>(p.mRight))
    + (16 * static_cast<int>(p.mBottom))
    + (64 * static_cast<int>(p.mLeft))
  );

}
//---------------------------------------------------------------------------
const bool operator==(const PuzzlePiece& p1, const PuzzlePiece& p2)
{
  return (p1.mValue == p2.mValue);
}
//---------------------------------------------------------------------------
const bool operator!=(const PuzzlePiece& p1, const PuzzlePiece& p2)
{
  return !(p1.mValue == p2.mValue);
}
//---------------------------------------------------------------------------
const bool operator<(const PuzzlePiece& p1, const PuzzlePiece& p2)
{
  assert(p1.mValue != p2.mValue);
  return (p1.mValue < p2.mValue);
  //return (ConvertToInt(p1) < ConvertToInt(p2));
}
//---------------------------------------------------------------------------
#pragma package(smart_init)

 

 

 

 

 

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

Go back to Richel Bilderbeek's homepage.

 

Valid XHTML 1.0 Strict

This page has been created by the tool CodeToHtml