Tile Game To Demonstrate Array Indexing & Sorting

TilerCd

TilesMainForm TilesCompletePuzzle

Do you remember those puzzle games you see in small shops, novelty stores, etc..? You know the ones where you have to slide the pieces around in a frame to get the picture correct? This game resembles one of those. That and it demonstrates how to index and sort an array. This game has the option of increasing the difficulty by making the board have more pieces. Don’t worry you can also view the completed puzzle to help out. Kind of like doing a regular puzzle at home. You can look at the box. You can also select a new puzzle and a new one will be randomly selected for you. I’ll be adding / changing the code to this game as time goes on. On keep an eye on the source.


MainForm Class


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Windows.Forms;

namespace Tiler
{
    public partial class MainForm : Form
    {
        private GameSettings myGameSettings = new GameSettings();       //Global instance for the game settings.
        private PictureBox _firstPictureBox = null;                     //The first selected picture box.
        private Tiles _myTiles = null;                                  //The tiles object.
        private PictureBox[,] _imageGrid = null;                        //The picturebox 2 dimensional array.

        public MainForm()
        {
            //Load a random image.
            LoadRandomImage();

            //Create the tiles.
            _myTiles = new Tiles(myGameSettings.NumberOfRows, myGameSettings.NumberOfColumns, myGameSettings.Image);

            //Creating the image grid.
            createImageGrid();

            InitializeComponent();
        }

        private void LoadRandomImage()
        {
            Random random = new Random();
            int randomIndex = random.Next(myGameSettings.Pictures.Length);

            //Getting the name of the randomly selected picture.
            string picture = myGameSettings.Pictures[randomIndex];
            myGameSettings.Image = new Bitmap(picture);
        }

        private void createImageGrid()
        {
            //Allocate a two dimensional array for our grid.
            _imageGrid = new PictureBox[myGameSettings.NumberOfRows, myGameSettings.NumberOfColumns];

            //Create each PictureBox control in our array.
            int tileCount = 0;

            for (int rows = 0; rows < myGameSettings.NumberOfRows; rows++)
            {
                for (int columns = 0; columns < myGameSettings.NumberOfColumns; columns++)
                {
                    //Create and assign the new picturebox.
                    PictureBox pictureBox = new PictureBox()
                    {
                        Image = _myTiles[tileCount].Face,
                        BackColor = Color.Black,
                        BorderStyle = BorderStyle.FixedSingle,
                        Cursor = Cursors.Hand,
                        Tag = tileCount
                    };
                    _imageGrid[rows, columns] = pictureBox;

                    //Increment the tile counter.
                    tileCount++;

                    //Adding a single event handler for all of the picture box mouseup events.
                    _imageGrid[rows, columns].MouseUp += new MouseEventHandler(imageMouseUpHandler);
                }
            }
        }

        void imageMouseUpHandler(object sender, MouseEventArgs e)
        {
            // Get the PictureBox control we're responding to
            PictureBox pictureBox = sender as PictureBox;

            if (_firstPictureBox == null)
            {
                // First pick
                _firstPictureBox = pictureBox;

                // Draw border to indicate the user selected tile
                pictureBox.CreateGraphics().DrawRectangle(
                    new Pen(Color.Red, 3.0F), 0, 0, pictureBox.ClientRectangle.Width - 1, pictureBox.ClientRectangle.Height - 1);
            }
            else
            {
                // Getting array indices
                int firstIndex = (int)_firstPictureBox.Tag;
                int currentIndex = (int)pictureBox.Tag;

                // Swap positions, reset images
                _myTiles.swap(firstIndex, currentIndex);
                _firstPictureBox.Image = _myTiles[firstIndex].Face;
                pictureBox.Image = _myTiles[currentIndex].Face;
                _firstPictureBox = null;

                if (_myTiles.isSolved())
                {
                    DialogResult result = MessageBox.Show("Puzzle Has Been Solved!\n OK - Refresh The Puzzle.\n Cancel - View The Puzzle.", 
                        this.Text, MessageBoxButtons.OKCancel);

                    if (result == DialogResult.OK)
                    {
                        //Resetting the tiles.
                        _myTiles.reset();

                        //Display the tiles.
                        TilesReset();
                    }
                }
            }

        }

