魔方阵的实现(C语言)

    xiaoxiao2021-03-25  73

    魔方阵又叫幻方(Magic Square),是一种将数字安排在正方形格子中,使每行、列和对角线上的数字和都相等的方法。幻方也是一种中国传统游戏。旧时在官府、学堂多见。它是将从一到若干个数的自然数排成纵横各为若干个数的正方形,使在同一行、同一列和同一对角线上的几个数的和都相等。 对平面幻方的构造,分为三种情况:N为奇数、N为4的倍数、N为其它偶数(4n+2的形式) 1、 N 为奇数时,最简单: ⑴ 将1放在第一行中间一列; ⑵ 从2开始直到n×n止各数依次按下列规则存放: 按 45°方向行走,如向右上 每一个数存放的行比前一个数的行数减1,列数加1 ⑶ 如果行列范围超出矩阵范围,则回绕。 例如1在第1行,则2应放在最下一行,列数同样加1; ⑷ 如果按上面规则确定的位置上已有数,或上一个数是第1行第n列时, 则把下一个数放在上一个数的下面。 2、 N为4的倍数时 采用对称元素交换法。 首先把数1到n×n按从上至下,从左到右顺序填入矩阵 然后将方阵的所有4×4子方阵中的两对角线上位置的数关于方阵中心作对 称交换,即a(i,j)与a(n+1-i,n+1-j)交换,所有其它位置上的数不变。 (或者将对角线不变,其它位置对称交换也可) **以上方法只适合于n=4时** 3、 N 为其它偶数时 当n为非4倍数的偶数(即4n+2形)时:首先把大方阵分解为4个奇数(2m+1阶)子方阵。 按上述奇数阶幻方给分解的4个子方阵对应赋值 由小到大依次为上左子阵(i),下右子(i+v),上右子阵(i+2v),下左子阵(i+3v), 即4个子方阵对应元素相差v,其中v=n*n/4 四个子矩阵由小到大排列方式为 ① ③ ④ ② 然后作相应的元素交换:a(i,j)与a(i+u,j)在同一列做对应交换(j<t或j>n-t+2), a(t-1,0)与a(t+u-1,0);a(t-1,t-1)与a(t+u-1,t-1)两对元素交换

    其中u=n/2,t=(n+2)/4 上述交换使行列及对角线上元素之和相等。

    C语言代码如下

    #include <stdio.h> #include <stdlib.h> void swap(int *i,int *j) { int t; t=*i; *i=*j; *j=t; } void n_qtosmfz(int k) { int a,x,y,i,j,n; n=k/2; int f[n][n],g[n][n],h[n][n],l[n][n]; f[(n+1)/2-1][0]=1; //左上 x=(n+1)/2-1; y=0; for(a=2; a<=n*n; a++) { if((a-1)%n==0) { f[x][y+1]=a; y++; } else { if(x+1==n) x=0; else x++; if(y-1<0) y=n-1; else y--; f[x][y]=a; } } g[(n+1)/2-1][0]=1+k*k/2; //右上 x=(n+1)/2-1; y=0; for(a=2+k*k/2; a<=n*n+k*k/2; a++) { if((a-1)%n==0) { g[x][y+1]=a; y++; } else { if(x+1==n) x=0; else x++; if(y-1<0) y=n-1; else y--; g[x][y]=a; } } h[(n+1)/2-1][0]=1+3*k*k/4; //左下 x=(n+1)/2-1; y=0; for(a=2+3*k*k/4; a<=n*n+3*k*k/4; a++) { if((a-1)%n==0) { h[x][y+1]=a; y++; } else { if(x+1==n) x=0; else x++; if(y-1<0) y=n-1; else y--; h[x][y]=a; } } l[(n+1)/2-1][0]=1+k*k/4; //右下 x=(n+1)/2-1; y=0; for(a=2+k*k/4; a<=n*n+k*k/4; a++) { if((a-1)%n==0) { l[x][y+1]=a; y++; } else { if(x+1==n) x=0; else x++; if(y-1<0) y=n-1; else y--; l[x][y]=a; } } int m=(k-2)/4; for(i=m+2; i<k/2; i++) //交换右半两个小方阵中大于k+2的列。 for(j=0; j<k/2; j++) swap(&g[i][j],&l[i][j]); swap(&f[m][m],&h[m][m]); swap(&f[0][m],&h[0][m]); for(i=0; i<m; i++) for(j=0; j<k/2; j++) swap(&f[i][j],&h[i][j]); for(j=0; j<n; j++) { { for(i=0; i<n; i++) printf("%-2d ",f[i][j]); for(i=0; i<n; i++) printf("%-2d ",g[i][j]); } printf("\n\n"); } for(j=0; j<n; j++) { { for(i=0; i<n; i++) printf("%-2d ",h[i][j]); for(i=0; i<n; i++) printf("%-2d ",l[i][j]); } printf("\n\n"); } } void n_4kmfz(int n) { int i=1,j=0,k; int a[n][n]; a[0][0]=1; while(i*j<=(n-1)*(n-1)) //首先把数1到n×n按从上至下,从左到右顺序填入矩阵 { a[i][j]=a[i-1][j]+1; i++; if(i==n&&j!=n-1) { i=1; j++; a[0][j]=a[n-1][j-1]+1; } } k=n/4; for(i=0; i<k; i++) /*然后将方阵的所有4×4子方阵中的两对角线上位置的数关于方阵中心作对 称交换,即a(i,j)与a(n+1-i,n+1-j)交换,所有其它位置上的数不变。*/ for(j=0; j<k; j++) { swap(&a[4*i][4*j],&a[n-1-4*i][n-1-4*j]); swap(&a[4*i+1][4*j+1],&a[n-1-4*i-1][n-1-4*j-1]); swap(&a[4*i][4*j+3],&a[n-1-4*i][n-1-4*j-3]); swap(&a[4*i+1][4*j+2],&a[n-1-4*i-1][n-1-4*j-2]); } for(i=0; i<n; i++) { for(j=0; j<n; j++) printf("%-4d ",a[i][j]); printf("\n\n"); } } void jsjmfz(int n) { int a,x,y,i,j; int f[n][n]; f[(n+1)/2-1][0]=1; x=(n+1)/2-1; y=0; for(a=2; a<=n*n; a++) { if((a-1)%n==0) { f[x][y+1]=a; y++; } else { if(x+1==n) x=0; else x++; if(y-1<0) y=n-1; else y--; f[x][y]=a; } } for(j=0; j<n; j++) { for(i=0; i<n; i++) { printf("%-2d ",f[i][j]); //控制格式,考虑%-*d格式 } printf("\n\n"); //换行考虑自定义函数循环 } } int main() { int n=1; while (n!=-1) { printf("请输入魔方阵阶数(请输入正整数,输入-1结束程序):\n"); scanf("%d",&n); printf("--------------------------------------\n"); if(n%2!=0) jsjmfz(n); else { if(n==2) printf("该阶数魔方阵不存在\n"); else if (n%4==0) n_4kmfz(n); else n_qtosmfz(n); } printf("--------------------------------------\n"); } }

    转载请注明原文地址: https://ju.6miu.com/read-35975.html

    最新回复(0)