一、關於單偶數階幻方和雙偶數階幻方
(一)單偶數階幻方(即當n=4k+2時)
任何4k+2 階幻方都可由2k+1階幻方與2×2方塊復合而成,6是此類型的最小階。
以6階為例,可由3階幻方與由0,1,2,3組成的2×2的小方塊拼成一個6×6的大方塊復合而成。
其中,3階幻方(洛書)如下圖1所示,
(圖1)
將每一單元格分成4等塊,各小塊的值與單元格的值相同,則行和、列和、對角和均為30,(見圖2),記為方陣M
(圖2)
用由0,1,2,3組成的2×2的小方塊拼成一個6×6的大方塊,使其行和、列和、對角和均為9,記為方陣N,(見圖3)
(圖3)
故6階幻方為方陣4M-N(見圖4)
(圖4)
流程圖為:
(二)雙偶數階幻方(即當n=4k時)
如上圖所示,數字可分為有圈型和無圈型。對任意的4k階幻方,可將其等分為k*k個如上圖所示的4×4元組的結構。例如8階幻方可分成4個上述結構,無圈的按照“自左至右、自上至下”的順序把1~64個數填上,有圈的先放空;有圈的按照“自右至左,自下至上”的順序把1~64個數填上,無圈處暫放空。這樣即可生成8階幻方。
流程圖為:
二、具體代碼
package MagicSquare; import java.util.Scanner; import javax.sql.rowset.FilteredRowSet; public class MagicSquare { //奇數幻方的實現: //盧培步法求奇數階幻方的函數,參數依次是儲存幻方的數組的名稱、幻方的階數, //標志位flag(為1表示主函數直接調用求奇數階幻方,為0表示SingleEven_Magic函數進行的調用) public static void Odd_Magic(int array[][],int k ,int flag){ int i=k,j=(k+1)/2,c=1; while (c<=k*k) { array[i][j]=c; if (c%k==0) {//若c是k的倍數,向上走 i-=1; } else{//若c不是k的倍數,向右下走 i+=1; j+=1; if (i>k) { i=1; } if (j>k) { j=1; } } c++; } if (flag==1) { outputArray(array); } } //雙偶數幻方: //即:階數能夠被4整除的幻方構造函數,參數依次是儲存幻方的數組的名稱、幻方的階數 public static void DoubleEven_Magic(int array[][],int k) { int i=1,j,c1=1,c2=k*k; while (i<k) { //把4k階看作k*k 個4*4 的方塊,將主對角線和反對角線上的元素標記為 -1 j=1; while (j<k) { array[i][j]=array[i+1][j+1]=array[i+2][j+2]=array[i+3][j+3] =array[i][j+3]=array[i+1][j+2] =array[i+2][j+1]=array[i+3][j]= - 1; j+=4; } i+=4; } for(i=1;i<=k;i++) for(j=1;j<=k;j++){ //標記為0的進行正向依次賦值(java 在整型數組實例化時將所有元素初始化賦值為0) if (array[i][j]==0) { array[i][j]=c1; } //否則,標記為-1 的進行反向依次賦值。 else{ array[i][j]=c2; } c1++; c2--; } outputArray(array);//輸出幻方 } //單偶數幻方: //即:階數被4除余2的幻方構造函數,參數依次是儲存幻方的數組的名稱、幻方的階數 public static void SingleEven_Magic(int array[][],int k) { int a[][]=new int[k+1][k+1]; int b[][]=new int [k+1][k+1]; int m[][]=new int [k/2+1][k/2+1]; int i,j; Odd_Magic(m, k/2, 0); //由k/2奇數階幻方衍生出1比4的k階方陣M for(i=1;i<=k/2;i++) for(j=1;j<=k/2;j++){ a[2*i-1][2*j-1]=a[2*i-1][2*j]=a[2*i][2*j-1]=a[2*i][2*j]=m[i][j]; } //構造方陣N i=1;j=1; while (i<k) { j=1; while (j<k) { //上半部分A型 1230 if (i<k/2||i==k/2&&(j==k/2+2||j==k/2-2)||i==k/2+2&&j==k/2) { b[i][j]=1; b[i][j+1]=2; b[i+1][j]=3; b[i+1][j+1]=0; } //左半部分C型 3102 else if(i==k/2&&j<k/2-2){ b[i][j]=3; b[i][j+1]=1; b[i+1][j]=0; b[i+1][j+1]=2; } //右半部分D型 2013 else if(i==k/2&&j>k/2+2){ b[i][j]=2; b[i][j+1]=0; b[i+1][j]=1; b[i+1][j+1]=3; } //6*6 核心中央和兩足 1203 else if(i==k/2&&j==k/2||i==k/2+2&&(j==k/2+2||j==k/2-2)){ b[i][j]=1; b[i][j+1]=2; b[i+1][j]=0; b[i+1][j+1]=3; } //下半部分B型 2103 else { b[i][j]=2; b[i][j+1]=1; b[i+1][j]=0; b[i+1][j+1]=3; } j+=2; } i+=2; } for(i=1;j<=k;i++) for(j=1;j<=k;j++){ array[i][j]=4*a[i][j]-b[i][j]; //4*M-N 幻方形式 } //outputArray(array); System.out.println(); //兩種幻方輸出時中間間隔一行; for(i=1;i<=k;i++) for(j=1;j<=k;j++){ array[i][j]=a[i][j]+(k/2)*(k/2)*b[i][j]; //M+(k/2)*(k/2)*N 幻方形式 } outputArray(array); } //輸出幻方的函數,參數是儲存幻方的數組的名稱 public static void outputArray (int array[][]) { for(int row=1;row<array.length;row++){ for (int column = 1; column < array[row].length; column++) { System.out.printf("%5d",array[row][column]); } System.out.println(); } } //測試函數 public static void main(String args[]) { int a[][]; System.out.println("請輸入幻方階數:"); Scanner input =new Scanner(System.in); int k=input.nextInt(); a=new int[k+1][k+1]; //階數為2的幻方不存在 if (k==2) { System.out.println("不存在階數為2的幻方,請重新輸入!"); } //奇數階幻方 else if (k%2!=0) { Odd_Magic(a, k, 1); } //4k型幻方(雙偶數幻方) else if (k%4==0) { DoubleEven_Magic(a, k); } //4k+2型幻方(單偶數幻方) else { SingleEven_Magic(a, k); } } }
三、結果截圖
(相關源碼詳見:https://github.com/shenxiaolinZERO/Resources/tree/master/Resources/Magic_Test)
將每一單元格分成4等塊,各小塊的值與單元格的值相同,則行和、列和、對角和均為30,(見圖2),記為方陣M