        private void MainForm_Shown(object sender, EventArgs e)
        {
            RefreshDisplay();
        }

        //Method used to refresh the graphics display.
        private void RefreshDisplay()
        {
            //Getting and setting the form dimensions.
            myGameSettings.FormHeight = this.Height;
            myGameSettings.FormWidth = this.Width;

            //Getting and setting the inner panel dimensions.
            myGameSettings.PanelHeight = mainPanel.ClientRectangle.Height;
            myGameSettings.PanelWidth = mainPanel.ClientRectangle.Width;

            //Setting the image dimensions.
            myGameSettings.setImageDimensions();

            //Adjusting the form dimensions to allow space for all of the image.
            this.Height = myGameSettings.FormHeight - myGameSettings.PanelHeight + myGameSettings.ImageHeight;
            this.Width = myGameSettings.FormWidth - myGameSettings.PanelWidth + myGameSettings.ImageWidth;

            //Get the height and the width for each picturebox using the inside height and width of the panel control.
            myGameSettings.PictureBoxWidth = mainPanel.ClientRectangle.Width / myGameSettings.NumberOfColumns;
            myGameSettings.PictureBoxHeight = mainPanel.ClientRectangle.Height / myGameSettings.NumberOfRows;

            //Iterate thru and set the location and dimensions of each picturebox control.
            for (int rows = 0; rows < myGameSettings.NumberOfRows; rows++)
            {
                for (int columns = 0; columns < myGameSettings.NumberOfColumns; columns++)
                {
                    _imageGrid[rows, columns].SetBounds(myGameSettings.PictureBoxWidth * columns, myGameSettings.PictureBoxHeight * rows,
                        myGameSettings.PictureBoxWidth, myGameSettings.PictureBoxHeight);
                }
            }

            //Add the picture controls to the panel controls collection.
            if (mainPanel.Controls.Count == 0)
            {
                for (int rows = 0; rows < myGameSettings.NumberOfRows; rows++)
                {
                    for (int columns = 0; columns < myGameSettings.NumberOfColumns; columns++)
                    {
                        mainPanel.Controls.Add(_imageGrid[rows, columns]);
                    }
                }
            }
        }

        private void showPuzzlePictureToolStripMenuItem_Click(object sender, EventArgs e)
        {
            PuzzlePictureForm showPuzzlePicture = new PuzzlePictureForm(myGameSettings.Image);
            showPuzzlePicture.Show();
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void resetToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //Resetting the tiles.
            _myTiles.reset();

            //Display the tiles.
            TilesReset();
        }

        private void TilesReset()
        {
            int tileCount = 0;

            for (int rows = 0; rows < myGameSettings.NumberOfRows; rows++)
            {
                for (int columns = 0; columns < myGameSettings.NumberOfColumns; columns++)
                {
                    _imageGrid[rows, columns].Image = _myTiles[tileCount++].Face;
                }
            }
        }

        //method used to clear arrays and reset the display.
        private void DisplayReset()
        {
            //Clearing the current panel.
            mainPanel.Controls.Clear();

            //Clearing the previous tiles array.
            _myTiles = null;

            //Clearing the image grid array.
            _imageGrid = null;
        }

        //Method used when the user wants to see a new randomly selected puzzle.
        private void newPuzzleToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //Clearing the display.
            DisplayReset();

            //Finding another random image.
            LoadRandomImage();

            _myTiles = new Tiles(myGameSettings.NumberOfRows, myGameSettings.NumberOfColumns, myGameSettings.Image);

            createImageGrid();

            RefreshDisplay();
        }

        private void changeTo2x2GridToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //Clearing the display.
            DisplayReset();

            //Change the number of rows and columns.
            myGameSettings.NumberOfRows = 2;
            myGameSettings.NumberOfColumns = 2;

            //Creating the new tiles.
            _myTiles = new Tiles(myGameSettings.NumberOfRows, myGameSettings.NumberOfColumns, myGameSettings.Image);

