1. 程式人生 > >C語言實現魔方陣程式碼及解析

C語言實現魔方陣程式碼及解析

問題描述編寫程式,實現如下表所示的5-魔方陣。

17 24 1 8 15
23 5 7 14 16
4 6 13 20 22
10 12 19 21 3
11 18 25 2 9
5-魔方陣

問題分析

所謂“n-魔方陣”,指的是使用1〜n2共n2個自然數排列成一個n×n的方陣,其中n為奇數;該方陣的每行、每列及對角線元素之和都相等,併為一個只與n有關的常數,該常數為n×(n2+1)/2。

例如4-魔方陣,其第一行、第一列及主對角線上各元素之和如下:

  • 第一行元素之和:17+24+1+8+15=65
  • 第一列元素之和:17+23+4+10+11=65
  • 主對角線上元素之和:17+5+13+21+9=65


而 n×(n2+1)/2=5×(52+1)/2=65 可以驗證,5-魔方陣中其餘各行、各列及副對角線上的元素之和也都為65。

假定陣列的行列下標都從0開始,則魔方陣的生成方法為:在第0行中間置1,對從2開始的其餘n2-1個數依次按下列規則存放:
(1) 假定當前數的下標為(i,j),則下一個數的放置位置為當前位置的右上方,即下標為(i-1,j+1)的位置。
(2) 如果當前數在第0行,即i-1小於0,則將下一個數放在最後一行的下一列上,即下標為(n-1,j+1)的位置。
(3) 如果當前數在最後一列上,即j+1大於n-1,則將下一個數放在上一行的第一列上,即下標為(i-1,0)的位置。
(4) 如果當前數是n的倍數,則將下一個數直接放在當前位置的正下方,即下標為(i+1,j)的位置。

演算法設計

在設計演算法時釆用了下面一些方法:

  • 定義array()函式,array()函式的根據輸入的n值,生成並顯示一個魔方陣,當發現n不是奇數時,就加1使之成為奇數。
  • 使用動態記憶體分配與釋放函式malloc()與free(),在程式執行過程中動態分配與釋放記憶體,這樣做的好處是使程式碼具有通用性,同時提高記憶體的使用率。

在分配記憶體時還要注意,由於一個整型數要佔用兩個記憶體,因此,如果魔方陣中要存放的數有max個,則分配記憶體時要分配2*max個單元,從而有malloc(max+max)。在malloc()函式中使用max+max而不是2*max是考慮了程式執行的效能。

顯然應該使用二維陣列來表示魔方陣,但雖然陣列是二維形式的,而由於記憶體是一維線性的,因此在存取陣列元素時,要將雙下標轉換為單個索引編號。在程式中直接定義了指標變數來指向陣列空間,即使用malloc()函式分配的記憶體。

下面是完整的程式碼:

#include<stdio.h>
#include<stdlib.h>

int array(int n)
{
    int i, j, no, num, max;
    int *mtrx;
    if(n%2 == 0)  /*n是偶數,則加1使其變為奇數*/
    {
        n=n+1;
    }
    max=n*n;
    mtrx=(int *)malloc(max+max);  /*為魔方陣分配記憶體*/
    mtrx[n/2]=1;  /* 將1存入陣列*/
    i=0;  /*自然數1所在行*/
    j=n/2;  /*自然數1所在列*/
    /*從2開始確定每個數的存放位置*/
    for(num=2; num<=max; num++)
    {
        i=i-1;
        j=j+1;
        if((num-1)%n == 0)  /*當前數是n的倍數*/
        {
            i=i+2;
            j=j-1;
        }
        if(i<0)  /*當前數在第0行*/
        {
            i=n-1;
        }
        if(j>n-1)  /*當前數在最後一列,即n-1列*/
        {
            j=0;
        }
        no=i*n+j;  /*找到當前數在陣列中的存放位置*/
        mtrx[no]=num;
    }
    /*列印生成的魔方陣*/
    printf("生成的%d-魔方陣為:",n);
    no=0;
    for(i=0; i<n; i++)
    {
        printf("\n");
        for(j=0; j<n; j++)
        {
            printf("%3d", mtrx[no]);
            no++;
        }
    }
    printf("\n");
    free(mtrx);
    return 0;
}

int main()
{
    int n;
    printf("請輸入n值:\n");
    scanf("%d", &n);
    array(n);  /*呼叫array函式*/
    return 0;
}

執行結果:

C語言實現魔方陣程式碼及解析

知識點補充

在解決該問題時,採用的是動態分配記憶體的方式,並使用了指標變數mtrx來指向二維陣列中的元素。在演算法設計中,要儲存魔方陣需要一個二維陣列,因此再給出直接使用二維陣列來生成8-魔方陣的程式。

直接使用二維陣列生成5-魔方陣的程式碼如下:

示例輸出如下:

C語言實現魔方陣程式碼及解析