任意阶幻方(魔方矩阵)C语言实现

魔方又称幻方纵横图九宫图,最早记录于我国古代的洛书。据说夏禹治水时,河南洛阳附近的大河里浮出了一只乌龟,背上有一个很奇怪的图形,古人认为是一种祥瑞,预示着洪水将被夏禹王彻底制服。后人称之为"洛书"或"河图",又叫河洛图
南宋数学家杨辉,在他著的《续古摘奇算法》里介绍了这种方法:只要将九个自然数按照从小到大的递增次序斜排,然后把上、下两数对调,左、右两数也对调;最后再把中部四数各向外面挺出,幻方就出现了。 (摘自《趣味数学辞典》)
在西方,阿尔布雷特·丢勒于1514年创作的木雕《忧郁》是最早关于魔方矩阵的记载。有学者认为,魔方矩阵和风靡一时的炼金术有关。几个世纪以来,魔方矩阵吸引了无数的学者和数学爱好者。本杰明·富兰克林就做过有关魔方矩阵的实验。
最简单的魔方就是平面魔方,还有立体魔方、高次魔方等。对于立体魔方、高次魔方世界上很多数学家仍在研究,本文只讨论平面魔方。
每行、每列及对角线之和被称为魔术常量或魔法总和,M。
其中,n为阶数。
例如,如果n=3,则M=[3*(3^2+1)]/2 = 15.

------------------来自百度

先标出引用地址:

http://blog.ddedu.com.cn/user1/88/archives/2007/2007420143329.shtml   //任意阶幻方构造方法

http://blog.csdn.net/cmutoo/article/details/5487157                                  //任意阶幻方C语言代码实现(有些许错误)

基础知识这里看:http://blog.csdn.net/oowgsoo/article/details/1567910

任意阶幻方的构造方法有很多种,所以要选定一种易于代码实现的一种

在上篇博客中说道:

/************************************************************************************

幻方的数量:
与我们大多数人的常识不同,幻方的数量不是唯一的,而且也不是一个简单的问题
3阶幻方只有1种
4阶幻方有880种,通过旋转和反射,总共可以有7040个幻方
5阶幻方有275 305 224个,这是用计算机算的
6阶幻方,大概是1.7743*10**19~1.7766*10**19之间,这是用统计学方法计算的,居然计算机也算不出来,更不要说6阶以上的幻方数量了

************************************************************************************/

所以代码实现的就有很大的局限性,只能实现某一种构造方法的幻方

幻方构造分为

1、奇数阶

2、双偶阶

3、单偶阶

三种。

对于奇数阶的幻方:

/*******************************************************************

n为奇数 (n=3,5,7,9,11……) (n=2×k+1,k=1,2,3,4,5……)
  奇数阶幻方最经典的填法是罗伯特法(也有人称之为楼梯法)。填写方法是这样:
  把1(或最小的数)放在第一行正中; 按以下规律排列剩下的n×n-1个数:
  (1)每一个数放在前一个数的右上一格;
  (2)如果这个数所要放的格已经超出了顶行那么就把它放在底行,仍然要放在右一列;
  (3)如果这个数所要放的格已经超出了最右列那么就把它放在最左列,仍然要放在上一行;
  (4)如果这个数所要放的格已经超出了顶行且超出了最右列,那么就把它放在前一个数的下一行同一列的格内;
  (5)如果这个数所要放的格已经有数填入,处理方法同(4)。
  这种写法总是先向“右上”的方向,象是在爬楼梯。
 
*******************************************************************/
其实在C语言实现时是有潜在的规律的,当要填的数为n的倍数时,说明所要放的格已经有数填入
实现过程也是很巧妙……
void Odd(int n,int index)
{
while(st != index)
{
cube[ox+stx][oy+sty] = st++; if((st-) % n != )
{
stx--;
sty++;
}
else
{
stx++;
} stx = ((stx-)%n+n)%n+;
sty = (sty%n == ? n : sty%n); }
}

对于双偶数阶的

就是一个中心对称

void DouEven(int n)
{
int i,j;
int st = ;
for(i=; i<=n; i++)
{
for(j=; j<=n; j++)
{
cube[i][j] = st++;
}
} int zx,zy,fx,fy;
for(i=; i<=n*n; i+=)
{ for(j=; j<=n*n; j+=)
{
zx=i-,zy=j-,fx=i,fy=j-;
cube[zx][zy]=n*n-cube[zx][zy]+;
cube[zx+][zy+]=n*n-cube[zx+][zy+]+;
cube[zx+][zy+]=n*n-cube[zx+][zy+]+;
cube[zx+][zy+]=n*n-cube[zx+][zy+]+; cube[fx][fy]=n*n-cube[fx][fy]+;
cube[fx-][fy+]=n*n-cube[fx-][fy+]+;
cube[fx-][fy+]=n*n-cube[fx-][fy+]+;
cube[fx-][fy+]=n*n-cube[fx-][fy+]+;
}
}
}

对于单偶数阶的,麻烦许多

