介绍
幻方(Magic Square),有时又称魔术方阵或纵横图,由一组排放在正方形中的整数组成,其每行、每列以及每一条主对角线的和均相等。通常幻方由从1到$N2$的连续整数组成,其中N为正方形的行或列的数目。因此N阶幻方有N行N列,并且所填充的数为从1到$N2$。
幻方可以使用N阶方阵来表示,方阵的每行、每列以及两条对角线的和都等于常数S(N),如果填充数为$1$,$2$,…,$N2$,那么有$S(N)=N(N2+1)/2$。
构造方法
根据构造方法的不同,幻方可以分成三类:奇数阶幻方、4M阶幻方和4M+2阶幻方,其中M为自然数,2阶幻方不存在。古往今来,人们实现的幻方构造法有许多种,在此我仅就这三类幻方,每一类给出一个通用的构造方法。
奇数阶幻方
奇数阶幻方的构造是最为简单的,也是我们软件构造课程实验中要求我们实现的构造法。对于这一幻方的构造,我们可以采用Merzirac法。说明如下:
- 把1放置在第一行的中间。
-
顺序将$2,3,…N^2$依次放在前一个数的右上方格中。
-
当右上方格行或列出界的时候,则由另一边进入。
-
当右上方格中已经填有数或行列均出界,则把数填入正下方的方格中。
-
按照以上步骤直到填写完所有$N^2$个方格。
(由于幻方的对称性,也可以把右上改为右下、左上以及左下等方位)
我们可以通过一个例子来更深的理解这个构造方法。对三阶幻方,1填写在(1,2)(第一行第二列)的位置上;2应当填写在其右上方格即(0,3)中,由于(0,3)超出顶边界,所以从最底行进入,即(3,3);3应当填写在(3,3)的右上方格(2,4)中,由于(2,4)超出右边界,所以从最左列进入,即(2,1);4应当填写在(2,1)的右上方格(1,2)中,由于(1,2)已经被1所占据,因此填写在(2,1)的正下方格(3,1)中;5填写在(3,1)的右上方格(2,2)中;6填写在(2,2)的右上方格(1,3)中;7应当填写在(1,3)的右上方格(0,4)中,由于(0,4)同时超出行边界与列边界,因此填写在(1,3)的正下方格(2,3)中;8应当填写在(2,3)的右上方格(1,4)中,由于(1,4)超出右边界,所以从最左列进入,即(1,1);9应当填写在(1,1)的右上方格(0,2)中,由于(0,2)超出顶边界,所以从最底行进入,即(3,2)。按照上面的步骤便可将所有数填入,三阶幻方构造完毕。其全过程示意图如下:
需要注意的是幻方并不是唯一的,这只是用该方法构造的幻方,如果采用其他构造法得到不同的幻方是很正常的。
知道了构造思路,便很容易用java语言实现这一构造方法,代码如下:
public static void magic_square_odd_generate()
{
squares = new int[n][n];
//n阶幻方中所有的方格初始化为0
squares[0][(n-1)/2] = 1;
int x = 0,y = (n-1)/2;
//count:所有待插入的数
for(int count = 2; count <= n * n; count++)
{
//先移动到上一位置的右上方格
x--;
y++;
//循环判断是否越界,直到一个方格不越界为止
while(true)
{
//越上界x<0,则移到最下方x=x+n,y不变; continue
if(x<0)
{
x += n;
continue;
}
//越右界y>=n,则y=y-n,x不变;continue
if(y>=n)
{
y -= n;
continue;
}
//如果已有数据,则移到x = x + 2;y = y - 1; continue
if (y<0){y+=n;continue;}
if(squares[x][y] != 0 )
{
x += 2;y -= 1;
if (x>=n)
{
x-=n;
continue;
}
if (y<0)
{
y+=n;
continue;
}
continue;
}
break;
}
//将当前的count值赋给选出的方格
squares[x][y]= count;
}
}
至此,课程要求的构造方法已经完成,但是我们对幻方的探索还远远没有结束,我们还没有实现4M阶幻方和4M+2阶幻方的构造。由于此条博客为本人所撰写的第一条博客,本人对于博客园发布博客还不太了解,因此简短一点就此结束这条博客。关于另外两种幻方构造方法部分的拓展内容,我将在下一条博客中叙述。
未完待续
。。。
标签:右上方,continue,构造方法,幻方,构造,课程,填写 From: https://www.cnblogs.com/2022112842zbx/p/18171546