C # write code sharing for jigsaw puzzles (bottom)

Source: Internet
Author: User
Tags integer division
This article is mainly for everyone to introduce the C # puzzle game code under the next chapter, with a certain reference value, interested in small partners can refer to

Preface: In C # puzzle game Coding Programming C # Implementation of the "jigsaw puzzle" (on), upload the code of each module, and in this article will be detailed analysis of the principle, so that the reader easier to understand and learn, the program has many problems, welcome points, the common learning and growth!

Body:

Jigsaw puzzle is a very classic game, basic everyone knows his gameplay, his start, run, end. So, how do we get started when we want to do puzzles? The answer is: from the reality, to describe the requirements (as far as possible to describe as a document), when we have a comprehensive demand, we can provide a reliable strategy, so in the code to achieve, and eventually become a work!

(a) Demand: (this need to write more scrawled, for the vast number of small white custom, according to the most common people's thinking, according to the process of participating in the game)

1. Picture: We play jigsaw puzzles at least have a picture

2. Cutting: The puzzle is not a graph, we need to cut a whole image into a n*n small image

3. Upset: N*n the small picture, but make sure you can restore it back by playing the rules.

4. Judging: The success of the puzzle

5. Interaction: Which interaction method do we use, here I choose mouse click

6. Display the full thumbnail image of the original picture

The above is the basic function, the following is the extension function

7. Record steps: How many steps are required to complete the recording

8. Change Picture: A picture play for a long time we can change a change ah haha

9. Select difficulty: Too simple? No! 3*3 got the 5*5,5*5. There are 9*9, roommates challenge the highest difficulty more than 3,000 steps, distressed my mouse tat

(ii) Analysis:

With the need, we can analyze how to implement it (mapping real-world requirements to computers), including:

1. Development platform: Choose C # language here

1). Storage: which includes what do we need to save? What structure do we use to save? We can see that there are some resources that need to be stored

Image: Using Image object storage

Unit (a collection of sub-images after the original picture has been cut): custom struct struct Node, which includes the image object used to store the small picture of the unit, and the number that is stored with the shaping (after cutting, each small unit is numbered, to check whether the game is completed).

Each unit (image collection after cutting the original picture): Using two-dimensional array (like puzzles, Gobang, consumer music, repeatedly see, Tetris and other plane dot matrix game can be used to store, why?) Because it looks like it! ) to store

Difficulty: Using custom enumeration types (simple and common and difficult) storage

Steps: Shaping variable int num storage

With storage, we can think about the partitioning of the modules (the right logical partitioning is extended, and the communication becomes clearer ), and the specific algorithms involved in each module are implemented.

First, the module of the program is divided into four units:

  Logic type:

1. Puzzle class: Used to describe puzzles

2. Configuration classes: Storing configuration variables

  Interactive type:

3. Game Menu window: Make menu options

4. Game Run window: The main interface of the game

1. The game menu allows you to manipulate the configuration, such as difficulty or picture.

2. The Run window can access and get the game configuration and make use of its corresponding construction puzzle object.

3. The user interacts through the running window, indirectly causes the puzzle object to call the moving method, obtains the pattern method

  Look at the code of the classmate, I think the most problematic place, unreasonable place is the difficulty of the enumeration type written in the puzzle class, should be written in the configuration class, or separate into classes, the reader to change their own


public enum Diff//game Difficulty {  simple,//simple  ordinary,//common  difficulty//Difficulty}

We can assume that the configuration class is like data storage, and the puzzle class as a logical processing, menu and run window as performance for interaction, I admit that this design is not very reasonable, but when the problem is not large enough, too much consideration of design, will make the program become bloated? I think there must be a degree, specific is how much, I do not know, but I feel, for this program, to achieve good, addicted to design (routine type), sometimes outweigh the cost. (Personal immature small point of view)

(c) Code implementation:

Description: This block focuses on the specific implementation of the Puzzle (jigsaw) class and the game run class and the entity communication:

How to construct a puzzle:

1. Assign values:

Public Puzzle (Image img,int Width, Diff gamedif)

Puzzle picture, Width (explanation: Square side length, unit is pixel, name ambiguous, sorry), game difficulty

The difficulty of the game determines the extent of your segmentation, the degree of segmentation, determine the size of the array you store, such as simple corresponding to 3 rows and 3 columns, ordinary corresponding 5 rows 5 columns, difficulty corresponds to 9 rows 9 columns


