N阶幻方的生成及应用

1.特性

 水平、垂直及斜角元素和都为一个固定值。以三 阶幻方为例:

492
357
816

它的各行元素和,各列元素和,及对角线元素和都是15。

2.代码

import java.util.Arrays;

/**
 * @author panda 
 * @date 2023年8月26日
 *
 */
public class MagicSquare {
    private int[][] matrix;
    private int size;

    public MagicSquare(int size) {
        this.size = size;
        matrix = new int[size][size];
        
        if (size <= 2) {
            System.err.println("");
            return;
        } else if (size % 2 == 1) {
            genOdd();
        } else {
            int ds = size / 2;
            if (ds % 2 == 0) {
                genDoubleEven();                
            } else {
                genSingleEven();                
            }
        }
    }

    /**
     * 边长为奇数:
     */
    public void genOdd() {
        int n = 1;
        int r = 0;
        int c = size / 2;

        while (n <= size * size) {
            matrix[r][c] = n;
            n++;
            r--;
            c++;
            
            if (r < 0 && c >= size) {
                r += 2;
                c--;
            } else if (r < 0) {
                r = size - 1;
            } else if (c >= size) {
                c = 0;
            } else if (matrix[r][c] != 0) {
                r += 2;
                c--;
            }
        }
    }
    
    /**
     * 边长为单偶数:
     */
    public void genSingleEven() {
        int r = 0;
        int c = size / 2 - 1;
        int total = size * size / 4;
        for (int i = 1; i <= total; i++) {
            int type = 1;

            if ((r == size / 2 + 1 && c != size / 2 - 1) || (r == size / 2 - 1 && c == size / 2 - 1)) {
                type = 0;
            }

            if (r >= size / 2 + 3) {
                type = -1;
            }
            
            switch (type) {
                case 1:
                    matrix[r][c] = 4 * i;
                    matrix[r][c + 1] = 4 * i - 3;
                    matrix[r + 1][c] = 4 * i - 2;
                    matrix[r + 1][c + 1] = 4 * i - 1;
                    break;

                case 0:
                    matrix[r][c] = 4 * i - 3;
                    matrix[r][c + 1] = 4 * i;
                    matrix[r + 1][c] = 4 * i - 2;
                    matrix[r + 1][c + 1] = 4 * i - 1;
                    break;

                default:
                    matrix[r][c] = 4 * i - 3;
                    matrix[r][c + 1] = 4 * i;
                    matrix[r + 1][c] = 4 * i - 1;
                    matrix[r + 1][c + 1] = 4 * i - 2;
                    break;
            }

            int m = (r - 2 + size) % size;
            int n = (c + 2) % size;
            if (matrix[m][n] > 0) {
                r = (r + 2) % size;
            } else {
                r = m;
                c = n;
            }
        }
    }
    
    /**
     * 边长为双偶数
     */
    public void genDoubleEven() {
        
        int[] arr = new int[size * size / 2];
        int index = 0;

        for (int r = 0; r < size; r++) {
            for (int c = 0; c < size; c++) {

                // 符合分割条件
                int m = r % 4;
                int n = c % 4;

                if (m != n && m + n != 3) {
                    arr[index++] = r * size + c + 1;
                    matrix[r][c] = 0;
                } else {
                    matrix[r][c] = r * size + c + 1;
                }
            }
        }

        Arrays.sort(arr);
        int tempIndex = arr.length - 1;

        for (int r = 0; r < size; r++) {
            for (int c = 0; c < size; c++) {
                if (matrix[r][c] == 0) {
                    matrix[r][c] = arr[tempIndex--];
                }
            }
        }
    }
    
    /**
     * 幻方检查
     * @return                          true:通过检查;false:没有通过检查
     */
    public boolean check() {
        //标准和:
        int stdSum = size * (size * size + 1) / 2;
        
        //检查行:
        int sum = 0;
        for (int i = 0; i < size; i++) {
            sum = 0;
            for (int j = 0; j < size; j++) {
                sum += matrix[i][j];
            }
            if (sum != stdSum) {
                return false;
            }
        }
        
        //检查列:
        for (int i = 0; i < size; i++) {
            sum = 0;
            for (int j = 0; j < size; j++) {
                sum += matrix[j][i];
            }
            if (sum != stdSum) {
                return false;
            }
        }
        
        //检查对角:
        sum = 0;
        for (int i = 0; i < size; i++) {
            sum += matrix[i][i];
        }
        if (sum != stdSum) {
            return false;
        }
        
        sum = 0;
        for (int i = 0; i < size; i++) {
            sum += matrix[i][size - i - 1];
        }
        if (sum != stdSum) {
            return false;
        }
        
        return true;
    }

    public void print() {
        for (int i = 0; i < size; i++) {
            for (int j = 0; j < size; j++) {
                System.out.print(matrix[i][j] + "\t");
            }
            System.out.println();
        }
    }

    public static void main(String[] args) {
        for (int i = 3; i < 256; i++) {
        MagicSquare magicSquare = new MagicSquare(i);
        //magicSquare.print();
        System.out.println("边长为" + i + ":" + magicSquare.check());
        }
    }
}

3.应用

加密数据。如果有一组数据,可以使用下16阶的幻方进行查表加密:

001 255 254 004 005 251 250 008 009 247 246 012 013 243 242 016 
240 018 019 237 236 022 023 233 232 026 027 229 228 030 031 225 
224 034 035 221 220 038 039 217 216 042 043 213 212 046 047 209 
049 207 206 052 053 203 202 056 057 199 198 060 061 195 194 064 
065 191 190 068 069 187 186 072 073 183 182 076 077 179 178 080 
176 082 083 173 172 086 087 169 168 090 091 165 164 094 095 161 
160 098 099 157 156 102 103 153 152 106 107 149 148 110 111 145 
113 143 142 116 117 139 138 120 121 135 134 124 125 131 130 128 
129 127 126 132 133 123 122 136 137 119 118 140 141 115 114 144 
112 146 147 109 108 150 151 105 104 154 155 101 100 158 159 097 
096 162 163 093 092 166 167 089 088 170 171 085 084 174 175 081 
177 079 078 180 181 075 074 184 185 071 070 188 189 067 066 192 
193 063 062 196 197 059 058 200 201 055 054 204 205 051 050 208 
048 210 211 045 044 214 215 041 040 218 219 037 036 222 223 033 
032 226 227 029 028 230 231 025 024 234 235 021 020 238 239 017 
241 015 014 244 245 011 010 248 249 007 006 252 253 003 002 256

当然在应用时,可以将所有值减1,或者将256替换成0,再做转换。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值