C语言:魔方阵-全(图解+代码+结果输出)
魔方阵,古代又称"纵横图",是指组成元素为自然数1、2…n的平方的n×n的方阵,其中每个元素值都不相等,且每行、每列以及主、副对角线上各n个元素之和都相等。一、奇数阶阵(n = 2k + 1)奇数魔方阵的排列规律如下(此处以3阶阵为例):⑴将1放在第一行中间一列;⑵从2开始直到n×n止各数依次按下列规则存放;每一个数存放的行比前一个数的行数减1,列数加1(例如上面的三阶魔方阵,5在4的上一行后一列
目录
前言
魔方阵,古代又称"纵横图",是指组成元素为自然数1、2…n的平方的n×n的方阵,其中每个元素值都不相等,且每行、每列以及主、副对角线上各n个元素之和都相等。
一、奇数阶阵(n = 2k + 1)
奇数魔方阵的排列规律如下(此处以3阶阵为例):
⑴将1放在第一行中间一列;
⑵从2开始直到n×n止各数依次按下列规则存放;每一个数存放的行比前一个数的行数减1,列数加1(例如上面的三阶魔方阵,5在4的上一行后一列);
⑶如果上一个数的行数为1,则下一个数的行数为n(指最下一行);例如1在第一行,则2应放在最下一行,列数同样加1;
⑷当上一个数的列数为n时,下一个数的列数应为1,行数减去1。例如2在第3行最后一列,则3应放在第二行第一列;
⑸如果按上面规则确定的位置上已有数,或上一个数是第一行第n列时,则把下一个数放在上一个数的下面。例如按上面的规定,4应该放在第1行第2列,但该位置已经被占据,所以4就放在3的下面;
以下为代码实现:
#define ROW 3
#define COL ROW
int arr[ROW][COL] = { 0 };
int currow = 0;
int curcol = COL / 2;
arr[0][curcol] = 1;//将1放于第一行中间
for (int i = 2; i <= ROW * COL; i++)
{
//判断上一行下一列是否存在元素
if (arr[(currow - 1 + ROW) % ROW][(curcol + 1) % COL] != 0)
{
//存在元素,将位置挪位现位置的底下
currow = (currow + 1) % ROW;
}
else
{
//不存在元素,挪位至现位置上一行下一列
currow = (currow - 1 + ROW) % ROW;
curcol = (curcol + 1) % COL;
}
arr[currow][curcol] = i;//为确定的位置赋值
}
//输出
for (int i = 0; i < ROW; i++)
{
for (int j = 0; j < COL; j++)
{
printf("%-4d", arr[i][j]);
}
printf("\n");
}
#undef ROW
#undef COL
结果输出:
二、偶数阶阵(n = 2k)
偶数阶阵存在两种情况,一种为可被4整除,一种为不能被4整除;
接下来将分开解析两种问题:
一、四倍偶数阶阵(n = 4k)
四倍偶数阶阵的排列规律如下(此处以4阶阵为例):
(1) 先将整个方阵划分成k* k个4阶方阵,然后在每个4阶方阵的对角线上做记号
(2) 由左而右、由上而下,遇到没有记号的位置才填数字,但不管是否填入数字,每移动一格数字都要加1
(3) 自右下角开始,由右而左、由下而上,遇到没有数字的位置就填入数字,但每移动一格数字都要加1
注:下列四倍偶数阶阵代码实现时,采取先全部顺序赋值,而后逆顺序对位于对角线上的元素赋值
此类型较为简单,只需注意对角线的分析:
#define ROW 4
#define COL ROW
int arr[ROW][COL] = { 0 };
//先按从左到右,从上至下的顺序依次赋值
for (int i = 0; i < ROW; i++)
{
for (int j = 0; j < COL; j++)
{
arr[i][j] = i * COL + j + 1;
}
}
for (int i = 0; i < ROW; i++)
{
for (int j = 0; j < COL; j++)
{
//对每个4*4方阵的对角线位置进行重新赋值
if (i % 4 == j % 4 || i % 4 + j % 4 == 3)
{
arr[i][j] = ROW * COL - i * COL - j;
}
}
}
//输出
for (int i = 0; i < ROW; i++)
{
for (int j = 0; j < COL; j++)
{
printf("%-4d", arr[i][j]);
}
printf("\n");
}
#undef ROW
#undef COL
结果输出:
二、非四倍偶数阶阵(n = 4k + 2)
四倍偶数阶阵的排列规律如下(此处以6阶阵为例):
6阶阵即为四个3阶阵的组合(图中标红即为换位元素)
本法填制魔方阵时,先将整个方阵划成田字型的四个2 k + 1阶的奇数阶小方阵,并以下法做注记:
(1)右半两个小方阵中大于k+2的列。
(2)左半两个小方阵中( k + 1 , k + 1 )的格位。
(3)左半两个小方阵中除了( 1 , k + 1 )是指第一列第 k+1行 的格位之外,小于k +1的列。
以奇数阶魔方阵的方法连续填制法依左上、右下、右上、左下的顺序分别填制这四个小方阵。
将上半及下半方阵中有注记的数字对调(代码实现时无需注记,只需要理清交换位置即可),魔方阵完成。
#define ROW 6
#define COL ROW
int arr[ROW][COL] = { 0 };
int currow = 0;
int curcol = COL / 4;
arr[currow][curcol] = 1;
//左上
for (int i = 2; i <= ROW * COL / 4; i++)
{
//判断上一行下一列是否存在元素
if (arr[(currow - 1 + ROW / 2) % (ROW / 2)][(curcol + 1) % (COL / 2)] != 0)
{
//存在元素,将位置挪位现位置的底下
currow = (currow + 1) % (ROW / 2);
}
else
{
//不存在元素,挪位至现位置上一行下一列
currow = (currow - 1 + (ROW / 2)) % (ROW / 2);
curcol = (curcol + 1) % (COL / 2);
}
arr[currow][curcol] = i;
}
//右下
currow = ROW / 2;
for (int i = 0; i < ROW / 2; i++, currow++)
{
curcol = COL / 2;
for (int j = 0; j < COL / 2; j++, curcol++)
{
arr[currow][curcol] = arr[i][j] + ROW * COL / 4;
}
}
//右上
currow = 0;
for (int i = 0; i < ROW / 2; i++, currow++)
{
curcol = COL / 2;
for (int j = 0; j < COL / 2; j++, curcol++)
{
arr[currow][curcol] = arr[i][j] + ROW * COL / 2;
}
}
//左下
currow = ROW / 2;
for (int i = 0; i < ROW / 2; i++, currow++)
{
curcol = 0;
for (int j = 0; j < COL / 2; j++, curcol++)
{
arr[currow][curcol] = arr[i][j] + ROW * COL / 4 + ROW * COL / 2;
}
}
// 1, 右半两个小方阵中大于k + 2的列。进行上下交换
//k = COL / 4, 右半边k = COL / 2 + COL / 4
//右半边大于 k + 2 = COL / 2 + COL / 4 + 2
for (int j = COL / 2 + COL / 4 + 2; j < COL; j++)
{
for (int i = 0; i < ROW / 2; i++)
{
int temp = arr[i][j];
arr[i][j] = arr[i + ROW / 2][j];
arr[i + ROW / 2][j] = temp;
}
}
// 2,左半两个小方阵中(k + 1, k + 1)的格位。
// 即两个方块中心点进行交换
int temp = arr[ROW / 4][COL / 4];
arr[ROW / 4][COL / 4] = arr[ROW / 4 + ROW / 2][COL / 4];
arr[ROW / 4 + ROW / 2][COL / 4] = temp;
// 3,左半两个小方阵中除了(1, k + 1)是指第一列第k + 1行的格位之外,小于k + 1的列。
// 即小于 k + 1 的列上下交换,除了中心行的第一个值
for (int i = 0; i < ROW / 2; i++)
{
for (int j = 0; j < COL / 4; j++)
{
if (i == ROW / 4 && j == 0)
{
continue;
}
int temp = arr[i][j];
arr[i][j] = arr[i + ROW / 2][j];
arr[i + ROW / 2][j] = temp;
}
}
//输出
for (int i = 0; i < ROW; i++)
{
for (int j = 0; j < COL; j++)
{
printf("%-4d", arr[i][j]);
}
printf("\n");
}
#undef ROW
#undef COL
结果输出:
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)