Merge branch 'master' into Layer_PoempelPosition
This commit is contained in:
commit
1161b972ba
@ -222,8 +222,6 @@ bool AbstractionLayer_1::PlaceOfPartGood(coor myCoor, uint8_t& myPart)
|
|||||||
|| (((negativePart & 0b00000011) == 0b00000000) && ((myPart & 0b00000011) == 0b00000000)) )
|
|| (((negativePart & 0b00000011) == 0b00000000) && ((myPart & 0b00000011) == 0b00000000)) )
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
if(myCoor.row==18 && myCoor.col==35)
|
|
||||||
cout << "gud: " << std::bitset<8>(myPart) << endl;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -399,6 +397,7 @@ bool analyseParts::getImages(){
|
|||||||
vector<vector<Point> > contours;
|
vector<vector<Point> > contours;
|
||||||
vector<Vec4i> hierarchy;
|
vector<Vec4i> hierarchy;
|
||||||
vector<Point> corners;
|
vector<Point> corners;
|
||||||
|
vector<double> lens;
|
||||||
|
|
||||||
vector<Mat> puzzleimages;
|
vector<Mat> puzzleimages;
|
||||||
vector<vector<Point> > contours1;
|
vector<vector<Point> > contours1;
|
||||||
@ -430,6 +429,8 @@ bool analyseParts::getImages(){
|
|||||||
}
|
}
|
||||||
mask.setCorners(corners);
|
mask.setCorners(corners);
|
||||||
mask.setTabs(analyseContour(corners,contours[0]));
|
mask.setTabs(analyseContour(corners,contours[0]));
|
||||||
|
mask.setLens(analyseLens(lens, corners));
|
||||||
|
mask.setMidpoint(calcMidpoint(corners));
|
||||||
masks.push_back(mask);
|
masks.push_back(mask);
|
||||||
destroyAllWindows();
|
destroyAllWindows();
|
||||||
}
|
}
|
||||||
@ -448,6 +449,24 @@ Point analyseParts::findCenter(Mat img){
|
|||||||
return center;
|
return center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float pitch2Points(Point one, Point two) //In Header
|
||||||
|
{
|
||||||
|
float pitch=0;
|
||||||
|
float deltay=0;
|
||||||
|
float deltax = 0;
|
||||||
|
deltay = abs(one.y - two.y);
|
||||||
|
deltax = abs(one.x - two.x);
|
||||||
|
|
||||||
|
if(deltax == 0)
|
||||||
|
deltax = 0.1;
|
||||||
|
|
||||||
|
if(deltay == 0)
|
||||||
|
deltay = 0.1;
|
||||||
|
|
||||||
|
pitch = deltay/deltax;
|
||||||
|
return pitch;
|
||||||
|
}
|
||||||
|
|
||||||
vector<Point> analyseParts::findCorners(vector<Point> contour, Point center){
|
vector<Point> analyseParts::findCorners(vector<Point> contour, Point center){
|
||||||
int minContourPoint = 5;
|
int minContourPoint = 5;
|
||||||
vector<vector<Point>> quad_contour;
|
vector<vector<Point>> quad_contour;
|
||||||
@ -614,136 +633,542 @@ vector<Point> analyseParts::findCorners(vector<Point> contour, Point center){
|
|||||||
if(DISPLAY) imshow("draw",drawing);
|
if(DISPLAY) imshow("draw",drawing);
|
||||||
return corners;
|
return corners;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char analyseParts::analyseContour(vector<Point> corners, vector<Point> contour) {
|
unsigned char analyseParts::analyseContour(vector<Point> corners, vector<Point> contour) {
|
||||||
vector<Point> contour_right;
|
vector<Point> contour_right;
|
||||||
vector<Point> contour_top;
|
vector<Point> contour_top;
|
||||||
vector<Point> contour_left;
|
vector<Point> contour_left;
|
||||||
vector<Point> contour_bottom;
|
vector<Point> contour_bottom;
|
||||||
Mat drawing = createEmpty(Point(IMG_SIZE,IMG_SIZE),1);
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
int corner0 = 0, corner1 = 0, corner2 = 0, corner3 = 0;
|
int corner0 = 0, corner1 = 0, corner2 = 0, corner3 = 0;
|
||||||
for(int i = 0; i < contour.size(); i++){
|
for(int i = 0; i < contour.size(); i++){
|
||||||
|
//cout << "contour " << contour[i] << endl;
|
||||||
if(contour[i] == corners[0])
|
if(contour[i] == corners[0])
|
||||||
corner0 = i;
|
corner0 = i;
|
||||||
if(contour[i] == corners[1])
|
else if(contour[i] == corners[1])
|
||||||
corner1 = i;
|
corner1 = i;
|
||||||
if(contour[i] == corners[2])
|
else if(contour[i] == corners[2])
|
||||||
corner2 = i;
|
corner2 = i;
|
||||||
if(contour[i] == corners[3])
|
else if(contour[i] == corners[3])
|
||||||
corner3 = i;
|
corner3 = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
count = corner0;
|
count = corner0;
|
||||||
while(contour[count] != contour[corner2]){
|
while(contour[count] != contour[corner2]){
|
||||||
count++;
|
count++;
|
||||||
count %= contour.size();
|
count %= contour.size();
|
||||||
contour_right.push_back(contour[count]);
|
contour_right.push_back(contour[count]);
|
||||||
circle(drawing,contour[count],3,Scalar(255,0,0),2,8);
|
|
||||||
}
|
}
|
||||||
count = corner2;
|
count = corner2;
|
||||||
while(contour[count] != contour[corner3]){
|
while(contour[count] != contour[corner3]){
|
||||||
count++;
|
count++;
|
||||||
count %= contour.size();
|
count %= contour.size();
|
||||||
contour_top.push_back(contour[count]);
|
contour_top.push_back(contour[count]);
|
||||||
circle(drawing,contour[count],3,Scalar(0,255,0),2,8);
|
|
||||||
}
|
}
|
||||||
count = corner3;
|
count = corner3;
|
||||||
while(contour[count] != contour[corner1]){
|
while(contour[count] != contour[corner1]){
|
||||||
count++;
|
count++;
|
||||||
count %= contour.size();
|
count %= contour.size();
|
||||||
contour_left.push_back(contour[count]);
|
contour_left.push_back(contour[count]);
|
||||||
circle(drawing,contour[count],3,Scalar(0,0,255),2,8);
|
|
||||||
}
|
}
|
||||||
count = corner1;
|
count = corner1;
|
||||||
while(contour[count] != contour[corner0]){
|
while(contour[count] != contour[corner0]){
|
||||||
count++;
|
count++;
|
||||||
count %= contour.size();
|
count %= contour.size();
|
||||||
contour_bottom.push_back(contour[count]);
|
contour_bottom.push_back(contour[count]);
|
||||||
circle(drawing,contour[count],3,Scalar(255,255,255),2,8);
|
|
||||||
}
|
}
|
||||||
float ref_right = (contour[corner0].x+contour[corner2].x)/2;
|
|
||||||
float ref_top = (contour[corner2].y+contour[corner3].y)/2;
|
|
||||||
float ref_left = (contour[corner3].x+contour[corner1].x)/2;
|
|
||||||
float ref_bottom = (contour[corner1].y+contour[corner0].y)/2;
|
|
||||||
|
|
||||||
|
contour_right.insert(contour_right.begin(),corners[0]);
|
||||||
|
contour_right.push_back(corners[2]);
|
||||||
|
|
||||||
|
contour_top.insert(contour_top.begin(),corners[2]);
|
||||||
|
contour_top.push_back(corners[3]);
|
||||||
|
|
||||||
|
contour_left.insert(contour_left.begin(),corners[3]);
|
||||||
|
contour_left.push_back(corners[1]);
|
||||||
|
|
||||||
|
contour_bottom.insert(contour_bottom.begin(),corners[1]);
|
||||||
|
contour_bottom.push_back(corners[0]);
|
||||||
|
|
||||||
|
/*-------------------------------------*/
|
||||||
|
//ecken Korrektur rechte Kontur
|
||||||
|
/*-------------------------------------*/
|
||||||
|
|
||||||
|
vector<Point> contour_r;
|
||||||
|
double laenge = 0;
|
||||||
|
int idx = 0, counter = 0, c = 0, d = 0;
|
||||||
|
|
||||||
|
while (counter < (contour_right.size()-1)) {
|
||||||
|
counter++;
|
||||||
|
c++;
|
||||||
|
laenge = sqrt((contour_right[idx].x - contour_right[idx + c].x) * (contour_right[idx].x - contour_right[idx + c].x) +
|
||||||
|
(contour_right[idx].y - contour_right[idx + c].y) * (contour_right[idx].y - contour_right[idx + c].y));
|
||||||
|
if (laenge > 4) {
|
||||||
|
d++;
|
||||||
|
contour_r.push_back(contour_right[idx]);
|
||||||
|
idx = counter;
|
||||||
|
c = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float k = 0;
|
||||||
|
int correct_count = 0;
|
||||||
|
int correct_idx = 0;
|
||||||
|
for(correct_count = 0; correct_count < contour_r.size()-2; correct_count++){
|
||||||
|
|
||||||
|
k = pitch2Points(contour_r[correct_count],contour_r[correct_count+1]);
|
||||||
|
//cout << "unten: " << k << endl;
|
||||||
|
if(k >= 2) {
|
||||||
|
correct_idx = correct_count;
|
||||||
|
correct_count = contour_r.size();
|
||||||
|
}
|
||||||
|
if(correct_count > 500)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/*-----------------------------------*/
|
||||||
|
if(correct_idx > 0){
|
||||||
|
corners[0] = contour_r[correct_idx];
|
||||||
|
}
|
||||||
|
/*-----------------------------------*/
|
||||||
|
vector<Point> contour_r1;
|
||||||
|
laenge = 0;
|
||||||
|
idx = contour_right.size()-1, counter = contour_right.size()-1, c = 0, d = 0;
|
||||||
|
|
||||||
|
while (counter > 1) {
|
||||||
|
counter--;
|
||||||
|
c--;
|
||||||
|
laenge = sqrt((contour_right[idx].x - contour_right[idx + c].x) * (contour_right[idx].x - contour_right[idx + c].x) +
|
||||||
|
(contour_right[idx].y - contour_right[idx + c].y) * (contour_right[idx].y - contour_right[idx + c].y));
|
||||||
|
if (laenge > 4) {
|
||||||
|
contour_r1.push_back(contour_right[idx]);
|
||||||
|
idx = counter;
|
||||||
|
c = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
k = 0;
|
||||||
|
correct_count = 0;
|
||||||
|
correct_idx = 0;
|
||||||
|
for(correct_count = 0; correct_count < contour_r1.size()-2; correct_count++){
|
||||||
|
|
||||||
|
k = pitch2Points(contour_r1[correct_count],contour_r1[correct_count+1]);
|
||||||
|
// cout << "oben: " << k << endl;
|
||||||
|
if(k >= 2) {
|
||||||
|
correct_idx = correct_count;
|
||||||
|
correct_count = contour_r1.size();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------*/
|
||||||
|
if(correct_idx > 0){
|
||||||
|
corners[2] = contour_r1[correct_idx];
|
||||||
|
}
|
||||||
|
/*-----------------------------------*/
|
||||||
|
|
||||||
|
/*-------------------------------------*/
|
||||||
|
//ecken Korrektur links Kontur
|
||||||
|
/*-------------------------------------*/
|
||||||
|
|
||||||
|
vector<Point> contour_l;
|
||||||
|
laenge = 0;
|
||||||
|
idx = 0, counter = 0, c = 0, d = 0;
|
||||||
|
|
||||||
|
while (counter < (contour_left.size()-1)) {
|
||||||
|
counter++;
|
||||||
|
c++;
|
||||||
|
laenge = sqrt((contour_left[idx].x - contour_left[idx + c].x) * (contour_left[idx].x - contour_left[idx + c].x) +
|
||||||
|
(contour_left[idx].y - contour_left[idx + c].y) * (contour_left[idx].y - contour_left[idx + c].y));
|
||||||
|
if (laenge > 4) {
|
||||||
|
d++;
|
||||||
|
contour_l.push_back(contour_left[idx]);
|
||||||
|
idx = counter;
|
||||||
|
c = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
k = 0;
|
||||||
|
correct_count = 0;
|
||||||
|
correct_idx = 0;
|
||||||
|
for(correct_count = 0; correct_count < contour_l.size()-2; correct_count++){
|
||||||
|
|
||||||
|
k = pitch2Points(contour_l[correct_count],contour_l[correct_count+1]);
|
||||||
|
// cout << "oben _links: " << k << endl;
|
||||||
|
if(k >= 2) {
|
||||||
|
correct_idx = correct_count;
|
||||||
|
correct_count = contour_l.size();
|
||||||
|
}
|
||||||
|
if(correct_count > 500)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/*-----------------------------------*/
|
||||||
|
if(correct_idx > 0){
|
||||||
|
corners[3] = contour_l[correct_idx];
|
||||||
|
}
|
||||||
|
/*-----------------------------------*/
|
||||||
|
vector<Point> contour_l1;
|
||||||
|
laenge = 0;
|
||||||
|
idx = contour_left.size()-1, counter = contour_left.size()-1, c = 0, d = 0;
|
||||||
|
|
||||||
|
while (counter > 1) {
|
||||||
|
counter--;
|
||||||
|
c--;
|
||||||
|
laenge = sqrt((contour_left[idx].x - contour_left[idx + c].x) * (contour_left[idx].x - contour_left[idx + c].x) +
|
||||||
|
(contour_left[idx].y - contour_left[idx + c].y) * (contour_left[idx].y - contour_left[idx + c].y));
|
||||||
|
if (laenge > 4) {
|
||||||
|
contour_l1.push_back(contour_left[idx]);
|
||||||
|
idx = counter;
|
||||||
|
c = 0;
|
||||||
|
}
|
||||||
|
if(correct_count > 500)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
k = 0;
|
||||||
|
correct_count = 0;
|
||||||
|
correct_idx = 0;
|
||||||
|
for(correct_count = 0; correct_count < contour_l1.size(); correct_count++){
|
||||||
|
|
||||||
|
k = pitch2Points(contour_l1[correct_count],contour_l1[correct_count+1]);
|
||||||
|
if(k >= 2) {
|
||||||
|
// cout << "end _links: " << endl;
|
||||||
|
correct_idx = correct_count;
|
||||||
|
correct_count = contour_l1.size();
|
||||||
|
}
|
||||||
|
if(correct_count > 500)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/*-----------------------------------*/
|
||||||
|
// cout << "unten _links_correct: " << correct_idx << endl;
|
||||||
|
if(correct_idx > 0){
|
||||||
|
corners[1] = contour_l1[correct_idx];
|
||||||
|
}
|
||||||
|
/*-----------------------------------*/
|
||||||
|
|
||||||
|
/*-------------------------------------*/
|
||||||
|
//ecken Korrektur oben Kontur
|
||||||
|
/*-------------------------------------*/
|
||||||
|
|
||||||
|
vector<Point> contour_t;
|
||||||
|
laenge = 0;
|
||||||
|
idx = 0, counter = 0, c = 0, d = 0;
|
||||||
|
|
||||||
|
while (counter < (contour_top.size()-1)) {
|
||||||
|
counter++;
|
||||||
|
c++;
|
||||||
|
laenge = sqrt((contour_top[idx].x - contour_top[idx + c].x) * (contour_top[idx].x - contour_top[idx + c].x) +
|
||||||
|
(contour_top[idx].y - contour_top[idx + c].y) * (contour_top[idx].y - contour_top[idx + c].y));
|
||||||
|
if (laenge > 4) {
|
||||||
|
d++;
|
||||||
|
contour_t.push_back(contour_top[idx]);
|
||||||
|
idx = counter;
|
||||||
|
c = 0;
|
||||||
|
}
|
||||||
|
if(correct_count > 500)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
k = 0;
|
||||||
|
correct_count = 0;
|
||||||
|
correct_idx = 0;
|
||||||
|
for(correct_count = 0; correct_count < contour_t.size()-2; correct_count++){
|
||||||
|
|
||||||
|
k = pitch2Points(contour_t[correct_count],contour_t[correct_count+1]);
|
||||||
|
// cout << "top _rechts: " << k << endl;
|
||||||
|
if(k <= 2) {
|
||||||
|
correct_idx = correct_count;
|
||||||
|
correct_count = contour_t.size();
|
||||||
|
}
|
||||||
|
if(correct_count > 500)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/*-----------------------------------*/
|
||||||
|
if(correct_idx > 0){
|
||||||
|
corners[2] = contour_t[correct_idx];
|
||||||
|
}
|
||||||
|
/*-----------------------------------*/
|
||||||
|
vector<Point> contour_t1;
|
||||||
|
laenge = 0;
|
||||||
|
idx = contour_top.size()-1, counter = contour_top.size()-1, c = 0, d = 0;
|
||||||
|
|
||||||
|
while (counter > 1) {
|
||||||
|
counter--;
|
||||||
|
c--;
|
||||||
|
laenge = sqrt((contour_top[idx].x - contour_top[idx + c].x) * (contour_top[idx].x - contour_top[idx + c].x) +
|
||||||
|
(contour_top[idx].y - contour_top[idx + c].y) * (contour_top[idx].y - contour_top[idx + c].y));
|
||||||
|
if (laenge > 4) {
|
||||||
|
contour_t1.push_back(contour_top[idx]);
|
||||||
|
idx = counter;
|
||||||
|
c = 0;
|
||||||
|
}
|
||||||
|
if(correct_count > 500)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
k = 0;
|
||||||
|
correct_idx = 0;
|
||||||
|
for(correct_count = 0; correct_count < contour_t1.size(); correct_count++){
|
||||||
|
k = pitch2Points(contour_t1[correct_count],contour_t1[correct_count+1]);
|
||||||
|
if(k < 2) {
|
||||||
|
correct_idx = correct_count;
|
||||||
|
correct_count = contour_t1.size();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*-----------------------------------*/
|
||||||
|
if(correct_idx > 0){
|
||||||
|
corners[3] = contour_t1[correct_idx];
|
||||||
|
}
|
||||||
|
/*-------------------------------------*/
|
||||||
|
|
||||||
|
/*-------------------------------------*/
|
||||||
|
//ecken Korrektur unten Kontur
|
||||||
|
/*-------------------------------------*/
|
||||||
|
|
||||||
|
vector<Point> contour_b;
|
||||||
|
laenge = 0;
|
||||||
|
idx = 0, counter = 0, c = 0, d = 0;
|
||||||
|
|
||||||
|
while (counter < (contour_bottom.size()-1)) {
|
||||||
|
counter++;
|
||||||
|
c++;
|
||||||
|
laenge = sqrt((contour_bottom[idx].x - contour_bottom[idx + c].x) * (contour_bottom[idx].x - contour_bottom[idx + c].x) +
|
||||||
|
(contour_bottom[idx].y - contour_bottom[idx + c].y) * (contour_bottom[idx].y - contour_bottom[idx + c].y));
|
||||||
|
if (laenge > 4) {
|
||||||
|
d++;
|
||||||
|
contour_b.push_back(contour_bottom[idx]);
|
||||||
|
idx = counter;
|
||||||
|
c = 0;
|
||||||
|
}
|
||||||
|
if(correct_count > 500)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
k = 0;
|
||||||
|
correct_count = 0;
|
||||||
|
correct_idx = 0;
|
||||||
|
for(correct_count = 0; correct_count < contour_b.size()-2; correct_count++){
|
||||||
|
|
||||||
|
k = pitch2Points(contour_b[correct_count],contour_b[correct_count+1]);
|
||||||
|
// cout << "bottom _rechts: " << k << endl;
|
||||||
|
if(k <= 2) {
|
||||||
|
correct_idx = correct_count;
|
||||||
|
correct_count = contour_b.size();
|
||||||
|
}
|
||||||
|
if(correct_count > 500)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/*-----------------------------------*/
|
||||||
|
if(correct_idx > 0){
|
||||||
|
corners[1] = contour_b[correct_idx];
|
||||||
|
}
|
||||||
|
/*-----------------------------------*/
|
||||||
|
vector<Point> contour_b1;
|
||||||
|
laenge = 0;
|
||||||
|
idx = contour_bottom.size()-1, counter = contour_bottom.size()-1, c = 0, d = 0;
|
||||||
|
|
||||||
|
while (counter > 1) {
|
||||||
|
counter--;
|
||||||
|
c--;
|
||||||
|
laenge = sqrt((contour_bottom[idx].x - contour_bottom[idx + c].x) * (contour_bottom[idx].x - contour_bottom[idx + c].x) +
|
||||||
|
(contour_bottom[idx].y - contour_bottom[idx + c].y) * (contour_bottom[idx].y - contour_bottom[idx + c].y));
|
||||||
|
if (laenge > 4) {
|
||||||
|
contour_b1.push_back(contour_bottom[idx]);
|
||||||
|
idx = counter;
|
||||||
|
c = 0;
|
||||||
|
}
|
||||||
|
if(correct_count > 500)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
k = 0;
|
||||||
|
correct_idx = 0;
|
||||||
|
for(correct_count = 0; correct_count < contour_b1.size(); correct_count++){
|
||||||
|
k = pitch2Points(contour_b1[correct_count],contour_b1[correct_count+1]);
|
||||||
|
if(k < 2) {
|
||||||
|
correct_idx = correct_count;
|
||||||
|
correct_count = contour_b1.size();
|
||||||
|
}
|
||||||
|
if(correct_count > 500)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/*-----------------------------------*/
|
||||||
|
if(correct_idx > 0){
|
||||||
|
corners[0] = contour_b1[correct_idx];
|
||||||
|
}
|
||||||
|
/*-----------------------------------*/
|
||||||
|
|
||||||
|
|
||||||
|
/*Korrektur Contour*/
|
||||||
|
|
||||||
|
vector<Point> contour_right_new;
|
||||||
|
vector<Point> contour_top_new;
|
||||||
|
vector<Point> contour_left_new;
|
||||||
|
vector<Point> contour_bottom_new;
|
||||||
|
|
||||||
|
for(int i = 0; i < contour.size(); i++){
|
||||||
|
if(contour[i] == corners[0])
|
||||||
|
corner0 = i;
|
||||||
|
else if(contour[i] == corners[1])
|
||||||
|
corner1 = i;
|
||||||
|
else if(contour[i] == corners[2])
|
||||||
|
corner2 = i;
|
||||||
|
else if(contour[i] == corners[3])
|
||||||
|
corner3 = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
count = corner0;
|
||||||
|
while(contour[count] != contour[corner2]){
|
||||||
|
count++;
|
||||||
|
count %= contour.size();
|
||||||
|
contour_right_new.push_back(contour[count]);
|
||||||
|
}
|
||||||
|
count = corner2;
|
||||||
|
while(contour[count] != contour[corner3]){
|
||||||
|
count++;
|
||||||
|
count %= contour.size();
|
||||||
|
contour_top_new.push_back(contour[count]);
|
||||||
|
}
|
||||||
|
count = corner3;
|
||||||
|
while(contour[count] != contour[corner1]){
|
||||||
|
count++;
|
||||||
|
count %= contour.size();
|
||||||
|
contour_left_new.push_back(contour[count]);
|
||||||
|
}
|
||||||
|
count = corner1;
|
||||||
|
while(contour[count] != contour[corner0]){
|
||||||
|
count++;
|
||||||
|
count %= contour.size();
|
||||||
|
contour_bottom_new.push_back(contour[count]);
|
||||||
|
}
|
||||||
|
|
||||||
|
contour_right_new.insert(contour_right_new.begin(),corners[0]);
|
||||||
|
contour_right_new.push_back(corners[2]);
|
||||||
|
|
||||||
|
contour_top_new.insert(contour_top_new.begin(),corners[2]);
|
||||||
|
contour_top_new.push_back(corners[3]);
|
||||||
|
|
||||||
|
contour_left_new.insert(contour_left_new.begin(),corners[3]);
|
||||||
|
contour_left_new.push_back(corners[1]);
|
||||||
|
|
||||||
|
contour_bottom_new.insert(contour_bottom_new.begin(),corners[1]);
|
||||||
|
contour_bottom_new.push_back(corners[0]);
|
||||||
|
/*----------------------*/
|
||||||
|
|
||||||
|
float ref_right = (corners[0].x+corners[2].x)/2;
|
||||||
|
float ref_top = (corners[2].y+corners[3].y)/2;
|
||||||
|
float ref_left = (corners[3].x+corners[1].x)/2;
|
||||||
|
float ref_bottom = (corners[1].y+corners[0].y)/2;
|
||||||
|
|
||||||
|
/*---------Suche Poempel Rechts---------------*/
|
||||||
float max_dist = 0;
|
float max_dist = 0;
|
||||||
float dist = 0;
|
float dist = 0;
|
||||||
int max_idx = 0;
|
int max_dist_idx = 0;
|
||||||
for(int i = 0; i < contour_right.size(); i++){
|
for(int i = 0; i < contour_right_new.size(); i++){
|
||||||
dist = abs(ref_right-contour_right[i].x);
|
dist = abs(ref_right-contour_right_new[i].x);
|
||||||
if(dist > max_dist) {
|
if(dist > max_dist) {
|
||||||
max_dist = dist;
|
max_dist = dist;
|
||||||
max_idx = i;
|
max_dist_idx = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/*-------------------------------------*/
|
||||||
unsigned char tabs = 0;
|
unsigned char tabs = 0;
|
||||||
circle(drawing,contour_right[max_idx],10,Scalar(255,0,255),2,8);
|
int poembel_threshold = 15;
|
||||||
if (ref_right - contour_right[max_idx].x <= -20)
|
if (ref_right - contour_right_new[max_dist_idx].x <= -poembel_threshold) {
|
||||||
tabs |= (2 << RIGHT);
|
tabs |= (2 << RIGHT);
|
||||||
if (ref_right - contour_right[max_idx].x >= 20)
|
}
|
||||||
|
if (ref_right - contour_right_new[max_dist_idx].x >= poembel_threshold) {
|
||||||
tabs |= (1 << RIGHT);
|
tabs |= (1 << RIGHT);
|
||||||
if (abs(ref_right - contour_right[max_idx].x) < 20)
|
}
|
||||||
|
if (abs(ref_right - contour_right_new[max_dist_idx].x) < poembel_threshold) {
|
||||||
tabs |= (0 << RIGHT);
|
tabs |= (0 << RIGHT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------Suche Poempel Oben---------------*/
|
||||||
max_dist = 0;
|
max_dist = 0;
|
||||||
dist = 0;
|
dist = 0;
|
||||||
max_idx = 0;
|
max_dist_idx = 0;
|
||||||
for(int i = 0; i < contour_top.size(); i++){
|
for(int i = 0; i < contour_top_new.size(); i++){
|
||||||
dist = abs(ref_top-contour_top[i].y);
|
dist = abs(ref_top -contour_top_new[i].y);
|
||||||
if(dist > max_dist) {
|
if(dist > max_dist) {
|
||||||
max_dist = dist;
|
max_dist = dist;
|
||||||
max_idx = i;
|
max_dist_idx = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
circle(drawing,contour_top[max_idx],10,Scalar(255,0,255),2,8);
|
/*-------------------------------------*/
|
||||||
if (ref_top - contour_top[max_idx].y <= -20)
|
|
||||||
|
if (ref_top - contour_top_new[max_dist_idx].y <= -poembel_threshold) {
|
||||||
tabs |= (1 << TOP);
|
tabs |= (1 << TOP);
|
||||||
if (ref_top - contour_top[max_idx].y >= 20)
|
}
|
||||||
|
if (ref_top - contour_top_new[max_dist_idx].y >= poembel_threshold) {
|
||||||
tabs |= (2 << TOP);
|
tabs |= (2 << TOP);
|
||||||
if (abs(ref_top - contour_top[max_idx].y) < 20)
|
}
|
||||||
|
if (abs(ref_top - contour_top_new[max_dist_idx].y) < poembel_threshold) {
|
||||||
tabs |= (0 << TOP);
|
tabs |= (0 << TOP);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------Suche Poempel Links---------------*/
|
||||||
max_dist = 0;
|
max_dist = 0;
|
||||||
dist = 0;
|
dist = 0;
|
||||||
max_idx = 0;
|
max_dist_idx = 0;
|
||||||
for(int i = 0; i < contour_left.size(); i++){
|
for(int i = 0; i < contour_left_new.size(); i++){
|
||||||
dist = abs(ref_left-contour_left[i].x);
|
dist = abs(ref_left -contour_left_new[i].x);
|
||||||
if(dist > max_dist) {
|
if(dist > max_dist) {
|
||||||
max_dist = dist;
|
max_dist = dist;
|
||||||
max_idx = i;
|
max_dist_idx = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
circle(drawing,contour_left[max_idx],10,Scalar(255,0,255),2,8);
|
/*-------------------------------------*/
|
||||||
if (ref_left - contour_left[max_idx].x <= -20)
|
if (ref_left - contour_left_new[max_dist_idx].x <= -poembel_threshold) {
|
||||||
tabs |= (1 << LEFT);
|
tabs |= (1 << LEFT);
|
||||||
if (ref_left - contour_left[max_idx].x >= 20)
|
}
|
||||||
|
if (ref_left - contour_left_new[max_dist_idx].x >= poembel_threshold) {
|
||||||
tabs |= (2 << LEFT);
|
tabs |= (2 << LEFT);
|
||||||
if (abs(ref_left - contour_left[max_idx].x) < 20)
|
}
|
||||||
|
if (abs(ref_left - contour_left_new[max_dist_idx].x) < poembel_threshold) {
|
||||||
tabs |= (0 << LEFT);
|
tabs |= (0 << LEFT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------Suche Poempel Oben---------------*/
|
||||||
max_dist = 0;
|
max_dist = 0;
|
||||||
dist = 0;
|
dist = 0;
|
||||||
max_idx = 0;
|
max_dist_idx = 0;
|
||||||
for(int i = 0; i < contour_bottom.size(); i++){
|
for(int i = 0; i < contour_bottom_new.size(); i++){
|
||||||
dist = abs(ref_bottom-contour_bottom[i].y);
|
dist = abs(ref_bottom -contour_bottom_new[i].y);
|
||||||
if(dist > max_dist) {
|
if(dist > max_dist) {
|
||||||
max_dist = dist;
|
max_dist = dist;
|
||||||
max_idx = i;
|
max_dist_idx = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
circle(drawing,contour_bottom[max_idx],10,Scalar(255,0,255),2,8);
|
/*-------------------------------------*/
|
||||||
if (ref_bottom - contour_bottom[max_idx].y <= -20)
|
if (ref_bottom - contour_bottom_new[max_dist_idx].y <= -poembel_threshold) {
|
||||||
tabs |= (2 << BOTTOM);
|
tabs |= (2 << BOTTOM);
|
||||||
if (ref_bottom - contour_bottom[max_idx].y >= 20)
|
}
|
||||||
|
if (ref_bottom - contour_bottom_new[max_dist_idx].y >= poembel_threshold) {
|
||||||
tabs |= (1 << BOTTOM);
|
tabs |= (1 << BOTTOM);
|
||||||
if (abs(ref_bottom - contour_bottom[max_idx].y) < 20)
|
}
|
||||||
|
if (abs(ref_bottom - contour_bottom_new[max_dist_idx].y) < poembel_threshold) {
|
||||||
tabs |= (0 << BOTTOM);
|
tabs |= (0 << BOTTOM);
|
||||||
|
}
|
||||||
//cout << bitset<sizeof(char) * CHAR_BIT> (tabs) << "b\n";
|
|
||||||
|
|
||||||
if(DISPLAY)imshow("corners",drawing);
|
|
||||||
if(DISPLAY)waitKey(0);
|
|
||||||
return tabs;
|
return tabs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
vector<double> analyseParts::analyseLens(vector<double> lens, vector<Point> corners){
|
||||||
|
Point space = corners[3] - corners[2];
|
||||||
|
double dist1 = sqrt(space.x*space.x+space.y*space.y);
|
||||||
|
lens.push_back(dist1);
|
||||||
|
space = corners[2] - corners[0];
|
||||||
|
dist1 = sqrt(space.x*space.x+space.y*space.y);
|
||||||
|
lens.push_back(dist1);
|
||||||
|
space = corners[0] - corners[1];
|
||||||
|
dist1 = sqrt(space.x*space.x+space.y*space.y);
|
||||||
|
lens.push_back(dist1);
|
||||||
|
space = corners[1] - corners[3];
|
||||||
|
dist1 = sqrt(space.x*space.x+space.y*space.y);
|
||||||
|
lens.push_back(dist1);
|
||||||
|
|
||||||
|
return lens;
|
||||||
|
}
|
||||||
|
|
||||||
|
Point analyseParts::calcMidpoint(vector<Point> corners){
|
||||||
|
Point midpoint;
|
||||||
|
|
||||||
|
midpoint = (corners[0] + corners[1] + corners[2] + corners[3])/4;
|
||||||
|
return midpoint;
|
||||||
|
}
|
||||||
|
@ -78,6 +78,10 @@ public:
|
|||||||
void setHierarchy(vector<Vec4i> hier){hierarchy = std::move(hier);}
|
void setHierarchy(vector<Vec4i> hier){hierarchy = std::move(hier);}
|
||||||
void setCorners(vector<Point> cor){corners = std::move(cor);}
|
void setCorners(vector<Point> cor){corners = std::move(cor);}
|
||||||
void setTabs(unsigned char t){tabs = t;}
|
void setTabs(unsigned char t){tabs = t;}
|
||||||
|
vector<double> getLen(){return len;}
|
||||||
|
void setLens(vector<double> l ){len = l;}
|
||||||
|
Point getMidpoint(){return midpoint;}
|
||||||
|
void setMidpoint(Point m ){midpoint = m;}
|
||||||
|
|
||||||
vector<Point> getCorners(){return corners;}
|
vector<Point> getCorners(){return corners;}
|
||||||
|
|
||||||
@ -87,7 +91,9 @@ private:
|
|||||||
vector<vector<Point>> contour;
|
vector<vector<Point>> contour;
|
||||||
vector<Vec4i> hierarchy;
|
vector<Vec4i> hierarchy;
|
||||||
Point center;
|
Point center;
|
||||||
|
vector<double> len;
|
||||||
unsigned char tabs;
|
unsigned char tabs;
|
||||||
|
Point midpoint;
|
||||||
};
|
};
|
||||||
|
|
||||||
class analyseParts{
|
class analyseParts{
|
||||||
@ -98,6 +104,10 @@ public:
|
|||||||
Point getCenter(int i){if(i>= nr_parts)return masks[nr_parts-1].getCenter(); else return masks[i].getCenter();}
|
Point getCenter(int i){if(i>= nr_parts)return masks[nr_parts-1].getCenter(); else return masks[i].getCenter();}
|
||||||
vector<Vec4i> getHierarchy(int i){if(i>= nr_parts)return masks[nr_parts-1].getHierarchy(); else return masks[i].getHierarchy();}
|
vector<Vec4i> getHierarchy(int i){if(i>= nr_parts)return masks[nr_parts-1].getHierarchy(); else return masks[i].getHierarchy();}
|
||||||
unsigned char getTabs(int i){if(i>= nr_parts)return masks[nr_parts-1].getTabs(); else return masks[i].getTabs();}
|
unsigned char getTabs(int i){if(i>= nr_parts)return masks[nr_parts-1].getTabs(); else return masks[i].getTabs();}
|
||||||
|
vector<double> getLen(int i ){return masks[i].getLen();}
|
||||||
|
vector<double> analyseLens(vector<double>, vector<Point>);
|
||||||
|
Point calcMidpoint(vector<Point>);
|
||||||
|
Point getMidpoint(int i){return masks[i].getMidpoint();}
|
||||||
Point findCenter(Mat);
|
Point findCenter(Mat);
|
||||||
vector<Point> findCorners(vector<Point>,Point);
|
vector<Point> findCorners(vector<Point>,Point);
|
||||||
unsigned char analyseContour(vector<Point>, vector<Point>);
|
unsigned char analyseContour(vector<Point>, vector<Point>);
|
||||||
|
@ -9,7 +9,7 @@ bool AbstractionLayer_PoempelPosition::PreProcessing(coor mySize, const vector<
|
|||||||
InitialiseConstraintMatrixSize(mySize.col, mySize.row);
|
InitialiseConstraintMatrixSize(mySize.col, mySize.row);
|
||||||
|
|
||||||
cout << "Done" << endl;
|
cout << "Done" << endl;
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//it through qualityVector and removes all that do not trigger PlaceOfPartGood
|
//it through qualityVector and removes all that do not trigger PlaceOfPartGood
|
||||||
@ -17,7 +17,7 @@ bool AbstractionLayer_PoempelPosition::EvaluateQuality (const coor constraintCoo
|
|||||||
{
|
{
|
||||||
for(int i = 0;i<qVector.size();i++)
|
for(int i = 0;i<qVector.size();i++)
|
||||||
{
|
{
|
||||||
float value = PlaceOfPartGood(constraintCoordinate, qVector[i].second->m_a3.SideLength));
|
float value = PlaceOfPartGood(constraintCoordinate, qVector[i].second->m_a3.SideLength);
|
||||||
if(value > 0.8)//TODO find threshold
|
if(value > 0.8)//TODO find threshold
|
||||||
{
|
{
|
||||||
qVector[i].first=value;
|
qVector[i].first=value;
|
||||||
|
@ -168,14 +168,14 @@ Mat Puzzle::resultImage( vector<LogEntry>& log){
|
|||||||
char name[100];
|
char name[100];
|
||||||
for (auto it:log)
|
for (auto it:log)
|
||||||
{
|
{
|
||||||
if (it.myCoor.col == 12 && it.myCoor.row == 0)
|
if (it.myCoor.col == 27 && it.myCoor.row == 5)
|
||||||
{
|
{
|
||||||
;
|
;
|
||||||
// imshow("result",result);
|
// imshow("result",result);
|
||||||
// waitKey(0);
|
// waitKey(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
cout << it.PieceCollector[0].second->GetPartID() << endl;
|
//cout << it.PieceCollector[0].second->GetPartID() << endl;
|
||||||
|
|
||||||
int imageNumber = it.PieceCollector[0].second->GetPartID();
|
int imageNumber = it.PieceCollector[0].second->GetPartID();
|
||||||
//cout<<"imageIndex: "<< imageNumber << endl;
|
//cout<<"imageIndex: "<< imageNumber << endl;
|
||||||
@ -186,7 +186,8 @@ Mat Puzzle::resultImage( vector<LogEntry>& log){
|
|||||||
copyMakeBorder(img,img,200,200,200,200,BORDER_CONSTANT,Scalar(255,255,255));
|
copyMakeBorder(img,img,200,200,200,200,BORDER_CONSTANT,Scalar(255,255,255));
|
||||||
Mat invert = Mat::ones(img.size(), CV_8UC3); // invert for rotation to work correctly
|
Mat invert = Mat::ones(img.size(), CV_8UC3); // invert for rotation to work correctly
|
||||||
bitwise_not ( img, invert );
|
bitwise_not ( img, invert );
|
||||||
if (it.myCoor.col == 12 && it.myCoor.row == 0)
|
|
||||||
|
if (it.myCoor.col == 35 && it.myCoor.row == 5)
|
||||||
{
|
{
|
||||||
//imshow("img",img);
|
//imshow("img",img);
|
||||||
//waitKey(0);
|
//waitKey(0);
|
||||||
|
@ -44,7 +44,6 @@ void createNextLogElement(vector<LogEntry>& log, Puzzle& puzzleMat)
|
|||||||
log.emplace_back(LogEntry(coor(0, 0)));
|
log.emplace_back(LogEntry(coor(0, 0)));
|
||||||
log.back().myCoor = calculateNextCoor(log, puzzleMat);
|
log.back().myCoor = calculateNextCoor(log, puzzleMat);
|
||||||
puzzleMat.dp.DestructionOfSurrounding(log.back().myCoor);//calculate dp from surrounding
|
puzzleMat.dp.DestructionOfSurrounding(log.back().myCoor);//calculate dp from surrounding
|
||||||
cout << "-----------------------" << endl;
|
|
||||||
//get all not set pieces
|
//get all not set pieces
|
||||||
for(auto it:puzzleMat.p_myBox)
|
for(auto it:puzzleMat.p_myBox)
|
||||||
if(!it->set)
|
if(!it->set)
|
||||||
@ -110,16 +109,13 @@ void setsolution(vector<LogEntry>& log, Puzzle& puzzleMat)
|
|||||||
//tell log entry that it is set
|
//tell log entry that it is set
|
||||||
log.back().Set();
|
log.back().Set();
|
||||||
puzzleMat.setConstraints(log.back().myCoor,log.back().PieceCollector.begin()->second);
|
puzzleMat.setConstraints(log.back().myCoor,log.back().PieceCollector.begin()->second);
|
||||||
cout << "set:" << log.back().myCoor.col << "," << log.back().myCoor.row << endl;
|
//cout << "set:" << log.back().myCoor.col << "," << log.back().myCoor.row << endl;
|
||||||
cout << "ID: " << log.back().PieceCollector[0].second->GetPartID() << endl;
|
//cout << "ID: " << log.back().PieceCollector[0].second->GetPartID() << endl;
|
||||||
cout << "log:" << endl;
|
|
||||||
for(auto it:log.back().PieceCollector)
|
|
||||||
cout << std::bitset<8>(it.second->m_a1.getConnections()) << "|" << it.second->GetPartID() << endl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool backtrack(vector<LogEntry>& log, Puzzle& puzzleMat)
|
bool backtrack(vector<LogEntry>& log, Puzzle& puzzleMat)
|
||||||
{
|
{
|
||||||
cout << "backtracking" ;
|
|
||||||
if(log.empty())
|
if(log.empty())
|
||||||
{
|
{
|
||||||
cout << "Puzzle not solveable!" << endl;
|
cout << "Puzzle not solveable!" << endl;
|
||||||
@ -129,38 +125,35 @@ bool backtrack(vector<LogEntry>& log, Puzzle& puzzleMat)
|
|||||||
//if more pieces possible, tset piece as not logged
|
//if more pieces possible, tset piece as not logged
|
||||||
if((log.back().PieceCollector.size())>1)
|
if((log.back().PieceCollector.size())>1)
|
||||||
{
|
{
|
||||||
cout << " next piece" << endl;
|
for(int i=0;i<puzzleMat.p_myBox.size();i++)//unset puzzlepieces
|
||||||
for(int i=0;i<puzzleMat.p_myBox.size();i++)
|
|
||||||
if(puzzleMat.p_myBox[i]->GetPartID()==log.back().PieceCollector.begin()->second->GetPartID())//sets all with partid
|
if(puzzleMat.p_myBox[i]->GetPartID()==log.back().PieceCollector.begin()->second->GetPartID())//sets all with partid
|
||||||
puzzleMat.p_myBox[i]->set=false;
|
puzzleMat.p_myBox[i]->set=false;
|
||||||
|
|
||||||
|
|
||||||
|
//remove similar in log
|
||||||
Part myPart = *log.back().PieceCollector[0].second;//tmpsaves bad part
|
Part myPart = *log.back().PieceCollector[0].second;//tmpsaves bad part
|
||||||
log.back().PieceCollector.erase(log.back().PieceCollector.begin());//removes bad part from log
|
log.back().PieceCollector.erase(log.back().PieceCollector.begin());//removes bad part from log
|
||||||
puzzleMat.removeSimilar(log.back().PieceCollector,myPart); //removes all pieces from log that are similar to bad part
|
puzzleMat.removeSimilar(log.back().PieceCollector,myPart); //removes all pieces from log that are similar to bad part
|
||||||
//TODO remove this when further layers are added!!!
|
//TODO remove this when further layers are added!!!
|
||||||
|
if(log.back().PieceCollector.size()) // this checks if 'removeSimilar' has cleared entire LogElement
|
||||||
|
{
|
||||||
if(log.back().PieceCollector.size()==1)
|
if(log.back().PieceCollector.size()==1)
|
||||||
log.back().decreaseRandomed();
|
log.back().decreaseRandomed();
|
||||||
|
setsolution(log,puzzleMat);
|
||||||
setsolution(log,puzzleMat);
|
return true;
|
||||||
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
//else remove log element and backtrack once more
|
//else remove log element and backtrack once more
|
||||||
else
|
puzzleMat.removeConstrains(log.back().myCoor); //this should remove constraints from all layers
|
||||||
{
|
if((log.back().PieceCollector.size())) //unset all
|
||||||
cout << " no more pieces" << endl;
|
for(int i=0;i<puzzleMat.p_myBox.size();i++)
|
||||||
puzzleMat.removeConstrains(log.back().myCoor); //this should remove constraints from all layers
|
if(puzzleMat.p_myBox[i]->GetPartID()==log.back().PieceCollector.begin()->second->GetPartID())//sets all with partid
|
||||||
if((log.back().PieceCollector.size()))
|
puzzleMat.p_myBox[i]->set=false;
|
||||||
for(int i=0;i<puzzleMat.p_myBox.size();i++)
|
|
||||||
if(puzzleMat.p_myBox[i]->GetPartID()==log.back().PieceCollector.begin()->second->GetPartID())//sets all with partid
|
log.pop_back();
|
||||||
puzzleMat.p_myBox[i]->set=false;
|
if(!backtrack(log,puzzleMat))
|
||||||
log.pop_back();
|
return false;
|
||||||
if(!backtrack(log,puzzleMat))
|
return true;
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -44,6 +44,7 @@ public:
|
|||||||
createBox(); createp_box();
|
createBox(); createp_box();
|
||||||
if(!dp.PreProcessing({cols,rows}, nullptr)) return false;
|
if(!dp.PreProcessing({cols,rows}, nullptr)) return false;
|
||||||
if(!a1.PreProcessing({cols,rows}, &p_myBox)) return false;
|
if(!a1.PreProcessing({cols,rows}, &p_myBox)) return false;
|
||||||
|
if(!a3.PreProcessing({cols,rows}, &p_myBox)) return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -17,13 +17,14 @@ int main()
|
|||||||
|
|
||||||
//puzzleMat.createRandomBox();
|
//puzzleMat.createRandomBox();
|
||||||
|
|
||||||
cout << "Solving Puzzle now...";
|
cout << "Solving Puzzle now..." << flush;
|
||||||
while(next(log, puzzleMat));
|
while(next(log, puzzleMat));
|
||||||
|
|
||||||
cout << "Done!" << endl;
|
cout << "Done!" << endl;
|
||||||
|
cout << "Printing Puzzle now..." <<flush;
|
||||||
cout << log.size() << endl;
|
|
||||||
puzzleMat.resultImage(log);
|
puzzleMat.resultImage(log);
|
||||||
|
|
||||||
|
|
||||||
puzzleMat.printPuzzle();
|
puzzleMat.printPuzzle();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user