//--------------------------------------------------------------------------- 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..."); }
//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>(); }