Search code examples
c#algorithmmatrixspiral

Where's the mistake in my Spiral Matrix algorithm? Size of matrix = input N^2


So I'm creating a spiral matrix using C#.

A spiral array is a square arrangement of the first N^2 natural numbers, where the numbers increase sequentially as you go around the edges of the array spiralling inwards.

For example:

enter image description here

I'm supposed to do this using an algorithm however my final results look like this:

enter image description here enter image description here

My code is below:

    private static void FillMatrix (int[ , ] matrix, int n)
    {
        int positionX = 0;
        int positionY = 0;

        int direction = 0; // The initial direction is "right"
        int stepsCount = n - 1; // stepsCount decrements after 3/2/2/2/2...
        int stepPosition = 0; // 0 steps already performed
        int counter = 1; // counter increments after every turn

        for (int i = 1; i < n * n; i++)
        {
            matrix[positionY, positionX] = i;

            //moving logic:

            if (stepPosition < stepsCount)
            {
                stepPosition++;
            }
            else
            {
                counter++;
                stepPosition = 1;

                if (counter <= 3)
                {
                    direction = (direction + 1) % 4;
                }

                else if (counter % 2 != 0 && counter >= 5 || counter == 4)
                {
                    stepsCount = stepsCount - 1;
                    direction = (direction + 1) % 4;
                }
            }


            // Move to the next cell in the current direction
            switch (direction)
            {
                case 0:
                    // right
                    positionX++;
                    break;
                case 1:
                    // down
                    positionY++;
                    break;
                case 2:
                    // left
                    positionX--;
                    break;
                case 3:
                    // up
                    positionY--;
                    break;
            }
        }
    }

    private static void PrintMatrix (int[ , ] matrix, int n)
    {
        for (int i = 0; i < n; i++)
        {
            for (int j = 0; j < n; j++)
            {
                Console.Write("{0,3}", matrix[i, j]);
            }
            Console.WriteLine();
        }
    }

    static void Main(string[] args)
    {
        int n;

        Console.WriteLine("Please enter N: ");
        bool checkN = int.TryParse(Console.ReadLine(), out n);

        if (checkN)
        {
            int[,] spiralMatrix = new int[n,n];

            FillMatrix(spiralMatrix, n);

            PrintMatrix(spiralMatrix, n);
        }

        Console.ReadKey();
    }
}

}

Any help much appreciated!


Solution

  • I've solved this problem.

    There was an issue with my algorithm. The number pattern for the size of sequential line when filling in a matrix from the outside in is N, N-1, N-1, N-2, N-2, N-3, N-3... and so on.

    For example in a spiral matrix of N size 4 the pattern goes like this:

    4 right. 3 down. 3 left. 2 up. 2 right. 1 down. 1 left.

    I originally thought the pattern started:

    3 right. 3 down. 3 left.

    I forgot to include the one more element of movement resulting in a algorithm that wouldn't fill out correctly.

    Once I changed my conditional statements to the following code it allowed for the correct output. To clarify I am supposed to be starting from 1 in my 0 element of the array. Apologies for the confusion.

    Code below:

                int positionX = 0;
                int positionY = 0;
    
                int direction = 0; // The initial direction is "right"
                int stepsCount = n - 1; // stepsCount decrements after 1/2/2/2/2... turns
                int stepPosition = 1; // 1 steps already performed
                int counter = 0; // counter increments after every change in direction
    
                for (int i = 1; i < n * n + 1; i++)
                {
                    matrix[positionY, positionX] = i;
    
                    //moving logic:
    
                    if (stepPosition <= stepsCount)
                    {
                        stepPosition++;
                    }
                    else
                    {
                        counter++;
                        stepPosition = 1;
    
                        if (counter % 2 != 0)
                        {
                            stepsCount = stepsCount - 1;
                            direction = (direction + 1) % 4;
                        }
                        else if (counter % 2 == 0)
                        {
                            direction = (direction + 1) % 4;
                        }
    
                    }
    

    The result is a much simpler way than checking for zero and turning based on that rule as it is absolutely infallable.

    Example results below:

    enter image description here enter image description here