C# Tutorial – Make a Image Sliding Puzzle Game in Windows Forms

Hi in this tutorial we will be making a Sliding Image Puzzle game. This game will be made using only windows form, C# and .NET in visual studio. We will not be adding third party framework to make this application or use any games engine such as Unity or GODOT. All of the components will be pure windows form and C# programming. Sliding image puzzle is a game I have been meaning to do in windows form because its one of the most requested and well-known game. Its not difficult to do but finding the right resources to do it is another question. For this tutorial we made sure to including all of the source codes and refactored the code to make it easier for beginner programmers to follow.

For this game, it won’t use pre-made sliced images instead it will use the browse feature to import an image to the application, crop the image to match the tiles in the game and then load them to a picture box.  There is also a win condition in the code when you matched all of the pictures. At any time, you can load another image and play it through. In the code you will see we have a shuffle feature where it will shuffle the images when it loads so you can get right into solving the puzzle.

Lesson Objectives –

  1. Create a simple slider image puzzle game using windows form, C# and visual studio
  2. Work with a menu strip in windows form
  3. Create and Load picture boxes from the C# script in a 3×3 grid
  4. Assign tags to to each picture box so they can be identified as the game is played
  5. Use labels to show the current position of the tiles and the win position of the tiles
  6. Load the image into a bitmap and resize to match the game conditions
  7. Crop the image to match each 130px tiles in the game.
  8. Use multiple lists to save the images and the image positions into
  9. Use custom functions and events in the game
  10. Assign the win condition when all of the tiles are matched
  11. Have fun

Video Tutorial –

 

Source Code –

namespace Image_Slider_Puzzle_Game_WIn_Forms_MOO_ICT
{
    public partial class Form1 : Form
    {


        // made by MOO ICT 2023
        // for educational purpose only


        List<PictureBox> pictureboxlist = new List<PictureBox>();
        List<Bitmap> images = new List<Bitmap>();
        List<string> locations = new List<string>();
        List<string> current_locations = new List<string>();

        string win_position;
        string current_position;

        Bitmap MainBitmap;

        public Form1()
        {
            InitializeComponent();
        }

        private void OpenFileEvent(object sender, EventArgs e)
        {
            if (pictureboxlist != null)
            {

                foreach (PictureBox pics in pictureboxlist.ToList())
                {
                    this.Controls.Remove(pics);
                }

                pictureboxlist.Clear();
                images.Clear();
                locations.Clear();
                current_locations.Clear();
                win_position = string.Empty;
                current_position = string.Empty;
                label2.Text = string.Empty;
            }

            OpenFileDialog open = new OpenFileDialog();
            open.Filter = "Image Files Only | *.jpg; *.jpeg; *.gif; *.png";
            if (open.ShowDialog() == DialogResult.OK)
            {
                MainBitmap = new Bitmap(open.FileName);
                CreatePictureBoxes();
                AddImages();
            }


        }

        private void CreatePictureBoxes()
        {
            for (int i = 0; i < 9; i++)
            {

                PictureBox temp_pic = new PictureBox();
                temp_pic.Size = new Size(130, 130);
                temp_pic.Tag = i.ToString();
                temp_pic.Click += OnPicClick;
                pictureboxlist.Add(temp_pic);
                locations.Add(temp_pic.Tag.ToString()); 
            }
        }

        private void OnPicClick(object? sender, EventArgs e)
        {
            PictureBox pictureBox = (PictureBox)sender;
            PictureBox emptyBox = pictureboxlist.Find(x => x.Tag == "0");

            Point pic1 = new Point(pictureBox.Location.X, pictureBox.Location.Y);
            Point pic2 = new Point(emptyBox.Location.X, emptyBox.Location.Y);

            var index1 = this.Controls.IndexOf(pictureBox);
            var index2 = this.Controls.IndexOf(emptyBox);

            if (pictureBox.Right == emptyBox.Left && pictureBox.Location.Y == emptyBox.Location.Y
                || pictureBox.Left == emptyBox.Right && pictureBox.Location.Y == emptyBox.Location.Y
                || pictureBox.Top == emptyBox.Bottom && pictureBox.Location.X == emptyBox.Location.X
                || pictureBox.Bottom == emptyBox.Top && pictureBox.Location.X == emptyBox.Location.X
                )
            {
                pictureBox.Location = pic2;
                emptyBox.Location = pic1;

                this.Controls.SetChildIndex(pictureBox, index2);
                this.Controls.SetChildIndex(emptyBox, index1);
            }

            label2.Text = "";
            current_locations.Clear();
            CheckGame();
        }

        private void CropImage(Bitmap main_bitmap, int height, int width)
        {
            int x, y;
            x = 0;
            y = 0;

            for (int blocks = 0; blocks < 9; blocks++)
            {
                Bitmap cropped_image = new Bitmap(height, width);

                for (int i = 0; i < height; i++)
                {
                    for (int j = 0; j < width; j++)
                    {
                        cropped_image.SetPixel(i, j, main_bitmap.GetPixel((i + x), (j + y)));
                    }
                }
                images.Add(cropped_image);
                x += 130;
                if (x == 390)
                {
                    x = 0;
                    y += 130;
                }
            }
        }

        private void AddImages()
        {
            Bitmap tempBitmap = new Bitmap(MainBitmap, new Size(390, 390));

            CropImage(tempBitmap, 130, 130);

            for (int i = 1; i < pictureboxlist.Count; i++)
            {
                pictureboxlist[i].BackgroundImage = (Image)images[i];
            }

            PlacePictureBoxesToForm();
        }

        private void PlacePictureBoxesToForm()
        {
            var shuffleImages = pictureboxlist.OrderBy(a => Guid.NewGuid()).ToList();
            pictureboxlist = shuffleImages;
            int x = 200;
            int y = 25;

            for (int i = 0; i < pictureboxlist.Count; i++)
            {
                pictureboxlist[i].BackColor = Color.Gold;

                if (i == 3 || i == 6)
                {
                    y += 130;
                    x = 200;
                }

                pictureboxlist[i].BorderStyle = BorderStyle.FixedSingle;
                pictureboxlist[i].Location = new Point(x, y);

                this.Controls.Add(pictureboxlist[i]);
                x += 130;

                win_position += locations[i];
            }


        }

        private void CheckGame()
        {
            foreach (Control x  in this.Controls)
            {
                if (x is PictureBox)
                {
                    current_locations.Add(x.Tag.ToString());
                }
            }

            current_position = string.Join("", current_locations);
            label1.Text = win_position;
            label2.Text = current_position;

            if (win_position == current_position)
            {
                label2.Text = "Matched !!!!";
            }
        }


    }
}

 




Comments are closed.