魔方阵1~n*n(全)--C语言

魔方阵的构造

描述:由n*n个数字所组成的n阶方阵,若具有各对角线、各横列与纵行的数字和都相等的性质,则称为魔方阵。
这个相等的和称为魔术数字。若填入的数字是从1到n*n,称此种魔方阵为n阶正规魔方阵。
如下所示为一个3阶魔方阵和一个四阶魔方阵。在这里插入图片描述
魔方阵的构建方法很多,一般将n分为三类,这三类n构成的魔方阵的算法各不相同。

  1. 当n为奇数,即n=2*k+1时,常采用简捷连续填数法。
  2. 当n为单偶数(n是偶数,但又不能被4整除),即n=4*k+2时,常采用井字调整法。
  3. 当n为双偶数(n能被4整除),即n=4*k时,常采用双向翻转法。

构造奇数阶魔方阵

奇数阶魔方阵的构造方法为:
首先把1放到顶行的正中间,然后把后继数按顺序放置在右上斜的对角线上,并作如下修改:

  1. 当到达顶行时,下一个数放到底行,好像它在顶行的上面;
  2. 当到达最右端列时,下一个数放在最左端列,好像它紧靠在右端列的右方;
  3. 当到达的位置已经填好数时,或到达右上角的位置时,下一个数就放在刚填写数的位置的正下方。

