JavaRush /Blog Java /Random-MS /Mencipta "Magic Square" di Jawa

Mencipta "Magic Square" di Jawa

Diterbitkan dalam kumpulan
Petak ajaib tertib n ialah matriks segi empat sama bersaiz nxn, terdiri daripada nombor 1, 2, 3, ..., n^2 supaya jumlah bagi setiap lajur, setiap baris dan setiap dua pepenjuru besar adalah sama. . Perkara pertama yang saya ingat ialah Sudoku :) Mencipta "Magic Square" di Jawa - 1pautan dari Wikipedia , bagi mereka yang tidak faham. Selepas bereksperimen dengan mencipta algoritma pengisian saya sendiri, saya membuat kesimpulan bahawa saya tidak boleh melakukannya tanpa bantuan orang lain. Oleh itu, selepas melalui sedozen pautan, saya melaksanakan 3 algoritma, yang secara keseluruhannya melaksanakan pengisian mana-mana matriks dimensi "n". Pada permulaan kod anda boleh mencari komen mengenai kaedah yang akan digunakan di bawah. Pautan kepada algoritma dan komen lain (berguna?) boleh didapati dalam badan kaedah yang sepadan. Saya di Telegram: @sergey3ts Dan Linkedin, sudah tentu (Tambahkan diri anda, ini penting bagi saya :)
// magicSquareOfOddOrder(int n);       метод для n нечетной размерности (3, 7, 9, и тд)
 // magicSquareOfEvenOddOrder(int n);   метод для n четно-нечетной размерности (n кратно 2 но не крастно 4)
 // magicSquareOfEvenOddOrder(int n);   метод для n четн-четной размерности (n кратно и 2 и 4);
 // magicSquare(int n);                 общий метод, который определяет кратность n и вызывает соотв. метод

 // Вспомогательные методы
 // standardMatrixFillingAscending(n); заполняет матрицу от 1 по возростанию
 // standardMatrixFillingDescending(n); заполняет матрицу от n*n по убыванию

 // Извиняюсь за косяки в codeе (непонятные переменные(возможно(нет(да)))) :)
public class MatrixSolution16 {
    public static void main(String[] args) {
        magicSquare(6);
    }
   public static int [][] magicSquare(int n) {
        if (n % 2 !=0) return magicSquareOfOddOrder(n);             // метод для n нечетной размерности (3, 7, 9, и тд)
        else if (n % 4 != 0) return magicSquareOfEvenOddOrder(n);   // метод для n четно-нечетной размерности (n кратно 2 но не кратно 4)
        return magicSquareOfEvenOddOrder(n);                        // метод для n четн-четной размерности (n кратно и 2 и 4);
    }
   private static int[][] magicSquareOfOddOrder(int n) {
        // "Сиамский метод" - один из самых просты для восприятия
        // https://ru.xcv.wiki/wiki/Siamese_method
        // Оставлю без комментариев (gif по ссылке наглядно показывает How он работает)
        // code не сложный
        int[][] matrix = new int[n][n];
        for (int i = 0; i < n; i++) {
            Arrays.fill(matrix[i], 0);
        }
        int count = 1, y = 0, x = matrix.length/2;
        while (true){
            matrix[y][x] = count;

            count++;
            if (((y == 0) && (x >= n-1)) && (matrix[n-1][0] != 0)){
                y++;
            }
            else {
                y--;
                if (y < 0) {
                    y = n - 1;
                }
                x++;
                if (x == n) {
                    x = 0;
                }
                if(matrix[y][x]!=0){
                    y+=2;
                    x--;
                }
            }

            if(count==n*n+1) break;
        }
        return matrix;
    }
   private static int[][] magicSquareOfEvenOddOrder(int n) {
        // Метод "анонима" спасибо человеку, который его придумал
        // Вот link на подробное описание метода http://www.klassikpoez.narod.ru/mojmetod.htm
        // Оставлю этот code без комментариев уж очень он большой
        // Надеюсь прочитав описание метода сможете понять(or нет?)
        int half = n/2;

        int[][] matrix = new int[n][n];
        int[][] tempMatrix;
        tempMatrix = magicSquareOfOddOrder(half);

        // 1/4 матрицы
        for (int i = 0; i < half; i++) {
            for (int j = 0; j < half; j++) {
                matrix[i][j] = tempMatrix[i][j];
            }
        }
        // 2/4 матрицы
        for (int i = 0; i < half; i++) {
            for (int j = half; j < n; j++) {
                int x = j-half;
                matrix[i][j] = (tempMatrix[i][x]+2*half*half);
            }
        }
        // 3/4 матрицы
        for (int i = half; i < n; i++) {
            for (int j = 0; j < half; j++) {
                int x = i-half;

                matrix[i][j] = (tempMatrix[x][j]+3*half*half);
            }
        }
        // 4/4 матрицы
        for (int i = half; i < n; i++) {
            for (int j = half; j < n; j++) {
                int x = i-half, y = j-half;
                matrix[i][j] = (tempMatrix[x][y]+half*half);
            }
        }
        int move = 0;
        for (int i = 6; i < n; i++) {
            if((i%4!=0)&&(i%2==0)) move++;
        }
        for (int j = matrix.length/2-move; j <= matrix.length/2+move-1; j++) {
            for (int i = 0; i < tempMatrix.length; i++) {

                int key = matrix[i][j];
                matrix[i][j] = matrix[half+i][j];
                matrix[half+i][j] = key;
            }
        }
        for (int j = 0; j <= 1; j++) {
            if (j == 0) {
                int key = matrix[0][0];
                matrix[0][0] = matrix[half][0];
                matrix[half][0] = key;
            }
            if (j == 1) {
                int key = matrix[half - 1][0];
                matrix[half - 1][0] = matrix[n - 1][0];
                matrix[n - 1][0] = key;
            }
        }
        for (int j = half+1; j < n-1; j++) {
            for (int i = 1; i < half-1; i++) {
                int key = matrix[i][1];
                matrix[i][1] = matrix[half+i][1];
                matrix[half+i][1] = key;
            }
        }
        return matrix;
    }
    private static int[][] evenMatrixSquare(int n){
        // Метод Раус-Болла хорошое описание нашел тут:
        // https://rep.bntu.by/bitstream/handle/data/62327/Magicheskie_kvadraty.pdf?sequence=1&isAllowed=y
        // Страница 8, 9
        int[][] matrix = WorkWithMatrix.standardMatrixFillingAscending(n);
        int[][] tempMatrix = WorkWithMatrix.standardMatrixFillingDescending(n);

        int size = 4;    // Размерность каждого квадрата (4х4 тафтология)
                         // можно заменить простой цифрой
        int x = 0;       // x, y - движение по кадратам (посмотрите How изменяются в ходе программы)
        int y = 0;
        for (int i = 0; i < (n*n/16); i++) {                // Смотрим сколько квадратов 4х4 помещается в матрице nxn
            if (x == (int)Math.sqrt(n*n/16)) {              // x, y переменные для движения по квадратам 4х4
                                                            // х проходит по первому ряду квадратов, достигая последнего
                                                            // обнуляется, а y увеличивается
                x = 0;
                y++;
            }
            // x и y должны лишь обеспечивать проход по квадратам
            for (int j = 0; j < 4; j++) {
                matrix[size*y+j][size*x+j] = tempMatrix[size*y+j][size*x+j];  // главная диагональ квадратов 4х4
                matrix[size*y+j][size*x+size-1-j] = tempMatrix[size*y+j][size*x+size-1-j]; // побочная диагональ
            }
            x++;
        }
        return matrix;
    }
}
Komen
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION