【軟體構造課程相關】幻方及其構造(上)

秒速五厘米。發表於2024-05-03

介紹

幻方(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()
{
    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階幻方的構造。由於此條部落格為本人所撰寫的第一條部落格,本人對於部落格園釋出部落格還不太瞭解,因此簡短一點就此結束這條部落格。關於另外兩種幻方構造方法部分的擴充內容,我將在下一條部落格中敘述。

未完待續

。。。

相關文章