魔方阵,古代又称“纵横图”,是指组成元素为自然数1、2…n2的平方的n×n的方阵,其中每个元素值都不相等,且每行、每列以及主、副对角线上各n个元素之和都相等。
下面是我的C代码:
#include<stdio.h>
#include<string.h>
#define M 100
int a[M][M];
int i,j,k,m,n;
//奇数阶魔方阵
void three(int i,int j,int n)
{
int i1=i,i2=i+n,j1=j,j2=j+n;//标记边界
m=n*n;
j+=n/2;
while(m--)
{
a[i][j]=k++;
i--;
j++;
if(i<i1&&j>j2-1)
{//若坐标超出右上角,直接放到当前元素下面
i+=2;
j--;
}
if(i<i1)
i=i2-1;
if(j>j2-1)
j=j1;
if(a[i][j]!=0)
{
i+=2;
j--;
}
}
}
//四阶倍数魔方阵
void four()
{
//我的做法是通过对称对整个大矩阵处理
for(i=0; i<n; i++)
for(j=0; j<n; j++)
a[i][j]=k++;
m=n*n+1;
//对角线先处理一下
for(i=0; i<n; i++)
{
a[i][i]=m-a[i][i];
a[n-1-i][i]=m-a[n-1-i][i];
}
//下面对角线处理了2下,故上面先处理一下,负负得正嘛
for(j=3; j<n; j+=4)
{
for(i=j; i>=0; i--)
{//这里的坐标都是对称找的
a[i][j-i]=m-a[i][j-i];
a[n-1-j+i][n-1-i]=m-a[n-1-j+i][n-1-i];
a[i][n-1-j+i]=m-a[i][n-1-j+i];
a[n-1-j+i][i]=m-a[n-1-j+i][i];
}
}
}
//四阶倍数+2阶魔方阵
void swa(int *a,int *b)
{
int t;
t=*a;*a=*b;*b=t;
}
void six()
{
int u=n/2;
int k=(n-2)/4;
//对每个象限梯形法
three(0,0,u);
three(u,u,u);
three(0,u,u);
three(u,0,u);
//互换位子
for(i=0;i<u;i++)
if(i!=u/2)//一三象限前K格互换
for(j=0;j<k;j++)
swa(&a[i][j],&a[u+i][j]);
for(j=0;j<k;j++)//中间行K格互换
swa(&a[u/2][j+u/2],&a[u/2+u][j+u/2]);
//二四象限互换
for(i=0;i<u;i++)
for(j=0;j<k-1;j++)
swa(&a[i][u+u/2-j],&a[i+u][u+u/2-j]);
}
void print()
{
int s[100]={0};
for(i=0; i<n; i++)
{
for(j=0; j<n; j++){
printf("%4d",a[i][j]);
}
printf("\n");
}
}
int main()
{
printf("please an n:\n");
while(scanf("%d",&n))
{
k=1;
memset(a,0,sizeof(a));
if(n==2||n<1)
{
printf("input 错误! please input an n:\n");
continue;
}
if(n%2)
three(0,0,n);
else if(n%4==0)
four();
else
six();
print();
printf("please an n:\n");
}
return 0;
}
1、奇数阶幻方
n为奇数 (n=3,5,7,9,11……) (n=2*k+1,k=1,2,3,4,5……)
奇数阶幻方最经典的填法是罗伯特法(也有人称之为楼梯方)。填写方法是这样:
把1(或最小的数)放在第一行正中; 按以下规律排列剩下的n*n-1个数:
(1)、每一个数放在前一个数的右上一格;
(2)、如果这个数所要放的格已经超出了顶行那么就把它放在底行,仍然要放在右一列;
(3)、如果这个数所要放的格已经超出了最右列那么就把它放在最左列,仍然要放在上一行; </