WPF Learning Series games-select a picture to make a 9-cell puzzle and a wpf palace Tile

Source: Internet
Author: User

WPF Learning Series games-select a picture to make a 9-cell puzzle and a wpf palace Tile

I want to learn about a puzzle project today.

The goal is to input an image, divide it into nine parts, remove one, and click the mouse to complete the puzzle.

The source file structure is simple.

Step 1: Create a project

There is nothing to say in this step. Creating a new project is the same as the source file structure.

Step 2: page layout (. xaml file)

View the source file

The control has three DockPanel Grid buttons and three Grid columns and three rows. DockPannel does not know how to use it for the moment, so I am not busy with it. Then I reported an error.

In the original xaml format, buttons are not surrounded by double tags and cannot be identified. Therefore, an error is returned. So you just need to add a label package. if you add the DockPanel label, it will be the same as the source file. Here, to understand the usage of DockPane, you still need to use Grid to see if an error will be reported later. My current code is

Step 2: Compile the function of selecting images by clicking the button

This post was written last week, but after half done, I went to study c ++. After studying c ++ for a while, I suddenly understood why I had to program. I am not interested in computer programming, not for 0 and 1. I learned computers and programs just to do things. So I will go back and continue to write this series. I will not grasp the details of the subsequent content. I just want to understand some things. It doesn't matter if you can't remember it. Check it again when you need it. After the project is made, I want to make it as I like, instead of just like the source code.

Click the button to do two things

1. In the pop-up dialog box, select an image.

2. Select an image and generate a puzzle.

The following code selects an image:

OpenFileDialog ofd = new OpenFileDialog (); // Microsoft. win32.ofd. filter = "Image Files (*. BMP ;*. JPG ;*. GIF ;*. PNG) | *. BMP ;*. JPG ;*. GIF ;*. PNG "; // supported image format ofd. multiselect = false; // multiple if (ofd. showDialog ()! = True) // ofd. showDialog () may have three values: true flase null {return;} try {BitmapImage image = new BitmapImage (new Uri (ofd. fileName, UriKind. relativeOrAbsolute); Image img = new Image {Source = image}; // write the code for creating the puzzle here} catch {MessageBox. show ("Couldnt load the image file" + ofd. fileName );}Select Image

 

  

The first step of generating a puzzle is to divide the image into nine blocks and fill the image in the corresponding area.

This is a bit complicated. The source code uses many methods. I am used to splitting it and writing it as a class.

/// <Summary> /// tile generation class /// input an image to generate a 9*9 image set /// </summary> public class PuzzleForImage {BitmapImage _ image; // original image public List <Rectangle> initialUnallocatedParts = new List <Rectangle> (); // The set of puzzles to return /// <summary> /// input the original image when the object is created /// </summary> /// <param name = "image"> </param> public PuzzleForImage (BitmapImage image) {_ image = image;
// Create a puzzle }}

Step 1: Write a sub-method to draw a rectangle Based on the start point and image width and height. Call it nine times to get the entire set of puzzles.

Step 2: Randomly arrange eight of the nine puzzles. Select the first eight.

Step 3: Add a blank tile.

Step 4: Add a move event

In this step, the source code is complete. You have added a successful code to execute the click event in the box.

Below is my code.

