//---------------------------------------------------------------------------
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...");
}
예제 #2
0
//Beware - FindSolution works only for 4x4 game!!!
void Fifteen::FindSolution()
{
	CopyTGameArray(GameArray, GameStartArray);			
	points = 0;
	Set* nothing;
	Set* closedSet = new Set();
	Set* openSet = new Set();
	Set* best = NULL;
	
	openSet->add(openSet, 0, GameArray, openSet, nothing);
	
	while (!openSet->empty())
	{
		openSet->best(openSet, best);		
		
		closedSet->add(closedSet, best->G, best->move, best->prev, best);			
		openSet->remove(openSet, best->move);			 
		CopyTGameArray(GameArray, best->move);
		
		if(best->H < 1)
		{
			SetSolution(best);
			ShowSolution();

			closedSet->DeleteAll(closedSet);
			openSet->DeleteAll(openSet);
			return;	
		}
		int zeroX;
		int zeroY;
		FindZero(zeroX, zeroY, best->move);
		
		for (int i = 0; i < 4; i++)
		{
			int dx = (-1) * ((zeroX > 0) && (i == 0)) + ((zeroX < SIZE - 1) && (i == 1));	
			int dy = (-1) * ((zeroY > 0) && (i == 2)) + ((zeroY < SIZE - 1) && (i == 3));
			
			TGameArray newArray;
			CopyTGameArray(newArray, best->move);
			newArray[zeroX][zeroY] = best->move[zeroX+dx][zeroY+dy];
			newArray[zeroX+dx][zeroY+dy] = 0; 
			if(!closedSet->isAlready(closedSet, newArray))
			{				
				openSet->add(openSet, best->G + 1, newArray, best, nothing);		
			}	
		}
	} 
}
//---------------------------------------------------------------------------
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>();
}