Dragon4ik
Member
- Joined
- Oct 24, 2020
- Messages
- 16
- Programming Experience
- Beginner
I have a task to write a programm, which slice the image into the equal rectangle puzzles . Then the program must solve this puzzle without knowing the way it was sliced. I wrote the code, but it works time after time and i can't understand what problem is. Thank you in advance for any help.
P.S. This alghoritm place every piece in the top left corner and try to find the best neighbor piece through the least difference between border pixels
P.S. This alghoritm place every piece in the top left corner and try to find the best neighbor piece through the least difference between border pixels
Autocompleting puzzles:
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
namespace Puzzles
{
struct PixelColor
{
public byte Blue;
public byte Green;
public byte Red;
public byte Alpha;
}
class Alghoritm
{
private List<int> GetNumbers(List<BitmapSource> list)
{
List<int> numbers = new List<int>();
for (int i = 1; i <= list.Count; i++)
{
if (list.Count % i == 0)
{
numbers.Add(i);
}
}
return numbers;
}
private PixelColor[,] GetPixels(BitmapSource source)
{
if (source.Format != PixelFormats.Bgra32)
source = new FormatConvertedBitmap(source, PixelFormats.Bgra32, null, 0);
int width = source.PixelWidth;
int height = source.PixelHeight;
PixelColor[,] result = new PixelColor[width, height];
source.CopyPixels(result, width * 4, 0, true);
return result;
}
private double GetDifference(PixelColor first, PixelColor second)
{
int dr = Math.Abs(first.Red - second.Red);
int dg = Math.Abs(first.Green - second.Green);
int db = Math.Abs(first.Blue - second.Blue);
int da = Math.Abs(first.Alpha - second.Alpha);
return Math.Sqrt(dr * dr + dg * dg + db * db );
}
private double GetRightDifference(PixelColor[,] left, PixelColor[,] right)
{
double rightDifference = 0;
try
{
if (left.Length != right.Length)
throw new Exception("Щось пішло не так");
for (int i = 0; i < left.GetLength(0); i++)
{
rightDifference += GetDifference(left[i, left.GetLength(1) - 1], right[i, 0]);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
return rightDifference;
}
private double GetBottomDifference(PixelColor[,] up, PixelColor[,] down)
{
double bottomDifference = 0;
try
{
if (up.Length != down.Length)
throw new Exception("Щось пішло не так і тут");
for (int i = 0; i < up.GetLength(1); i++)
{
bottomDifference += GetDifference(up[up.GetLength(0) - 1, i], down[0, i]);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
return bottomDifference;
}
private BitmapSource GetRightImage(BitmapSource first, List<BitmapSource> list, ref double totalDifference)
{
double min = Int32.MaxValue;
PixelColor[,] left = GetPixels(first);
BitmapSource next = null;
for (int i = 0; i < list.Count; i++)
{
PixelColor[,] right = GetPixels(list[i]);
double value = GetRightDifference(left, right);
if (min > value)
{
next = list[i];
min = value;
}
}
totalDifference += min;
return next;
}
private BitmapSource GetBottomImage(BitmapSource first, List<BitmapSource> list, ref double totalDifference)
{
double min = Int32.MaxValue;
PixelColor[,] up = GetPixels(first);
BitmapSource next = null;
for (int i = 0; i < list.Count; i++)
{
PixelColor[,] down = GetPixels(list[i]);
double value = GetBottomDifference(up, down);
if (min > value)
{
next = list[i];
min = value;
}
}
totalDifference += min;
return next;
}
private double GetBestCurrentVariant(List<BitmapSource> list, int row,int col, ref BitmapSource[,] bestChoice)
{
BitmapSource bestPiece;
double min = Int32.MaxValue;
for (int j = 0; j < list.Count; j++) //перебір всіх елементів колекції для даної розстановки
{
double total = 0; //показує повну різницю всього малюнку
BitmapSource[,] elements = new BitmapSource[row, col]; //отриманий результат
List<BitmapSource> cash = new List<BitmapSource>(list); //колекція доступних елементів
elements[0, 0] = cash[j];
cash.RemoveAt(j);
for (int irow = 0; irow < row - 1; irow++) // перебір по рядкам
{
for (int icol = 0; icol < col - 1; icol++) //перебір по стовпцям
{
//for(int icas = 0; icas<cash.Count;icas++) //перебір по доступним елементам
//{
//}
bestPiece = GetRightImage(elements[irow, icol], cash, ref total);//отримуємо найкращий правий фрагмент
elements[irow, icol + 1] = bestPiece;//додаємо отриманий фрагмент до результату
cash.Remove(bestPiece);//видаляємо недоступний елемент
}
bestPiece = GetBottomImage(elements[irow, 0], cash, ref total);//отримуємо найкращий нижній фрагмент
elements[irow+1, 0] = bestPiece;//додаємо отриманий фрагмент до результату
cash.Remove(bestPiece);//видаляємо недоступний елемент
}
//додаємо фрагменти до останнього рядка
for (int icol = 0; icol < col - 1; icol++) //перебір по стовпцям
{
bestPiece = GetRightImage(elements[row - 1, icol], cash, ref total);//отримуємо найкращий правий фрагмент
elements[row - 1, icol + 1] = bestPiece;//додаємо отриманий фрагмент до результату
cash.Remove(bestPiece);//видаляємо недоступний елемент
}
if (min > total)
{
bestChoice = (BitmapSource[,])elements.Clone();
min = total;
}
}
return min;
}
public BitmapSource[,] GetBestPuzzleImage(List<BitmapImage> list)
{
List<BitmapSource> bmp = new List<BitmapSource>();
for(int i=0;i<list.Count;i++)
{
BitmapSource temp = (BitmapSource)list[i];
bmp.Add(temp);
}
List<int> numbers = new List<int>(GetNumbers(bmp));
BitmapSource[,] bestChoice = null;
double min = Int32.MaxValue; //значення найменшої різниці малюнку(для визначення найкращого результату)
for (int i = 0; i < numbers.Count;i++)
{
int row = numbers[i]; //кількість рядків
int col = list.Count / row; //кількість стовпців
BitmapSource[,] possibleChoice = new BitmapSource[row,col];
double value = GetBestCurrentVariant(bmp, row, col, ref possibleChoice);
if (min > value)
{
bestChoice = (BitmapSource[,])possibleChoice.Clone();
min = value;
}
}
return bestChoice;
}
}
}