因为要用到奇数阶的构造方法

void SingleEven(int n)
{
int i,j; ox=oy=;st=;
stx=,sty=(n/+)/;
Odd(n/,n*n*/+); //A ox=oy=n/;
stx=,sty=(n/+)/;
Odd(n/,n*n*/+); //D ox=,oy=n/;
stx=,sty=(n/+)/;
Odd(n/,n*n*/+); //B ox=n/,oy=;
stx=,sty=(n/+)/;
Odd(n/,n*n*/+); //C int k=(n-)/,tmp;
for(j=; j<=n/; j++)
{
for(i=; i<=k; i++)
{
if(j != (n/+)/)
{
tmp = cube[j][i];
cube[j][i] = cube[j+n/][i];
cube[j+n/][i] = tmp;
}
else
{
tmp = cube[j][i+(n/+)/-];
cube[j][i+(n/+)/-] = cube[j+n/][i+(n/+)/-];
cube[j+n/][i+(n/+)/-] = tmp;
}
}
}
if(k-)
{
for(i=; i<=n/; i++)
{
int tmpp = (*n+)/-;
for(j=; j<=k-; j++)
{
tmp = cube[i][j+tmpp];
cube[i][j+tmpp] = cube[i+n/][j+tmpp];
cube[i+n/][j+tmpp] = tmp; }
}
}
}

最后贴一个完整的代码:

#include <stdio.h>
#include <string.h> int cube[][];
int stx,sty;
int st;
int num;
int ox,oy; void Odd(int n,int index)
{
while(st != index)
{
cube[ox+stx][oy+sty] = st++; if((st-) % n != )
{
stx--;
sty++;
}
else
{
stx++;
} stx = ((stx-)%n+n)%n+;
sty = (sty%n == ? n : sty%n); }
} void DouEven(int n)
{
int i,j;
int st = ;
for(i=; i<=n; i++)
{
for(j=; j<=n; j++)
{
cube[i][j] = st++;
}
} int zx,zy,fx,fy;
for(i=; i<=n*n; i+=)
{ for(j=; j<=n*n; j+=)
{
zx=i-,zy=j-,fx=i,fy=j-;
cube[zx][zy]=n*n-cube[zx][zy]+;
cube[zx+][zy+]=n*n-cube[zx+][zy+]+;
cube[zx+][zy+]=n*n-cube[zx+][zy+]+;
cube[zx+][zy+]=n*n-cube[zx+][zy+]+; cube[fx][fy]=n*n-cube[fx][fy]+;
cube[fx-][fy+]=n*n-cube[fx-][fy+]+;
cube[fx-][fy+]=n*n-cube[fx-][fy+]+;
cube[fx-][fy+]=n*n-cube[fx-][fy+]+;
}
}
} void SingleEven(int n)
{
int i,j; ox=oy=;st=;
stx=,sty=(n/+)/;
Odd(n/,n*n*/+); //A ox=oy=n/;
stx=,sty=(n/+)/;
Odd(n/,n*n*/+); //D ox=,oy=n/;
stx=,sty=(n/+)/;
Odd(n/,n*n*/+); //B ox=n/,oy=;
stx=,sty=(n/+)/;
Odd(n/,n*n*/+); //C int k=(n-)/,tmp;
for(j=; j<=n/; j++)
{
for(i=; i<=k; i++)
{
if(j != (n/+)/)
{
tmp = cube[j][i];
cube[j][i] = cube[j+n/][i];
cube[j+n/][i] = tmp;
}
else
{
tmp = cube[j][i+(n/+)/-];
cube[j][i+(n/+)/-] = cube[j+n/][i+(n/+)/-];
cube[j+n/][i+(n/+)/-] = tmp;
}
}
}
if(k-)
{
for(i=; i<=n/; i++)
{
int tmpp = (*n+)/-;
for(j=; j<=k-; j++)
{
tmp = cube[i][j+tmpp];
cube[i][j+tmpp] = cube[i+n/][j+tmpp];
cube[i+n/][j+tmpp] = tmp; }
}
}
} void print(int n)
{
int i,j; for(i=; i<=n; i++)
{
int sum = ;
for(j=; j<=n ; j++)
{
sum += cube[i][j];
printf("%4d",cube[i][j]);
}
printf(" sum = %d",sum);
printf("\n");
}
} int main()
{ int i,j,k,t,n,m;
do
{
printf("Please Input n(3-17): ");
scanf("%d",&n);
if(n<)continue; memset(cube,,sizeof(cube));
if(n % == )
{
stx=,sty=(n+)/;
ox=oy=;
st=;
Odd(n,n*n+);
print(n);
}
else if(n % == )
{
DouEven(n);
print(n);
}
else if(n % == && n % != )
{ SingleEven(n);
print(n);
}
}while(); return ;
}

再上一个专门关于介绍幻方的博客:http://blog.sina.com.cn/u/1225071715

上一篇:Struts2框架学习(一)——Struts2的概念及搭建


下一篇:魔方阵算法及C语言实现