            //Creating the new image grid.
            createImageGrid();

            //Refresh the display
            RefreshDisplay();
        }

        private void changeTo3x3GridToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //Clearing the display.
            DisplayReset();

            //Change the number of rows and columns.
            myGameSettings.NumberOfRows = 3;
            myGameSettings.NumberOfColumns = 3;

            //Creating the new tiles.
            _myTiles = new Tiles(myGameSettings.NumberOfRows, myGameSettings.NumberOfColumns, myGameSettings.Image);

            //Creating the new image grid.
            createImageGrid();

            //Refresh the display
            RefreshDisplay();
        }

        private void changeTo4x4GridToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //Clearing the display.
            DisplayReset();

            //Change the number of rows and columns.
            myGameSettings.NumberOfRows = 4;
            myGameSettings.NumberOfColumns = 4;

            //Creating the new tiles.
            _myTiles = new Tiles(myGameSettings.NumberOfRows, myGameSettings.NumberOfColumns, myGameSettings.Image);

            //Creating the new image grid.
            createImageGrid();

            //Refresh the display
            RefreshDisplay();
        }

        private void changeTo8x8GridToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //Clearing the display.
            DisplayReset();

            //Change the number of rows and columns.
            myGameSettings.NumberOfRows = 8;
            myGameSettings.NumberOfColumns = 8;

            //Creating the new tiles.
            _myTiles = new Tiles(myGameSettings.NumberOfRows, myGameSettings.NumberOfColumns, myGameSettings.Image);

            //Creating the new image grid.
            createImageGrid();

            //Refresh the display
            RefreshDisplay();
        }
    }
}


PuzzlePictureForm Class


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace Tiler
{
    public partial class PuzzlePictureForm : Form
    {
        private GameSettings puzzleFormSettings = new GameSettings();
        private PictureBox pictureBox = new PictureBox();

        public PuzzlePictureForm(Bitmap image)
        {
            //Loading the image.
            puzzleFormSettings.Image = image;

            InitializeComponent();

            //Creating a picturebox to load the image.
            pictureBox.Image = puzzleFormSettings.Image;
            pictureBox.Dock = DockStyle.Fill;
            puzzlePicturePanel.Controls.Add(pictureBox); 
        }

        private void PuzzlePictureForm_Shown(object sender, EventArgs e)
        {
            //Getting and setting the form dimensions.
            puzzleFormSettings.FormHeight = this.Height;
            puzzleFormSettings.FormWidth = this.Width;

            //Getting and setting the inner panel dimensions.
            puzzleFormSettings.PanelHeight = puzzlePicturePanel.ClientRectangle.Height;
            puzzleFormSettings.PanelWidth = puzzlePicturePanel.ClientRectangle.Width;

            //Setting the image dimensions.
            puzzleFormSettings.setImageDimensions();

            //Adjusting the form dimensions to show all of the image.
            this.Height = puzzleFormSettings.FormHeight - puzzleFormSettings.PanelHeight + puzzleFormSettings.ImageHeight;
            this.Width = puzzleFormSettings.FormWidth - puzzleFormSettings.PanelWidth + puzzleFormSettings.ImageWidth;
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
        }
    }
}


Tile Class


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

namespace Tiler
{
    public class Tile : IComparable
    {
        public string SortValue;        //Sortable value field for scrambling.
        public Bitmap Face;             //Tile image field.

        public int CompareTo(object sortObject)
        {
            Tile tile = null;

            //Test and cast the parameter to Tile.
            if (sortObject != null)
                tile = sortObject as Tile;

            //Perform a recursive sort or throw an exception.
            if (tile != null)
                return this.SortValue.CompareTo(tile.SortValue);
            else
                throw new ArgumentException("Object is not a Tile.");
        }
    }
}


Tiles Class


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

namespace Tiler
{
    public class Tiles
    {
        private int _numberOfTiles;
        private Tile[] _tilesScrambled;
        private Tile[] _tilesSorted;

        private int _numberOfRows;
        private int _numberOfColumns;
        private Bitmap _image;