/// <Summary> /// MainWindow. interaction logic of xaml // </summary> public partial class MainWindow: Window {public MainWindow () {InitializeComponent ();} /// <summary> // select an image to generate a puzzle /// </summary> private void BtnPickImg_Click (object sender, RoutedEventArgs e) {OpenFileDialog ofd = new OpenFileDialog (); ofd. filter = "Image Files (*. BMP ;*. JPG ;*. GIF ;*. PNG) | *. BMP ;*. JPG ;*. GIF ;*. PNG "; // supported image format ofd. multiselect = f Alse; // you are not allowed to select if (ofd. ShowDialog ()! = True) {return;} try {BitmapImage image = new BitmapImage (new Uri (ofd. fileName, UriKind. relativeOrAbsolute); // Image img = new Image {Source = image}; PuzzleForImage puzzle = new PuzzleForImage (image); // create a puzzle. setGrid (GridImg);} catch {MessageBox. show ("this file is not supported:" + ofd. fileName );}}}MainWindow. xaml. cs /// <summary> /// tile generation class /// input an image to generate a 9*9 image set /// </summary> public class PuzzleForImage {BitmapImage _ image; // original image List <Rectangle> initialUnallocatedParts = new List <Rectangle> (); // the public List of the puzzle set to be returned <Rectangle> allocatedParts = new List <Rectangle> (); // int [] map = new int [9] of the disrupted image; // determine whether the game map is successful /// <summary> // specify the original image when creating the object /// </summary> /// <param name = "image"> </param> p Ublic PuzzleForImage (BitmapImage image) {_ image = image; CreatePuzzleForImage ();} /// <summary> /// place the puzzle in the UI /// </summary> /// <param name = "GridImg"> </param> public void SetGrid (grid GridImg) {GridImg. children. clear (); GridImg. height = _ image. height/_ image. width * GridImg. width; int index = 0; for (int I = 0; I <3; I ++) {for (int j = 0; j <3; j ++) {allocatedParts [index]. setValue (Grid. ro WProperty, I); allocatedParts [index]. setValue (Grid. columnProperty, j); GridImg. children. add (allocatedParts [index]); index ++ ;}}/// <summary> // create a puzzle /// </summary> private void CreatePuzzleForImage () {# initialize initialUnallocatedParts in the region jigsaw puzzle container. clear (); allocatedParts. clear (); # endregion # double width = 1.0/3 of the first eight puzzles created by region; // The width of each puzzle, double height = 1.0/3; // height of each puzzle // row0 CreateImagePart (0, 0, width, height); CreateImagePart (width, 0, width, height); CreateImagePart (2 * width, 0, width, height); // row1 CreateImagePart (0, height, width, height); CreateImagePart (width, height, width, height); CreateImagePart (2 * width, height, width, height); // row2 CreateImagePart (0, 2 * height, width, height); CreateImagePart (width, 2 * height, width, height); // CreateImagePart (2 * width, 2 * Height, width, height); # endregion // randomly arrange RandomizeTiles (); // create a white square CreateBlankRect ();} /// <summary> /// draw a rectangle /// create an image painting brush and use the X/Y/width/height parameter to create the image. only part of the image is displayed. This is the ImageBrush used to fill the rectangle, add to the internal table of the unallocated rectangle /// </summary> /// <param name = "x"> start point x </param> /// <param name = "y"> Start Point y </param> /// <param name = "width"> width </param> /// <param name = "height"> height </ param> private void CreateImagePart (double x, double y, double width, double height) {# region defines the brush ImageBrush ib = new ImageBrush (); // ib. stretch = Stretch. uniformToFill; // cropping is adapted to the screen. This will cause the image to not stretch to ib. imageSource = _ image; ib. Viewbox = new Rect (x, y, width, height); ib. viewboxUnits = BrushMappingMode. relativeToBoundingBox; // set the width and height of ib by percentage. tileMode = TileMode. none; // percentage should not result in the case that the image is smaller than the value to be split # endregion # region defines the Rectangle rectPart = new Rectangle (); rectPart. fill = ib; rectPart. margin = new Thickness (0); rectPart. horizontalAlignment = HorizontalAlignment. stretch; rectPart. verticalAlignment = verticalignment. stretch; RectPart. mouseDown + = new MouseButtonEventHandler (rectPart_MouseDown); // Add a rectangular Click Event # endregion initialUnallocatedParts. add (rectPart); // Add the rectangle to the puzzle set} // <summary> // disrupt the picture /// </summary> private void RandomizeTiles () {Random rand = new Random (); for (int I = 0; I <8; I ++) {int index = 0; // if (initialUnallocatedParts. count> 1) // {// index = (int) (rand. nextDouble () * initialUnallocatedParts. C Ount); //} index = (int) (rand. nextDouble () * initialUnallocatedParts. count); while (initialUnallocatedParts [index] = null) {index = (int) (rand. nextDouble () * initialUnallocatedParts. count);} allocatedParts. add (initialUnallocatedParts [index]); // initialUnallocatedParts. removeAt (index); // remove the image initialUnallocatedParts [index] = null; map [I] = index; // Add map }}/// <summary> /// create a blank rectangle /// </sum Mary> private void CreateBlankRect () {Rectangle rectPart = new Rectangle (); rectPart. fill = new SolidColorBrush (Colors. white); rectPart. margin = new Thickness (0); rectPart. horizontalAlignment = HorizontalAlignment. stretch; rectPart. verticalAlignment = verticalignment. stretch; allocatedParts. add (rectPart); map [8] = 8 ;}/// <summary> // click the event in the box /// </summary> private void rectPart_MouseDown (obje Ct sender, MouseButtonEventArgs e) {// get the source Rectangle, and the blank Rectangle // NOTE: Blank Rectangle never moves, its always the last Rectangle // in the allocatedParts List, but it gets re-allocated to // different Gri Row/Column Rectangle rectCurrent = sender as Rectangle; // Rectangle rectBlank = allocatedParts [allocatedParts. count-1]; // default square // get the position of the white block and default square int currentTileRow = (Int) rectCurrent. getValue (Grid. rowProperty); int currentTileCol = (int) rectCurrent. getValue (Grid. columnProperty); int currentblkrow = (int) rectBlank. getValue (Grid. rowProperty); int currentblkcol = (int) rectBlank. getValue (Grid. columnProperty); // List of four locations that can be moved by the white block <PossiblePositions> posibilities = new List <PossiblePositions> (); posibilities. add (new PossiblePositions {Row = currentBlankRow-1, C Ol = currentBlankCol}); posibilities. add (new PossiblePositions {Row = currentBlankRow + 1, Col = currentBlankCol}); posibilities. add (new PossiblePositions {Row = currentBlankRow, Col = currentBlankCol-1}); posibilities. add (new PossiblePositions {Row = currentBlankRow, Col = currentBlankCol + 1}); // check whether the square can be clicked (the white block can be moved to the position of the current square) bool validMove = false; foreach (PossiblePositions position in po Sibilities) if (currentTileRow = position. row & currentTileCol = position. col) validMove = true; // only allow valid move if (validMove) {// Switch location rectCurrent. setValue (Grid. rowProperty, currentBlankRow); rectCurrent. setValue (Grid. columnProperty, currentblkcol); rectBlank. setValue (Grid. rowProperty, currentTileRow); rectBlank. setValue (Grid. columnProperty, currentTileCol); // update map int indexCur = CurrentTileRow * 3 + currentTileCol; int indexBlank = currentblkrow * 3 + currentblkcol; int temp = map [indexCur]; map [indexCur] = map [indexBlank]; map [indexBlank] = temp; // determines if (isSuccess () {MessageBox. show ("successful, great! ");}}} /// <Summary> /// verify whether the game is successful /// </summary> /// <returns> </returns> private bool isSuccess () {for (int I = 0; I <9; I ++) {if (map [I]! = I) {return false ;}} return true ;}} /// <summary> /// Simply struct to store Row/Column data // </summary> struct PossiblePositions {public int Row {get; set ;} public int Col {get; set ;}}PuzzleForImage. cs

Running effect:

Other problems:

1. Now the image will be stretched. I didn't expect a good solution for the moment.

2. Random puzzles

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.