Switch (THIS._GAMEDIF)  {case  diff.simple://Simple then the cell array is saved as a two-dimensional array of 3*3 this   . N = 3;   Node=new node[3,3];   break;  Case Diff.ordinary://General is 5*5 this   . N = 5;   node = new node[5, 5];   break;  Case Diff.difficulty://The difficulty is 9*9 this   . N = 9;   node = new node[9, 9];   break;  }

2. Split image


The split picture forms each unit saved in an array of  int Count = 0;  for (int x = 0; x < this. N x + +)  {for  (int y = 0; y < this. N y++)  {   node[x, y]. IMG = Captureimage (this._img, this. Width/this. N, this. Width/this. N, X * (this. Width/this. N), Y * (this. Width/this. N));   Node[x, Y]. Num = Count;   count++;  }  }

In fact, the process of assigning a unit array, a two-dimensional array is traversed using a double for loop, and then the ordinal assignment number Node[x,y]. Num;

Then to Node[x,y]. IMG, that is, the small image assignment of the unit, the method of assignment is the C # image of the class library, write a method, using this method, the large map to the corresponding size of the small map to intercept, and save in Node[x,y]. IMG;

What is width/n? Is the side length divided by the number of rows, that is, the interval is the side length of each unit! And then the starting coordinate (x, y) starts with saying, after a few units, my position,

That is: (x, y)=(cell edge length * distance from the starting X axis of the unit number, the cell edge length * distance from the starting point of the y-axis unit number);

In this kind of problem, I hope that the reader can draw more drawings, and then naturally understand;

Public Image captureimage (image fromimage, int width, int height, int spaceX, int spaceY)

Main logic: Using the DrawImage method:


Create a new diagram bitmap  Bitmap Bitmap = new Bitmap (width, height);//create drawing area Graphics graphic = graphics.fromimage (BITMAP);// The corresponding area of the captured original is written to the plot area  graphic. DrawImage (fromimage, 0, 0, New Rectangle (x, y, width, height), graphicsunit.pixel);//Generate a new image from the plot area  image saveimage = image . Fromhbitmap (bitmap. Gethbitmap ());

After the split, we have to do a special deal, because we know that there is always a place is white, right? We default to the last position, i.e. node[n-1,n-1];

is to write to a white picture, and then all around the edges are painted red, has been found, a significant number of other units before I also painted the sideline, but it is white, but also in order to get a distinction between the ornamental of the puzzle. The code is not introduced.

3. Upset the Picture:

In fact, the two-dimensional array is scrambled, we can take some sort of scrambling method, but please note! Not every kind of disruption can be restored!

So how is it possible? The method is very simple to understand, is to let our computer before the start, the complete sequence of units in accordance with the rules provided by the way of walking the rule, a large number of walking! In other words, this method must be able to walk back!

First understand, the specific disruption method, explained in the following.

Move Method:

The movement of the square in the puzzle game is actually the exchange of two adjacent units, and in these two units, there must be a white unit (i.e. the node[n-1,n-1] unit mentioned above, his number is n*n-1, it is recommended that you write a calculation)

So our judgment condition is that if you move a block, he's up and down in four directions, and once there is a white unit, the n*n-1 unit, it's swapped. This is the basic logic, but does not include the constraints, when our array reaches the boundary, we can not access the cross-border data, such as when the cell is node[0,0], you can not access the data above and to the right, because node[-1,0] node[0,-1] will be out of bounds, An exception occurred

Move succeeded, return true

Move failed, return false


<summary>///mobile coordinates (x, y) puzzle unit///</summary>/<param name= "x" > Puzzle unit x Coordinate </param>//<param Name= "Y" > Puzzle unit y-coordinate </param> public bool Move (int x,int y) {  //messagebox.show ("" + node[2, 2]. Num);  if (x + 1! = N && node[x + 1, y]. Num = = N * N-1)  {  Swap (new Point (x + 1, y), New Point (x, y));  return true;  }  if (y + 1! = N && node[x, y + 1]. Num = = N * N-1)  {  Swap (new Point (x, y + 1), new Point (x, y));  return true;  }    if (x-1! =-1 && node[x-1, y]. Num = = N * N-1)  {  Swap (new Point (X-1, y), New Point (x, y))  ; return true;  }   if (y-1! =-1 && node[x, y-1]. Num = = N * N-1)  {  Swap (new Point (X, y-1), New Point (x, y))  ; return true;  }  return false;   }

Exchange method (Swap):

Swap the position of the two elements in the array, which should not be accessed outside the class and set to private permissions


Swap two cells private void Swap (point A, point B) {  node temp = new Node ();  temp = this.node[a.x, a.y];  this.node[a.x, a.y] = this.node[b.x, b.y];  this.node[b.x, b.y] = temp; }

Scrambling method:

Mentioned earlier, in fact, is to let the computer help disorderly walk a pass, plainly is a large number of calls to move (int x,int y) method, that is, the white space in the upper and lower left and right four adjacent squares randomly extracted one, and its coordinates to move to move it, the same to cross-border considerations, This kind of operation is a lot of repetition! Code to see for yourself, using random numbers.


<summary>///scrambled puzzles///</summary> public void upset () {  int sum = 100000;  if (this._gamedif = = diff.simple) sum = 10000;  if (this._gamedif = = diff.ordinary) sum = 100000;  Random ran = new random ();  for (int i = 0, x = N-1, y = N-1; i < sum; i++)  {  long tick = DateTime.Now.Ticks;  ran = new Random ((int) (tick & 0xffffffffL) | (int) (tick >> +) |ran. Next ());  Switch (ran. Next (0, 4))  {case   0:   if (x + 1! = N)   {    Move (x + 1, y);    x = x + 1;   }       break;   Case 1:   if (y + 1! = N)   {    Move (x, y + 1);    y = y + 1;   }    break;   Case 2:   if (x-1! =-1)   {    Move (x-1, y);    x = x-1;   }    break;   Case 3:   if (y-1! =-1)   {    Move (x, y-1);    y = y-1;   }   break;  }  } }

Ways to return Pictures:

How did you get a ghost name like that? DisPlay ...

This method is exactly the same as the segmentation method, this method is actually to iterate over the array, and combine it, the combination of methods is very simple, that is, they will be a one by the position of a blank drawing of the same size as the original image! The final submission of the drawing, that is, return an image;


Public Image Display () {  Bitmap Bitmap = new Bitmap (this. Width, this. Width);  Create a   Graphics area Newgra = Graphics.fromimage (bitmap);  for (int x = 0; x < this. N x + +) for  (int y = 0; y < this. N y++)   newgra.drawimage (node[x, y]. IMG, new Point (X * this. Width/this. N, Y * this. Width/this. N));  return bitmap; }

The same is the use of DrawImage method, know how to split, this should be easy to understand, their own calculation, on the paper gestures on the understanding;

Judging method:

This method is easy to understand, is ordered by order! Traverse all the cells if they have a number in the result of a unit

Node[x, Y]. Num is not equal to the serial number of the traversal, then it shows that the unit is not in the original position, that is, the entire picture has not been completed, we can directly return False value false
If all the traversal results are correct, we can assume that the picture has been restored, and that this returns true


public bool Judge () {  int count=0;  for (int x = 0; x < this. N x + +)  {for  (int y = 0; y < this. N y++)  {   if (this.node[x, y]. Num! = count)   return false;   count++;  }  }  return true; }

Game Run window: The window used for interaction when playing games

Here's one way to do this: that is, what should we do when we accept the user's mouse click event?

In fact, this sentence is difficult to understand:

Puzzle. Move (e.x/(puzzle. Width/puzzle. N), E.y/(puzzle. Width/puzzle. N))

Call the Move method, move the block

The horizontal axis is: E. X/(puzzle. Width/puzzle. N
The ordinate axis is: E. Y/(puzzle. Width/puzzle. N

The integer division in our programming is not the same as the division in mathematics! For example, 10/4 math equals 2 or 2 or 2.5, the computer is equal to 2, only take the whole number of parts

Number of rows = line coordinates/square edge length

Number of columns = column coordinates/square edge length

Let's see p1,p2 these two.

P1:40/30*30=1
P2:50/30*30=1

We'll find that in a single cell, regardless of which location you click, this algorithm can be converted to
The same coordinate.

(E.X,E.Y) Click on the coordinates for the mouse click event


private void Picturebox1_mouseclick (object sender, MouseEventArgs e) {  if (puzzle. Move (e.x/(puzzle. Width/puzzle. N), E.y/(puzzle. Width/puzzle. N))  {  num++;  pictureBox1.Image = puzzle. Display ();  if (puzzle. Judge ())  {    if (MessageBox.Show ("Congratulations Pass", "whether to play again", messageboxbuttons.okcancel) = = DialogResult.OK)   {   Num = 0;   Puzzle. Upset ();   pictureBox1.Image = puzzle. Display ();      }   else   {   Num = 0;   Closefather ();   This. Close ();}}  }  Numlabel.text = Num.tostring (); }

Good, then the general logic, the program most need to think about the algorithm has been finished, there is not much to understand the place, welcome to Exchange ~ Ah da ~

Added a little bit of music history score

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.