【软件构造课程相关】幻方及其构造(上)

介绍

幻方(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$依次放在前一个数的右上方格中。

  • 当右上方格行或列出界的时候,则由另一边进入。

  • 当右上方格中已经填有数或行列均出界,则把数填入正下方的方格中。

  • 按照以上步骤直到填写完所有N2个方格。

(由于幻方的对称性,也可以把右上改为右下、左上以及左下等方位)

​ 我们可以通过一个例子来更深的理解这个构造方法。对三阶幻方,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(int[][] squares)
{
    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阶幻方的构造。由于此条博客为本人所撰写的第一条博客,本人对于博客园发布博客还不太了解,因此简短一点就此结束这条博客。关于另外两种幻方构造方法部分的拓展内容,我将在下一条博客中叙述。

未完待续

。。。

posted @ 2024-05-03 19:55  秒速五厘米。  阅读(20)  评论(0编辑  收藏  举报