PuzzleSolver/Source/functions/solve/classExtension.cpp
Raphael Maenle 2ef3f164c7 added basic dP calculation, removed deprication warnings
Changed for loops to auto range, changed returns to bool literals, changed return of constructor to more basic call.

added dP calculation, save of the per piece runtime is still missing in puzzlebox or constraint matrix.
2017-12-13 10:47:15 +01:00

325 lines
13 KiB
C++
Executable File

#include "../../header.h"
//shifts puzzle piece one to the right
void PuzzlePiece::shift(unsigned int moves)
{
shifts = (shifts+moves)%4;
setConnections(((getConnections() >> (moves*2)) | (getConnections() << sizeof(unsigned char)*8 - (moves*2))));
}
//creates random centerpiece
void PuzzlePiece::randomCenterPiece()
{
setConnections(0b00000000);
if(rand()%2)
setConnections(getConnections() | 0b01000000);
else
setConnections(getConnections() | 0b10000000);
if(rand()%2)
setConnections(getConnections() | 0b00010000);
else
setConnections(getConnections() | 0b00100000);
if(rand()%2)
setConnections(getConnections() | 0b00000100);
else
setConnections(getConnections() | 0b00001000);
if(rand()%2)
setConnections(getConnections() | 0b00000001);
else
setConnections(getConnections() | 0b00000010);
}
//tests the myPart in all 4 rotations at position m, n
bool Puzzle::testRotationPiece(coor myCoor, PuzzlePiece& myPart, int nrOfRotations)
{
for(int rotation=0; rotation < nrOfRotations; rotation++)
{
//coor myCoor(m,n);
if(PlaceOfPartGood(myCoor,myPart))
return true;
//cout << "was rotated in testRotationPiece" << endl;
myPart.shift(1);
}
//cout << "Was a bad part" << endl;
return false;
}
//insterts piece at position in box according to boxidentifier and removes piece from puzzle
//this returns the position after!! the puzzle piece was put back in! not the boxidentifier of the piece. look that up in other function.
unsigned int Puzzle::putBackIntoBox(coor myCoor, vector<PuzzlePiece>& myBox)
{
#ifdef debug
cout << "putting back" << endl;
cout << "Old Box: ";
printBox(myBox);
cout << endl;
#endif
for(int i = 0; i < myBox.size();i++)
{
if(myBox[i].getBoxIdentifier()>getPiece(myCoor.m,myCoor.n).getBoxIdentifier())
{
myBox.insert(myBox.begin()+i,getPiece(myCoor.m,myCoor.n));
removePiece(myCoor);
return i+1;
}
}
//using push back, if the element was the last element in the vector chain
myBox.push_back(getPiece(myCoor.m,myCoor.n));
removePiece(myCoor);
return myBox.size();
}
//checks if the myPart in its current orientation is legal in position m, n
bool Puzzle::PlaceOfPartGood(coor myCoor, PuzzlePiece& myPart)
{
PuzzlePiece negativePart(0);
negativePart.setConnections(negativePart.getConnections() | (getPiece(myCoor.m,myCoor.n+1).getConnections() & 0b11000000));
negativePart.setConnections(negativePart.getConnections() | (getPiece(myCoor.m-1,myCoor.n).getConnections() & 0b00110000));
negativePart.setConnections(negativePart.getConnections() | (getPiece(myCoor.m,myCoor.n-1).getConnections() & 0b00001100));
negativePart.setConnections(negativePart.getConnections() | (getPiece(myCoor.m+1,myCoor.n).getConnections() & 0b00000011));
negativePart.shift(2);
if (
( ((((negativePart.getConnections() & 0b11000000) ^ (myPart.getConnections() & 0b11000000)) != 0b00000000) && (((myPart.getConnections() & 0b11000000) != 0b00000000) && (negativePart.getConnections() & 0b11000000) != 0b00000000))
|| ((((negativePart.getConnections() & 0b11000000) == 0b11000000) || ((myPart.getConnections() & 0b11000000) == 0b11000000)) && (((myPart.getConnections() & 0b11000000) != 0b00000000) && (negativePart.getConnections() & 0b11000000) != 0b00000000))
|| (((negativePart.getConnections() & 0b11000000) == 0b00000000) && ((myPart.getConnections() & 0b11000000) == 0b00000000)) )
&&
( ((((negativePart.getConnections() & 0b00110000) ^ (myPart.getConnections() & 0b00110000)) != 0b00000000) && (((myPart.getConnections() & 0b00110000) != 0b00000000) && (negativePart.getConnections() & 0b00110000) != 0b00000000))
|| ((((negativePart.getConnections() & 0b00110000) == 0b00110000) || ((myPart.getConnections() & 0b00110000) == 0b00110000)) && (((myPart.getConnections() & 0b00110000) != 0b00000000) && (negativePart.getConnections() & 0b00110000) != 0b00000000))
|| (((negativePart.getConnections() & 0b00110000) == 0b00000000) && ((myPart.getConnections() & 0b00110000) == 0b00000000)) )
&&
( ((((negativePart.getConnections() & 0b00001100) ^ (myPart.getConnections() & 0b00001100)) != 0b00000000) && (((myPart.getConnections() & 0b00001100) != 0b00000000) && (negativePart.getConnections() & 0b00001100) != 0b00000000))
|| ((((negativePart.getConnections() & 0b00001100) == 0b00001100) || ((myPart.getConnections() & 0b00001100) == 0b00001100)) && (((myPart.getConnections() & 0b00001100) != 0b00000000) && (negativePart.getConnections() & 0b00001100) != 0b00000000))
|| (((negativePart.getConnections() & 0b00001100) == 0b00000000) && ((myPart.getConnections() & 0b00001100) == 0b00000000)) )
&&
( ((((negativePart.getConnections() & 0b00000011) ^ (myPart.getConnections() & 0b00000011)) != 0b00000000) && (((myPart.getConnections() & 0b00000011) != 0b00000000) && (negativePart.getConnections() & 0b00000011) != 0b00000000))
|| ((((negativePart.getConnections() & 0b00000011) == 0b00000011) || ((myPart.getConnections() & 0b00000011) == 0b00000011)) && (((myPart.getConnections() & 0b00000011) != 0b00000000) && (negativePart.getConnections() & 0b00000011) != 0b00000000))
|| (((negativePart.getConnections() & 0b00000011) == 0b00000000) && ((myPart.getConnections() & 0b00000011) == 0b00000000)) )
)
{
//cout << "good Part: ";
//myPart.printPiece();
//cout << endl;
return true;
}
//cout << "bad Part: ";
//myPart.printPiece();
//cout << endl;
return false;
}
//TODO!!
//simpler algorithm to the first placeofpartgood
//not yet functional!!!
bool Puzzle::PlaceOfPart2Good(coor myCoor, PuzzlePiece& myPart)
{
PuzzlePiece tmpPuzzlePiece = myPart;
//make tmp a negative part
if(((tmpPuzzlePiece.getConnections() & 0b11000000) != 0b11000000) || ((tmpPuzzlePiece.getConnections() & 0b11000000) != 0b00000000))
tmpPuzzlePiece.setConnections(tmpPuzzlePiece.getConnections() ^ 0b11000000);
if(((tmpPuzzlePiece.getConnections() & 0b00110000) != 0b00110000) || ((tmpPuzzlePiece.getConnections() & 0b00110000) != 0b00000000))
tmpPuzzlePiece.setConnections(tmpPuzzlePiece.getConnections() ^ 0b00110000);
if(((tmpPuzzlePiece.getConnections() & 0b00001100) != 0b00001100)|| ((tmpPuzzlePiece.getConnections() & 0b00001100) != 0b00000000))
tmpPuzzlePiece.setConnections(tmpPuzzlePiece.getConnections() ^ 0b00001100);
if(((tmpPuzzlePiece.getConnections() & 0b00000011) != 0b00000011) || ((tmpPuzzlePiece.getConnections() & 0b00000011) != 0b00000000))
tmpPuzzlePiece.setConnections(tmpPuzzlePiece.getConnections() ^ 0b00000011);
PuzzlePiece negativePart(0);
negativePart.setConnections(negativePart.getConnections() | (getPiece(myCoor.m,myCoor.n+1).getConnections() & 0b11000000));
negativePart.setConnections(negativePart.getConnections() | (getPiece(myCoor.m-1,myCoor.n).getConnections() & 0b00110000));
negativePart.setConnections(negativePart.getConnections() | (getPiece(myCoor.m,myCoor.n-1).getConnections() & 0b00001100));
negativePart.setConnections(negativePart.getConnections() | (getPiece(myCoor.m+1,myCoor.n).getConnections() & 0b00000011));
negativePart.shift(2);
//check tmp part with environment
if(((negativePart.getConnections() & 0b11000000) == (tmpPuzzlePiece.getConnections() & 0b11000000)) && ((negativePart.getConnections() & 0b00110000) == (tmpPuzzlePiece.getConnections ()& 0b00110000)) &&
((negativePart.getConnections() & 0b00001100) == (tmpPuzzlePiece.getConnections() & 0b00001100)) && ((negativePart.getConnections() & 0b00000011) == (tmpPuzzlePiece.getConnections() & 0b00000011)))
return true;
return false;
}
//prints the true puzzle (without 0 edges)
void Puzzle::printPuzzle()
{
cout << "current Puzzle: " << endl;
for(int i=1;i<row+1;i++)
{
for(int j=1;j<col+1;j++)
{
Matrix[i][j].printPiece();
cout << " ";
}
cout << endl;
}
cout << endl;
}
//creates a legal puzzle out of random pieces
void randomBox::createRandomAbstraction1()
{
coor myCoor;
PuzzlePiece temporaryRandomPiece(0);
for(int i=0;i<getRows();i++)
{
for(int j = 0; j < getCols();)
{
//create random piece, set edges according to position and check if piece is good
temporaryRandomPiece.randomCenterPiece();
if(i==0)
temporaryRandomPiece.setConnections(0b00111111 & temporaryRandomPiece.getConnections());
if(i==getRows()-1)
temporaryRandomPiece.setConnections(0b11110011 & temporaryRandomPiece.getConnections());
if(j==0)
temporaryRandomPiece.setConnections(0b11111100 & temporaryRandomPiece.getConnections());
if(j==getCols()-1)
temporaryRandomPiece.setConnections(0b11001111 & temporaryRandomPiece.getConnections());
myCoor.m = j;
myCoor.n = i;
if(PlaceOfPartGood(myCoor,temporaryRandomPiece))
{
temporaryRandomPiece.assignIdentifier();
setPiece(myCoor,temporaryRandomPiece);
j++;
}
}
}
}
void randomBox::createRandomAbstraction2()
{
//get a picture
cv::Mat PuzzlePicture = cv::imread("../../Codicil/Images/Balloons.jpg");
if(! PuzzlePicture.data )
{
cout << "Could not open or find the image" << std::endl ;
return;
}
//split a picture into mxn pieces
cv::Size smallSize ((int)(PuzzlePicture.cols/getCols()) ,(int)(PuzzlePicture.rows/getRows()));
// get the image data
vector<cv::Mat> smallChannels;
unsigned int i=0,j=0;
for ( int y=0; y<=PuzzlePicture.rows-smallSize.height; y += smallSize.height )
{
for ( int x=0 ; x<=PuzzlePicture.cols-smallSize.width; x += smallSize.width )
{
//split into different ROIs
cv::Rect rect = cv::Rect (x ,y , smallSize.width, smallSize.height );
cv::Mat tmpSmallPicture = cv::Mat(PuzzlePicture,rect);
cv::split(tmpSmallPicture, smallChannels);
//save color into individual PuzzlePieces in Matrix
PuzzlePiece tmpPiece = getPiece(j,i);
tmpPiece.r = cv::mean(smallChannels[0]).operator[](0);
tmpPiece.g = cv::mean(smallChannels[1]).operator[](0);
tmpPiece.b = cv::mean(smallChannels[2]).operator[](0);
setPiece(coor(j,i),tmpPiece);
j++;
}
i++;
j=0;
}
}
void randomBox::putAllIntoBox() {
for (int i = 0; i < getRows(); i++)
{
for (int j = 0; j < getCols(); j++)
{
Box.push_back(getPiece(j,i));
}
}
}
//prints a box contents on console
void randomBox::printBox()
{
shuffle();
for (auto i:Box)
{
i.printPiece();
cout << ' ';
}
cout << endl;
}
//shuffles around a box, randomizing pieces and orientation
vector<PuzzlePiece> randomBox::shuffle()
{
random_shuffle(Box.begin(),Box.end());
for (auto &i:Box)
{
i.shift(rand()%4);
i.resetShift();
}
numerateBox(Box);
return Box;
}
//creates a random box size m, n, shuffles it, and then retuns it
vector<PuzzlePiece> createBox(coor myCoor)
{
randomBox myFirstPuzzleBox(myCoor.m,myCoor.n);
myFirstPuzzleBox.createRandomAbstraction1();
myFirstPuzzleBox.createRandomAbstraction2();
myFirstPuzzleBox.putAllIntoBox();
myFirstPuzzleBox.printPuzzle();
return myFirstPuzzleBox.shuffle();
}
//prints contents of box
void printBox(vector<PuzzlePiece> myBox)
{
cout << "current Box: " << endl;
for (auto &i:myBox)
{
i.printPiece();
cout << ' ';
}
cout << endl;
}
//gives every element in box a box identifier.
void numerateBox(vector<PuzzlePiece>& myBox)
{
for(int i = 0; i< myBox.size();i++)
myBox[i].setBoxIdentifier(i);
}
std::vector<PuzzlePiece> convertPart2PuzzlePiece(std::vector<Part> simplePartBox)
{
std::vector<PuzzlePiece> advancedPartBox;
for(auto const &i:simplePartBox)
{
PuzzlePiece tmpNewPiece(0);
tmpNewPiece.setConnections(i.getConnections());
advancedPartBox.push_back(tmpNewPiece);
}
return advancedPartBox;
}