魔方阵的实现(C语言)

来源:互联网 发布:apache用什么语言写的 编辑:程序博客网 时间:2024/06/05 05:51

魔方阵又叫幻方(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");    }}


0 0
原创粉丝点击