        public Bitmap Image
        {
            get { return _image; }
        }

        //Constructor
        public Tiles(int numberOfRows, int numberOfColumns, Bitmap image)
        {
            //Setting the class variables.
            _numberOfRows = numberOfRows;
            _numberOfColumns = numberOfColumns;
            _numberOfTiles = numberOfRows * numberOfColumns;
            _image = image;

            //Create the tile arrays.
            _tilesScrambled = new Tile[_numberOfTiles];
            _tilesSorted = new Tile[_numberOfTiles];

            //Reset the tiles.
            reset();
        }

        //Indexer
        public Tile this[int index]
        {
            get
            {
                return _tilesScrambled[index];
            }
            set
            {
                _tilesScrambled[index] = value;
            }
        }

        public void reset()
        {
            //Clear out all of the old tiles.
            Array.Clear(_tilesSorted, 0, _tilesSorted.Length);
            Array.Clear(_tilesScrambled, 0, _tilesScrambled.Length);

            //Calculating the image chunks.
            int heightChunk = _image.Height / _numberOfRows;
            int widthChunk = _image.Width / _numberOfColumns;

            //Generating the new tiles in sorted order and adding a GUID for later scrambling.
            int imageCount = 0;
            for (int rows = 0; rows < _numberOfRows; rows++)
            {
                for (int columns = 0; columns = 0
                    && firstIndex = 0 && secondIndex < _tilesScrambled.Length)
            {
                Tile holdTile = _tilesScrambled[secondIndex];
                _tilesScrambled[secondIndex] = _tilesScrambled[firstIndex];
                _tilesScrambled[firstIndex] = holdTile;
            }
        }

        public bool isSolved()
        {
            bool result = true;

            // Compare sorted and scrambled, and if they match, solved
            for (int i = 0; i < _numberOfColumns; i++)
            {
                if (_tilesScrambled[i].SortValue != _tilesSorted[i].SortValue)
                {
                    result = false;
                    break;
                }
            }

            return result;
        }

    }
}


GameSettings Class


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

namespace Tiler
{
    class GameSettings
    {
        private Bitmap _image;
        private int _formHeight;
        private int _formWidth;
        private int _panelHeight;
        private int _panelWidth;
        private int _imageHeight;
        private int _imageWidth;
        private int _pictureBoxWidth;
        private int _pictureBoxHeight;
        private int _numberOfRows = 3;
        private int _numberOfColumns = 3;
        private string[] _pictures = { "WaterLilies-400x400.jpg", "Sunset-400x400.jpg", "Winter-400x400.jpg", "Technology.jpg",
                                     "Clouds.jpg", "Computer.jpg"};

        public Bitmap Image
        {
            get { return _image; }
            set { _image = value; }
        }

        public int FormHeight
        {
            get { return _formHeight; }
            set { _formHeight = value; }
        }

        public int FormWidth
        {
            get { return _formWidth; }
            set { _formWidth = value; }
        }

        public int PanelHeight
        {
            get { return _panelHeight; }
            set { _panelHeight = value; }
        }

        public int PanelWidth
        {
            get { return _panelWidth; }
            set { _panelWidth = value; }
        }

        public int ImageHeight
        {
            get { return _imageHeight; }
        }

        public int ImageWidth
        {
            get { return _imageWidth; }
        }

        public int PictureBoxWidth
        {
            get { return _pictureBoxWidth; }
            set { _pictureBoxWidth = value; }
        }

        public int PictureBoxHeight
        {
            get { return _pictureBoxHeight; }
            set { _pictureBoxHeight = value; }
        }

        public int NumberOfRows
        {
            get { return _numberOfRows; }
            set { _numberOfRows = value; }
        }

        public int NumberOfColumns
        {
            get { return _numberOfColumns; }
            set { _numberOfColumns = value; }
        }

        public string[] Pictures
        {
            get { return _pictures; }
        }

        //Method used to set the image dimensions.
        public void setImageDimensions()
        {
            _imageHeight = _image.Height;
            _imageWidth = _image.Width;
        }
    }
}

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s