برای ساده تر شدن کار مشخصات هر تکه رو توی یه کلاس نگه میدارم ..
internal class PazzelImage
{
/// <summary>
/// Mahale asli in Tekke
/// </summary>
public int MainLocation { get; private set; }
/// <summary>
/// Mahali ke alan in Tekke tu une
/// </summary>
public int CurrentLocation { get; set; }
/// <summary>
/// Akse marbut be in Tekke
/// </summary>
public Image Image { get; set; }
public PazzelImage(int mainLocation, Image img)
{
this.MainLocation = mainLocation;
this.Image = img;
this.CurrentLocation = this.MainLocation;
}
عکس مربوطه رو لود میکنیم ...
private Image _pazzelImage;
public Pazzel()
{
InitializeComponent();
_pazzelImage = Image.FromFile("pazzel.jpg");
}
من از یه عکس 400*400 استفاده کرم و اونو به 16 قسمت 100*100 تقسیم کردم ...
private List<PazzelImage> _imageParts;
private void InitPazzel()
{
int pos = 1;
Size s = new Size(100, 100);//andazeye har block 100*100
for (int y = 0; y < 4; y++)
{
for (int x = 0; x < 4; x++)
{
Point loc = new Point(x * 100, y * 100);
Rectangle rect = new Rectangle(loc, s);
PazzelImage img = new PazzelImage(pos, _pazzelImage.cropImage(rect));
_imageParts.Add(img);
_drawBounds.Add(pos, rect);
pos++;
}
}
_imageParts.RemoveAt(15);
_empty = 16;
Randomize();
}
مستطیل های ساخته شده رو به همراه شماره موقعیتشون ( از 1 تا 16 ) توی یه لیست نگه میدارم ...
private Dictionary<int, Rectangle> _drawBounds;
حالا موقعیت قرار گیری این مستطیل ها رو به صورت رندوم به هم میریزیم ...
private void Randomize()
{
List<int> ints = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
Random rand = new Random();
foreach (var item in _imageParts)
{
int index = rand.Next(0, ints.Count);
item.CurrentLocation = ints[index];
ints.RemoveAt(index);
}
}
توی اونت Paint عکس هارو توی یه پنل Draw میکنیم ...
private void pnlDraw_Paint(object sender, PaintEventArgs e)
{
if (_imageParts != null && _imageParts.Count > 0)
{
foreach (PazzelImage item in _imageParts)
{
e.Graphics.DrawImage(item.Image, _drawBounds[item.CurrentLocation]);
}
}
}
از اینجا به بعد قسمت اصلیش شروع میشه ... با کلیک روی هر کدوم از این تکه ها ...
1 - مختصات محل کلیک
Point mPOs = this.PointToClient(Cursor.Position);
2 - مختصات مستطیل ها رو که توی _drawBounds ذخیره کرده بودیم چک میکنیم ببینیم محل کلیک توی کدوم یک از این مستطیل هاست ...
private KeyValuePair<int, Rectangle> GetClickedRectangle(Point pos)
{
foreach (var item in _drawBounds)
{
if ( (pos.X > item.Value.X && pos.X < item.Value.Right) &&
(pos.Y > item.Value.Y && pos.Y < item.Value.Bottom))
{
return item;
}
}
return new KeyValuePair<int, Rectangle>(16, Rectangle.Empty);
}
3 - با توجه به مستطیل انتخاب شده object عکس اون محل رو پیدا مسکنیم ...
PazzelImage part = _imageParts.First(n => n.CurrentLocation == selectedRectangle.Key);
4 - محل خونه خالی رو توی یه متغیر نگه میداریم ...
private int _empty;
5 - محل مستطیل دریافت شده رو چک میکنیم که خونه خالی نباش ...
if (selectedRectangle.Key != _empty)
6 - اگه محل مستطیل دریافت شده خونه خالی نیست چک میکنیم که در همسایگی خونه خالی هست یا نه ...
private bool IsInContanct(Rectangle rect)
{
Rectangle empty = _drawBounds[_empty];
//az samte balayi ba mahale khali dar tamas ast
if ((rect.Top - 5 < empty.Bottom) && (rect.Bottom > empty.Bottom) && (rect.X == empty.X))
return true;
//az samte payini ba mahale khali dar tamas ast
if ((rect.Bottom + 5 > empty.Top) && (rect.Top < empty.Top) && (rect.X == empty.X))
return true;
//az samte chap ba mahale khali dar tamas ast
if ((rect.Left - 5 < empty.Right) && (rect.Right > empty.Right) && (rect.Y == empty.Y))
return true;
//az samte rast ba mahale khali dar tamas ast
if ((rect.Right + 5 > empty.Left) && (rect.Left < empty.Left) && (rect.Y == empty.Y))
return true;
return false;
}
7 - اگر جواب مثبت بود محل این 2 مستطیل رو عوض میکنیم و پنل رو RePaint ...
if (IsInContanct(selectedRectangle.Value))
{
PazzelImage part = _imageParts.First(n => n.CurrentLocation == selectedRectangle.Key);
int temp = _empty;
_empty = part.CurrentLocation;
part.CurrentLocation = temp;
pnlDraw.Invalidate();
}
8 - و آخر سر چک میکنیم که آیا همه خونه ها سر جای خودشون هستن یا نه ...
private bool IsFinish()
{
foreach (var item in _imageParts)
{
if (item.MainLocation != item.CurrentLocation)
return false;
}
return true;
}
و اینجوریا ....