神奇的魔方陣–(MagicSquare)(2)

在上一篇部落格中,我們討論了階數為奇數,以及階數為(4K)的魔方陣的排列規則,以及程式碼實現(詳見://www.cnblogs.com/1651472192-wz/p/14640903.html);

本篇文章則對最後一種情況: 階數n = 4K + 2 的魔方陣 排列規律 進行分析, 以及程式碼實現.讓我們直接進入正題:

 1. 偶數階魔方陣(n = 4*K + 2)

  1.排列規律:(源自百度百科):

         1. 先將整個方陣劃成田字型的四個2 k + 1階的奇數階小方陣

         2. 右半兩個小方陣中大於k+2的列;

         3. 左半兩個小方陣中( k + 1 , k + 1 )的格位;

         4. 左半兩個小方陣中除了( k+1 , 1 )是指第一列第k+1行的格位之外,小於k +1的列。

         5. 以奇數階魔方陣的方法連續填製法依左上、右下、右上、左下的順序分別填制這四個小方陣。

         6. 將上半及下半方陣中有註記的數字對調,魔方陣完成。
 
  2. 規律解讀:
   我們可以將排列規律分成兩個部分,
   1. 分塊,並對所分的塊兒 按照 左上、右下、右上、左下的順序分別以奇數魔方陣的擺放規則進行擺放(注意 : 在填寫時要接上上個魔方陣的最後一個數字開始填起),
   2. 對魔方陣的特殊位置進行標記 ,在最後對上下對稱的標記的位置的數字進行對調.
 
  3. 圖示:(在這裡以6階魔方陣為例)

   1.分塊:

  

 

   2. 按照 左上、右下、右上、左下的順序分別以奇數魔方陣的擺放規則進行擺放 , 同時標記:

   

 

   3.對標記的方塊進行對調,魔方陣完成:

  

 

   4.程式碼實現:

  根據上面的分析,程式碼主要分為兩部分 1. 分塊填數, 2. 交換

  程式碼如下:(軟體:VS2019)

 

#include<assert.h>
#include<stdio.h>


void
Print(int(*ar)[6], int row, int col)//列印 { for (int i = 0; i < row; i++) { for (int j = 0; j < col; j++) { printf("%3d", ar[i][j]); } printf("\n"); } } //傳入 奇數階小魔方陣起始的行列資訊,以及小魔方陣的大小,起始的數字 void Magic_Square_1(int (*ar)[6],int row, int col, int size, int num) { assert(ar != nullptr && row >= 0 && col >= 0); ar[row][size / 2 + col] = num;//注意第一個數擺在魔方陣第row行中間的位置 // 在這裡不能取col/2,要取 size/2 + col; int preRow = row;//記錄上一個數字的行對於[row][col] 的偏移量 資訊 int preCol = size / 2 + col; for (int i = num +1; i < num + size * size; i++) { //重點: //注意在這裡行列下標都需要加上傳入的row 和 col 即在這裡的preRow 和 preCol 記錄的是相對與 //坐標[row][col]的偏移量. if (ar[row + (preRow - 1 + size) % size][col + (preCol + 1) % size] == 0) { ar[row + (preRow - 1 + size) % size][col + (preCol + 1) % size] = i ; preRow = (preRow - 1 + size) % size; preCol = (preCol + 1) % size; } else { ar[row + (preRow + 1) % size][col + preCol] = i; preRow = (preRow + 1) % size; } } } void Swap(int* pa, int* pb) { int tmp = *pa; *pa = *pb; *pb = tmp; } void Magic_Square() { #define ROW 6 #define COL ROW int ar[ROW][COL] = {}; Magic_Square_1(ar, 0, 0, ROW / 2, 1);//左上 Magic_Square_1(ar, ROW/2, COL/2, ROW / 2, 1+(ROW*COL/4));//右下 Magic_Square_1(ar, 0, COL/2, ROW / 2, 1+ (ROW * COL / 2));//右上 Magic_Square_1(ar, ROW/2, 0, ROW / 2, 1+ (ROW * COL / 4)*3);//左下 //上下對調右半兩個小方陣中大於k+2的列; for (int i = 0; i < ROW/2; i++) { for (int j = 0; j < COL; j++) { //上下對調右半兩個小方陣中大於k+2的列; if (j > ((ROW - 2) / 4 + ROW/2 + 2)) // 此處 注意需要加上 ROW/2 { Swap(&ar[i][j], &ar[i + ROW / 2][j]); } //左半兩個小方陣中除了( k+1 , 1 )是指第一列第k+1行的格位之外,小於k +1的列。 if(j < ((ROW - 2) / 4 ) ) //此處注意在程式中,下標是從零開始的,所以不需要加1 即:if(j < ((ROW - 2) / 4 + 1)) 這樣是錯誤的 { if (j != 1 && i != ((ROW - 2) / 4 ))//同上不需要加一 { Swap(&ar[i][j], &ar[i + ROW / 2][j]); } } } } //左半兩個小方陣中( k + 1 , k + 1 )的格位; Swap(&ar[ROW / 4][COL / 4], &ar[ROW / 4 + ROW / 2][COL / 4]); Print(ar, ROW, COL); #undef ROW #undef COL } int main() { Magic_Square(); return 0; }

 

運行結果:

 

 

(若有大哥發現其中的不合適或者錯誤,請務必在評論中告知,小弟在這裡祝大哥心情愉悅,生活快樂!)

 

 

本篇完.

 

Tags: