奇数魔方阵
一、规律:
一、规律:
⑴ 将1放在第一行中间一列
⑵ 从2开始直到n×n止各数依次按下列规则存放:
每一个数存放的行比前一个数的行数 -1,列数 +1
⑶ 如果上一个数的行数为1,下一个数的行数应为n,即最后一行 //理解为封闭环形
⑷ 如果上一个数的列数为n,下一个数的列数应为1,即第一列 //理解为封闭环形
⑸ 如果按上面规则确定的位置上已有数,则把下一个数放在上一个数的下面
二、填数过程:
①
1放在第一行中间
② 2放在1的上一行(即最后一行),下一列
③ 3放在2的上一行,下一列(即第一列)
④ 4放在3的上一行,下一列,但该位置被1占据,所以放在3(上一个数)下面
⑤ 5放在4的上一行,下一列,即最中间位置
⑥ 6放在5的上一行,下一列
⑦ 7放在6的上一行,下一列,但该位置被4占据,
所以放在6(上一个数)下面
⑧ 8放在7的上一行,下一列
⑨ 9放在8的上一行,下一列
三、上一行,下一列的表示
如果用 i , j表示行,列坐标
1)
i = ((i - 1 < 0) ? ROW - 1 : i - 1);
j = ((j - 1 < 0) ? COL - 1: j - 1);
2)
行 -1 规律:
(
3+0-1)%3=2 第一(i=0)行的上一行为第三(i=2)行
(
3+1-1)%3=0
第二(i=1)行的上一行为第一(i=0)行
(
3+2-1)%3=1
第三(i=2)行的上一行为第二(i=1)行
列+1 规律:
(0+1)%3=1
第一(i=0)列的下一列为第三(i=1)列
(1+1)%3=2
第二(i=1)列的下一列为第三(i=2)列
(2+1)%3=0
第三(i=2)列的下一列为第三(i=0)列
当前数的“行”为上一个数 行-1
i = (ROW + i - 1) % ROW;
加上ROW是为了防止出现负数
当前数的“列”为上一个数 列+1
j = (j + 1) % COL;
如果格子已经填数,则处理如下:
行”为上一个数的 行-1
行”为上一个数的 行-1
i = (i + 2) % ROW;
“列”为上一个数的 同列
j = (COL + j - 1)%COL
加上COL是为了防止出现负数
四、程序编写如下:
#include<stdio.h> #include<assert.h> void MagicSquare() { #define ROW 3 #define COL ROW assert(ROW % 2 != 0);//此代码适用于奇数魔方阵 //assert((ROW & 1) != 0); int arr[ROW][COL] = { 0 };//将每个格子置为0,后面用于判断是否已经填数 arr[0][COL / 2] = 1;//将1放在第一行最中间 int i = 0; //记录行下标 int j = COL / 2;//记录列下标 for (int n = 2; n <= ROW*COL; n++)//从2开始填数直到空格填满 { //i = (ROW + i - 1) % ROW;//当前数的“行”为上一个数 行-1 //这里加上ROW是为了防止出现负数 i = ((i - 1 < 0) ? ROW - 1 : i - 1); j = (j + 1) % COL;//当前数的“列”为上一个数 列+1 if (arr[i][j] != 0)//判断当前格子是否已经填入数字,如果填入,则处理如下 { i = (i + 2) % ROW;//如果该格子已经填数,则“行”为上一个数的 行-1 //j = (COL + j - 1)%COL;------------,则“列”为上一个数的 同列 //这里加上COL是为了防止出现负数 j = ((j - 1 < 0 )? COL - 1 : j - 1); } arr[i][j] = n;//填入数字 } for (int i = 0; i < ROW; i++) { for (int j = 0; j < COL; j++) { printf("%-3d", arr[i][j]); } printf("\n"); } } int main() { MagicSquare(); return 0; }运行结果: