Writing very dynamic Puzzle

I wrote this puzzle while ago and thought it’s time to share it, as when i searched the internet back the time od developing this i did not find any similar puzzle that expose this flexibility.


To have this flexibility on hand we have to do couple of things first of all generate buttons which will be the peaceis of the puzzle and then devuide the image and paint the peaices with it.


So first of all generating the number of the the peacies which can be non-symetric like 2 x 5 or 7 x 13 as you want.







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
 private void GenerateButtons(int rows, int columns)
{
//Resize panel
panel.Height = columns * 70;
panel.Width = rows * 70;

//double loop to create buttoms and in the way they fill in coulmns and rows.
for (int r = 0; r <= columns - 1; r++)//row variable
{
for (int c = 0; c <= rows - 1; c++)//coulmn variable
{
Button temp = new Button();
temp.Height = temp.Width = 70;//set square dimentions for the buttom
temp.Location = new Point(c * temp.Width, r * temp.Height);
temp.Click += new EventHandler(ImagesOnClick); //Attach the handler for the click event.
temp.FlatStyle = FlatStyle.Popup;
ALAllImages.Add(temp);
ALImagesLocations.Add(temp.Location); //Add location on every buttons on specific array
}
}
foreach (Button b in ALAllImages)
{
panel.Controls.Add(b); //Add buttons to the panel on the form.
}
//Assign the location of the last left cornerd buttom to the empty space.
FreeSquare.X = panel.Controls[panel.Controls.Count - 1].Location.X;
FreeSquare.Y = panel.Controls[panel.Controls.Count - 1].Location.Y;
//Preserve the last left cornerd buttom for movment
panel.Controls.RemoveAt(panel.Controls.Count - 1);
ALAllImages.RemoveAt(ALAllImages.Count - 1);
}


Now we will read from the user desierd image and paint every peace of the puzzle we have.







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
 private void PaintPuzzle(Bitmap UserInput, int rows, int columns)
{
//calculate area to pick color pixels
ArrayList SmallPics = new ArrayList(rows * columns);
int hp = 0;//lenth from the eadge of the panel
int vp = 0;
int x = 70;//dimention of the image
int y = 70;
for (int i = 0; i < (rows * columns); i++)
{
Bitmap b = new Bitmap(x, y);

for (int n = 0; n < x; n++)
{
for (int m = 0; m < y; m++) //creating small images 70*70 for every button.
{
int np = n + hp;
int mp = m + vp;
Color c = UserInput.GetPixel(np, mp);
b.SetPixel(n, m, c);
}
}

SmallPics.Add(b);

hp += 70; // for the movment of coloring.
if (hp >= rows * 70)
{ hp = 0; vp += 70; }
}

for (int i = 0; i < ALAllImages.Count; i++)
{
((Button)ALAllImages[i]).Image = (Image)SmallPics[i];//bind the small images to each button
}
}


After accomplish these two steps we are now have a bunch of buttoms with the picture painted on them, now we have to shuffle things a little.







1
2
3
4
5
6
7
8
9
10
11
12
13
private void ShuffleImages()
{
if (ALAllImages == null)
return;
Random factory = new Random();//create randome object
Button crazyButton = new Button();
int c = int.Parse(numericUpDown1.Value.ToString())*int.Parse(numericUpDown2.Value.ToString());
for (int i = 0; i < 25*c; i++)//100 movment at most to be done.
{
crazyButton = (Button)ALAllImages[factory.Next(ALAllImages.Count)];//choose random button
OneStep(crazyButton);//move the random button
}
}


All what left is to move the buttons to the right free direction.


This code will move the clicked button single step (depend on the button/peace dimentions) towrd the direction of the free square .







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
private void OneStep(Button ClickedButton)
{
//Make sure that the clicked buttom is near free space horizontally or vertically
if (FreeSquare.Y == ClickedButton.Location.Y || FreeSquare.X == ClickedButton.Location.X)
{
//create a holder for the empty point which will change…
Point freesquareHolder = new Point();
freesquareHolder = ClickedButton.Location;

//tow possible group of movments up&down , right&left
//implementation for the movment vertically
if (FreeSquare.X == ClickedButton.Location.X)
{
foreach (Button b in panel.Controls)
{
if (((
b.Location.Y >= ClickedButton.Location.Y)
&& (b.Location.Y < FreeSquare.Y)
&& (b.Location.X == FreeSquare.X))
|| ((b.Location.Y <= ClickedButton.Location.Y)
&& (b.Location.Y > FreeSquare.Y)
&& (b.Location.X == FreeSquare.X)))
{
if (ClickedButton.Location.Y > FreeSquare.Y
&& ClickedButton.Location.X == FreeSquare.X)
{
b.Location = new Point(b.Location.X, b.Location.Y - b.Size.Height);// move up
}
if (ClickedButton.Location.Y < FreeSquare.Y
&& ClickedButton.Location.X == FreeSquare.X)
{
b.Location = new Point(b.Location.X, b.Location.Y + b.Size.Height); //move down
}
}
}
}

//implementation for horizontal movment
foreach (Button b in panel.Controls)
{
if (((
b.Location.X >= ClickedButton.Location.X)
&& (b.Location.X < FreeSquare.X)
&& (b.Location.Y == FreeSquare.Y))
|| ((b.Location.X <= ClickedButton.Location.X)
&& (b.Location.X > FreeSquare.X)
&& (b.Location.Y == FreeSquare.Y)))
{
if (ClickedButton.Location.X < FreeSquare.X
&& ClickedButton.Location.Y == FreeSquare.Y)
{
b.Location = new Point(b.Location.X + b.Size.Width, b.Location.Y);//move right
}
if (ClickedButton.Location.X > FreeSquare.X
&& ClickedButton.Location.Y == FreeSquare.Y)
{
b.Location = new Point(b.Location.X - b.Size.Width, b.Location.Y);//move left
}
}

}

FreeSquare = freesquareHolder;//return the original coordinate for the empty space
}
}


Full Code (VS 2005)

kick it on DotNetKicks.com

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>