下面以构造一个3阶魔方阵为例,说明这种方法的构造过程,具体如下图所示。
图1  简捷连续填数法构造3阶魔方阵
编题思路

  • 程序中定义一个二维数组a[N][N]来保存方阵,初始时,数组中所有元素均置0。
  • 用变量row和col来存储待填数字num在方阵中的位置,由于第1个数字放在顶行的正中间,因此初始时,行row=0,列col=n/2,待填写数字num=1。
  • 采用简捷连续填数法构造方阵的过程是一个循环程序,描述为:
    While (待填写数字num<=n*n)
    {
    确定待填写数字num应该填写的位置row和col;
    填写num,即a[row][col]=num;
    Num++; // 下一个待填写的数字
    }
  • 程序中,确定待填写位置的方法是:
  1. 后继数按顺序放置在右上斜的对角线上,即row–; col++;
  2. 有三种情形需要调整。
    当到达顶行时(即row<0), row=n-1;
    当到达最右端列时(即col==n), col=0;
    当到达的位置已经填好数时(即(a[row][col]!=0), row+=2; col–;
  3. 有一种情况,当到达右上角的位置时(row=-=0 && col==n-1),直接进行特殊处理,row++ 。

构造双偶数阶魔方阵

当n为双偶数,即n=4*k时,采用双向翻转法。双向翻转法构造魔方阵的步骤如下:

  1. 将数字1到n*n按由左至右、由上到下的顺序填入方阵中。
  2. 将方阵中央部分半数的行中的所有数字左右翻转。
  3. 将方阵中央部分半数的列中的所有数字上下翻转。

由于在构造的过程中需要进行两次翻转,因此称为双向翻转法。下面以构造一个4阶魔方阵为例,说明这种方法的构造过程,具体如下图所示。
图2  双向翻转法构造4阶魔方阵

构造单偶数阶魔方阵

当n为单偶数,即n=4*k+2(6、10、14、18、22、26、30…)时,采用井字调整法。井字调整法构造魔方阵的步骤如下:

  1. 将数字1到n*n按由左至右、由上到下的顺序填入方阵中,然后在第k + 1、3 k + 2 行及列做井字标记。
  2. 将井字两边长方形中的数字和其对称位置的数字交换。注:坐标( x, y) 的对称位置为 ( n + 1 – x,n + 1 - y )。
  3. 将井字分隔线的两横行及第k + 2行两侧的数字左右对调,两横行中央的数字上下对调。左边纵列的数字除交叉点外垂直翻转。
  4. 将井字分隔线的两纵列中央的数字除第 2k+1行外左右对调,两横行左方的第一个数字上下对调,上横行中央的数字水平翻转。

在构造单偶数阶魔方阵的过程中,为了便于识别,构造时在方阵中有井字形的纵横线标记,因此称为井字调整法。
图3所示为一个6(4*1+2,k=1)阶魔方阵的构造过程,具体步骤如下:

  1. 先将数字1~36顺序填入方阵,然后在第 2(1+1)、5(3*1+2)列及第 2、5 行做上井字形标记,如下图(1)所示。
  2. 将井字两边长方形中的数字与其对称位置的数字交换,如下图(2)所示,图中交换的数字用黑框标出
  3. 将第 2、3、5行两侧的数字左右对调,第 2、5行中央的数字上下对调,第 2列的数字除交叉点外进行垂直翻转,如下图(3)所示,图中交换的数字依次用波浪线框、单线框和黑框标出。
  4. (4)第 2、5列中央的数字(第3行中的数字除外)左右对调,第 2行中央的数字水平翻转,第 2、5行左边的第一个数字上下对调,如图下(4)所示,图中交换的数字依次用波浪线框、单线框和黑框标出。
    图3  井字调整法构造6阶魔方阵

代码来源

说明:构造魔方阵方法来源于此链接,下面源代码是我经过研究,整理,接着敲成的
点击此处,产看更详细步骤

源程序代码

#include<stdio.h>

void print(int a[][30],int n)                     //打印矩阵函数
{
    int i,j;
    for(i=0;i<n;i++){
        for(j=0;j<n;j++)
            if(j==n-1)
                printf("%d",a[i][j]);
            else
                printf("%-4d",a[i][j]);
        printf("\n");
    }
}
void swap(int *x,int *y)                          //x和y交换
{
    int t;
    t=*x; *x=*y; *y=t;
}
void one(int n)                                   //n为奇数(简捷连续填数法)
{
    int num,row,col;                              //row:第一维(行);col:第二维(列)
    int a[30][30];
    for(row=0;row<n;row++)    
        for(col=0;col<n;col++)
            a[row][col]=0;                        //初始化,数组中所有元素均置0
    num=1;row=0;col=n/2;
    a[row][col]=num;
    while(num<=n*n){
        num++;
        if(row==0&&col==n-1)                     //达到右上角位置
            row++;
        else{
            row--; col++;
            if(row<0) row=n-1;
            if(col==n) col=0;
            if(a[row][col]!=0){
                row+=2;
                col--;}
            }
        a[row][col]=num;
    }
    print(a,n);
}
void two(int n)                               //n为双偶数(双向反转方法)
{
    int row,col,k;
    int num,a[30][30];
    num=1; k=n/4;
    for(row=0;row<n;row++)
        for(col=0;col<n;col++)
            a[row][col]=num++;
    for(row=k;row<=k*3-1;row++)
        for(col=0;col<n/2;col++)
            swap(&a[row][col],&a[row][n-1-col]);
  for(col=k;col<=k*3-1;col++)
        for(row=0;row<n/2;row++)
            swap(&a[row][col],&a[n-1-row][col]);
  print(a,n);
}
void three(int n)                            //n为单偶数(井字调整法)
{
    int row,col,k;
    int a[30][30],num=1;
    for(row=0;row<n;row++)
        for(col=0;col<n;col++)
            a[row][col]=num++;
    k=(n-2)/4;
    for(row=0;row<=k-1;row++)
        for(col=k+1;col<=3*k;col++){
            swap(&a[row][col],&a[n-1-row][n-1-col]);
            swap(&a[col][row],&a[n-1-col][n-1-row]);
        }
    for(col=0;col<=k-1;col++){
        swap(&a[k][col],&a[k][n-1-col]);                //井字分割线第k+1
        swap(&a[3*k+1][col],&a[3*k+1][n-1-col]);          //井字分割线3k+2
        swap(&a[k+1][col],&a[k+1][n-1-col]);                //第k+2行
    }
    for(col=k+1;col<=3*k;col++)
        swap(&a[k][col],&a[3*k+1][col]);
    for(row=0;row<n/2;row++)
        if(row!=k)
            swap(&a[row][k],&a[n-1-row][k]);
    swap(&a[k][0],&a[3*k+1][0]);
    for(col=k+1;col<n/2;col++)
        swap(&a[k][col],&a[k][n-1-col]);        
    for(col=k+1;row<=3*k;row++)
        if(row!=2*k)
            swap(&a[row][k],&a[row][3*k+1]);
    print(a,n);
}
        
int main()
{
    int n;
    printf("Input n:\n");
    scanf("%d",&n);
   if(n%2!=0)
        one(n);
    else if(n%4==0)
        two(n);
    else if((n-2)%4==0)
        three(n);
    return 0;
} 

说明:若想打印“更大”的魔方阵,将二维数组的范围更改更大即可
输出示例:
11阶魔方阵

  • 33
    点赞
  • 152
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
以下是C语言实现n阶奇数魔方阵的代码和解释: ```c #include <stdio.h> #include <stdlib.h> #include <assert.h> int **Magic1(int n) //奇数阶魔方阵 { assert(n%2 != 0); //判断n是否为奇数,如果不是则终止程序 int **arr = (int **)malloc(sizeof(int *)*n); //创建二维数组存放魔方阵 for(int i = 0;i<n;i++) { arr[i] = (int *)calloc(n,sizeof(int)); //所有元素赋值为零,以判断每个位置上是否放置了有效数字 } int row = 0; //从第0行开始 int col = n/2; //从第n/2列开始 for(int i = 0;i<n*n;i++) { arr[row][col] = i+1; //从1开始赋值 if(arr[(row-1+n)%n][(col+1)%n] == 0) { //如果当前位置的前一行下一列数字是0,则把下一个数字放在那里 row = (row-1+n)%n; col = (col+1)%n; } else { //否则放在当前位置的下一行同列 row = (row+1)%n; } } return arr; } int main() { int n = 5; //定义魔方阵的阶数 int **arr = Magic1(n); //生成n阶魔方阵 for(int i = 0;i<n;i++) { for(int j = 0;j<n;j++) { printf("%d ",arr[i][j]); //输出魔方阵 } printf("\n"); } return 0; } ``` 解释: 1. 首先判断n是否为奇数,如果不是则终止程序。 2. 创建一个二维数组存放魔方阵,所有元素赋值为零,以判断每个位置上是否放置了有效数字。 3. 从第0行正中开始赋值,从第n/2列开始赋值。 4. 如果当前位置的前一行下一列数字是0,则把下一个数字放在那里,否则放在当前位置的下一行同列。 5. 返回生成的魔方阵
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值