Где ошибка в моем алгоритме спиральной матрицы? Размер матрицы = ввод N^2

Итак, я создаю спиральную матрицу с помощью С#.

Спиральный массив представляет собой квадратное расположение первых N ^ 2 натуральных чисел, где числа последовательно увеличиваются по мере того, как вы идете по краям массива по спирали внутрь.

Например:

введите здесь описание изображения

Я должен сделать это с помощью алгоритма, однако мои окончательные результаты выглядят так:

введите здесь описание изображениявведите здесь описание изображения

Мой код ниже:

    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();
    }
}

}

Любая помощь высоко ценится!


person MattGarnett    schedule 07.08.2014    source источник
comment
Начните с 0, а не с 1, чтобы исправить очевидное отклонение по одному. Другие числа (20, 21, 22) в выводе кажутся неуместными из-за неправильной ширины/зажатия справа, что перезаписывает предыдущие значения и оставляет некоторые незаполненные пробелы в конце.   -  person user2864740    schedule 07.08.2014


Ответы (2)


В вашей логике принятия решения о том, когда делать поворот и сколько шагов нужно сделать, есть ошибка, и она более сложна, чем необходимо. Лучший способ принять решение о том, когда поворачивать, — это проверить саму матрицу. Предварительно заполните матрицу -1, затем начните заполнять ее в верхнем левом углу. Когда увидите -1, продолжайте движение прямо; если вы достигли одного из концов матрицы или в следующей позиции есть -1, то сделайте поворот. Это делает ваши переменные stepPosition и stepCount ненужными и немного сокращает ваш код.

Еще один полезный прием — поворот направо: вместо того, чтобы сохранять направление как одну переменную, сохраните две переменные «дельта» — dx и dy.

if (positionX < 0 || positionX == n || positionY < 0 || positionY == N || matrix[positionX][positionY] != -1) {
    int temp = dy;
    dy = dx;
    dx = -temp;
}
positionX += dx;
positionY += dy;
person Sergey Kalinichenko    schedule 07.08.2014
comment
Просто посмотрите ноль, могут возникнуть проблемы. Как и в примере, верхний левый угол равен нулю. - person hk6279; 07.08.2014
comment
@ hk6279 Понятно - я не заметил пример, глядя на ошибки в середине вывода OP. Я отредактировал ответ, чтобы вместо этого использовать -1. Спасибо! - person Sergey Kalinichenko; 07.08.2014
comment
Спасибо, ребята, я ценю помощь, но проблема была с моим алгоритмом, а не с моим методом. Мои ошибки, возможно, не прояснили для вас вопрос, поэтому я прошу прощения за это. Мое рабочее решение находится в этом посте как ответ, который вы можете посмотреть. - person MattGarnett; 08.08.2014

Я решил эту проблему.

Возникла проблема с моим алгоритмом. Числовой шаблон для размера последовательной строки при заполнении матрицы снаружи: N, N-1, N-1, N-2, N-2, N-3, N-3... и т. д. .

Например, в спиральной матрице размером N 4 шаблон выглядит следующим образом:

4 справа. 3 вниз. осталось 3. 2 вверх. 2 справа. 1 вниз. 1 осталось.

Я изначально думал, что шаблон начался:

3 справа. 3 вниз. осталось 3.

Я забыл включить еще один элемент движения, в результате чего алгоритм не работал правильно.

Как только я изменил свои условные операторы на следующий код, он позволил получить правильный вывод. Чтобы уточнить, я должен начинать с 1 в моем 0 элементе массива. Извиняюсь за путаницу.

Код ниже:

            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;
                    }

                }

В результате получается гораздо более простой способ, чем проверка нуля и поворот на основе этого правила, поскольку оно абсолютно безошибочно.

Пример результатов ниже:

введите здесь описание изображениявведите здесь описание изображения

person MattGarnett    schedule 08.08.2014