目录

前言

一、奇数阶阵(n = 2k + 1)

结果输出:

二、偶数阶阵(n = 2k)

一、四倍偶数阶阵(n = 4k)

结果输出:

二、非四倍偶数阶阵(n = 4k + 2)

结果输出:


前言

​​​​​​​魔方阵,古代又称"纵横图",是指组成元素为自然数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

结果输出:

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