Click here to Skip to main content
15,891,740 members
Articles / Programming Languages / C#

Using Single Dimensional Array to Represent Two Dimensional Data

Rate me:
Please Sign up or sign in to vote.
4.50/5 (9 votes)
30 Aug 2013CPOL2 min read 62.5K   560   11  
Shows how to treat a single dimensional array for both single and two dimensional data at the same time
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace nPuzzel
{
    /// <summary>
    /// Interaction logic for PuzzelControl.xaml
    /// </summary>
    public partial class PuzzelControl : UserControl
    {
        int moves;
        int dimension;
        BitmapSource image;
        List<PuzzelPiece> buttons = new List<PuzzelPiece>();
        bool gameFinished;

        public PuzzelControl(int dimension, string imagePath)
        {
            InitializeComponent();
            this.dimension = dimension;
            image = new BitmapImage(new Uri(imagePath));
            mainCanvas.Width = image.Width;
            mainCanvas.Height = image.Height;
            CreateButtons();
            RandomiseButtons(buttons.Count - 1);
        }

        public void UseImage(bool value)
        {
            foreach (var button in buttons)
            {
                button.UseImage = value;
            }
        }

        void RandomiseButtons(int emptyIndex)
        {
            Random rand = new Random();
            for (int i = 0; i < 1000; i++)
            {
                try
                {
                    Direction randomDirection = (Direction)rand.Next(4);
                    emptyIndex = MoveButton(emptyIndex, randomDirection);
                }
                catch { }
            }
        }

        void CreateButtons()
        {
            int vSize = (int)(image.Height / dimension);
            int hSize = (int)(image.Width / dimension);
            for (int i = 0; i < dimension * dimension; i++)
            {
                Int32Rect srcRect = new Int32Rect((int)((i % dimension) * hSize), (int)((i / dimension) * vSize), hSize, vSize);
                CroppedBitmap bm = new CroppedBitmap(image, srcRect);
                ImageBrush brush = new ImageBrush(bm);
                PuzzelPiece b = new PuzzelPiece(i, brush);
                buttons.Add(b);
                b.Width = hSize;
                b.Height = vSize;
                b.Location = new Point((i % dimension) * hSize, (i / dimension) * vSize);
                b.Click += new RoutedEventHandler(b_Click);
                mainCanvas.Children.Add(b);
                b.Style = (Style)Application.Current.FindResource("PuzzelButtonStyle");
            }
            buttons.Last().MakeEmpty();
        }

        void b_Click(object sender, RoutedEventArgs e)
        {
            if (!gameFinished)
            {
                int index = buttons.IndexOf(sender as PuzzelPiece);
                int emptyIndex = GetEmptyNeighbour(index);
                if (emptyIndex >= 0)
                {
                    SwapButtons(buttons[index], buttons[emptyIndex]);
                    moves++;
                    if (GameWon())
                    {
                        MessageBox.Show("You won the game after " + moves + " moves");
                        foreach (var b in buttons)
                        {
                            b.UseImage = true;
                        }
                        gameFinished = true;
                    }
                }
            }
        }

        void SwapButtons(PuzzelPiece p1, PuzzelPiece p2)
        {
            int index = p1.PieceIndex;
            ImageBrush b = p1.PieceBrush;
            bool enabled = p1.IsEnabled;

            p1.PieceIndex = p2.PieceIndex;
            p2.PieceIndex = index;

            p1.IsEnabled = p2.IsEnabled;
            p2.IsEnabled = enabled;

            p1.PieceBrush = p2.PieceBrush;
            p2.PieceBrush = b;
            p1.SetBackground();
            p2.SetBackground();
        }

        bool GameWon()
        {
            for (int i = 0; i < dimension * dimension - 1; i++)
            {
                if (buttons[i].PieceIndex != i)
                    return false;
            }
            return true;
        }

        int GetEmptyNeighbour(int index)
        {
            int currentRow = index / dimension;
            int currentCol = index % dimension;

            if (currentCol - 1 >= 0) //left
            {
                if (!buttons[index - 1].IsEnabled)
                {
                    return index - 1;
                }
            }
            if (currentCol + 1 < dimension) //rirht
            {
                if (!buttons[index + 1].IsEnabled)
                {
                    return index + 1;
                }
            }
            if (currentRow - 1 >= 0) //top
            {
                if (!buttons[index - dimension].IsEnabled)
                {
                    return index - dimension;
                }
            }
            if (currentRow + 1 < dimension)//bottom
            {
                if (!buttons[index + dimension].IsEnabled)
                {
                    return index + dimension;
                }
            }
            return -1;
        }

        enum Direction { Back, Forward, Up, Down }

        int MoveButton(int emptyButtonIndex, Direction direction)
        {
            if (buttons[emptyButtonIndex].IsEnabled)
            {
                throw new Exception("The button to move is not empty!");
            }
            int newIndex = emptyButtonIndex;
            switch (direction)
            {
                case Direction.Back:
                    if (emptyButtonIndex % dimension > 0)
                    {
                        SwapButtons(buttons[emptyButtonIndex], buttons[emptyButtonIndex - 1]);
                        newIndex = emptyButtonIndex - 1;
                    }
                    break;
                case Direction.Forward:
                    if (emptyButtonIndex % dimension < dimension - 1)
                    {
                        SwapButtons(buttons[emptyButtonIndex], buttons[emptyButtonIndex + 1]);
                        newIndex = emptyButtonIndex + 1;
                    }
                    break;
                case Direction.Up:
                    if (emptyButtonIndex / dimension > 0)
                    {
                        SwapButtons(buttons[emptyButtonIndex], buttons[emptyButtonIndex - dimension]);
                        newIndex = emptyButtonIndex - dimension;
                    }
                    break;
                case Direction.Down:
                    if (emptyButtonIndex / dimension < dimension - 1)
                    {
                        SwapButtons(buttons[emptyButtonIndex], buttons[emptyButtonIndex + dimension]);
                        newIndex = emptyButtonIndex + dimension;
                    }
                    break;
            }
            return newIndex;
        }
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Technical Lead https://mathiversity.com
Unknown
I am a full-stack developer. My skills include JavaScript, C#/.Net, MS Azure cloud etc. I love to work on complex programming tasks requiring deep analysis, planning and use of efficient algorithms and data structures.

Comments and Discussions