2021.11.30 魔方阵

69 篇文章 3 订阅

对于魔方阵,我们得考虑一下它的偶数阶和奇数阶是否是同一个规则呢?从平常我们写的魔方阵可以看出,偶数阶的和奇数阶的规则是不一样的,因此,在本文从两个角度来分析魔方阵,但是偶数阶中,我们又可以发现,偶数阶中又分为能被4整除和可以被2整除且不能被4整除的矩阵。

1. 奇数阶魔方阵的排列规律(n=2k+1)

(1) 首先将数字1放在第1行中间1列(在程序中可以先特殊处理,直接令这一个位置值为1)

(2) 从数字2开始直到n×n止,其余各数依次按这样的规则:每一个数存放的行比前一个数的行数减1,列数加1(例如上面的三阶魔方阵,5在4的上一行后一列);

(3) 如果上一个数的行数为1,则下一个数的行数为n(指最下一行)(例如1在第一行,则2应放在最下一行,列数同样加1)

(4) 当上一个数的列数为n时,下一个数的列数应为1,行数减去1。(例如2在第3行最后一列,则3应放在第二行第一列)

(5) 如果按上面规则确定的位置上已有数,或上一个数是第一行第n列时,则把下一个数放在上一个数的下面(例如按上面的规定,4应该放在第1行第2列,但该位置已经被占据,所以4就放在3的下面)

代码:

#include<stdio.h>
#include<assert.h>
void Magic1()
{
#define ROW 5
#define COL ROW
	assert(ROW % 2 != 0);

	int arr[ROW][COL] = { 0 };

	int currow = 0;
	int curcol = COL / 2;
	arr[currow][curcol] = 1;
	for (int i = 2; i <= ROW * COL; i++)
	{
		if (arr[(currow - 1 + ROW) % ROW][(curcol + 1) % COL] == 0)
		{
			currow = (currow - 1 + ROW) % ROW;
			curcol = (curcol + 1) % COL;
		}
		else
		{
			currow = (currow + 1) % ROW;
		}
		arr[currow][curcol] = i;
	}

	for (int i = 0; i < ROW; i++)
	{
		for (int j = 0; j < COL; j++)
		{
			printf("%-3d", arr[i][j]);
		}
		printf("\n");
	}
#undef ROW
#undef COL
}
int main()
{
    Magic1();
    return 0;
}

运行结果:

2. 偶数阶魔方阵

2.1 能被4整除的偶数阶魔方阵规律(n=4k)

(1) 先将整个方阵划分成k*k个4阶方阵,然后在每个4阶方阵的对角线上做记号

(2) 由左而右、由上而下,遇到没有记号的位置才填数字,但不管是否填入数字,每移动一格数字都要加1

(3) 自右下角开始,由右而左、由下而上,遇到没有数字的位置就填入数字,但每移动一格数字都要加1

代码:

#include<stdio.h>
#include<assert.h>
void Magic2()
{
#define ROW 8
#define COL ROW
	assert(ROW % 2 == 0 && ROW % 4 == 0);

	int arr[ROW][COL] = { 0 };

	int tmp = 1;
	for (int i = 0; i < ROW; i++)
	{
		for (int j = 0; j < COL; j++)
		{
			arr[i][j] = tmp++;
		}
	}

	int row1 = 0;//主对角线行
	int col1 = 0;//主对角线列
	int row2 = 0;//副对角线行
	int col2 = 0;//副对角线列

	//总体划分K*K块(i*j)
	for (int i = 0; i < (ROW / 4); i++)//i指向行
	{
		for (int j = 0; j < COL / 4; j++)//j指向列
		{
			row1 = 4 * i;
			col1 = 4 * j;
			row2 = 4 * i;
			col2 = 4 * j + 3;

			for (int k = 0; k < 4; k++)
			{
				arr[row1][col1] = (ROW * COL + 1) - arr[row1][col1];
				arr[row2][col2] = (ROW * COL + 1) - arr[row2][col2];
				row1++;
				col1++;
				row2++;
				col2--;
			}
		}
	}


	for (int i = 0; i < ROW; i++)
	{
		for (int j = 0; j < COL; j++)
		{
			printf("%-3d", arr[i][j]);
		}
		printf("\n");
	}

#undef ROW
#undef COL
}
int main()
{
    Magic2();
    return 0;
}

 运行结果:

2.1 能被2整除且不能被4整除的偶数阶魔方阵规律(n=4k+2)

 在填充魔方阵时,先将整个方阵划成田字型的4个2k+ 1阶的奇数阶小方阵,并以下列规则法做标记:(这里下标是从0开始)

(1) 右半两个小方阵中大于k+2的列。

(2) 左半两个小方阵中( k + 1 , k + 1 )的格位。

(3) 左半两个小方阵中除了( 1 , k + 1 )是指第一列第k+1行的格位之外,小于k +1的列。

以奇数阶魔方阵的方法连续填制法依左上、右下、右上、左下的顺序分别填制这四个小方阵,然后

将上半及下半方阵中有标记的数字对调,可得到魔方阵

代码:

#include<stdio.h>
#include<assert.h>
void Magic3()
{
#define ROW 6
#define COL ROW
	assert(ROW % 2 == 0 && ROW % 4 != 0);
	int tmp = 0;
	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) % (ROW / 2);
			curcol = (curcol + 1) % (COL / 2);
		}
		else
		{
			currow = (currow + 1) % (ROW / 2);
		}
		arr[currow][curcol] = i;
	}

	//右下角矩阵(根据左上角矩阵,观察可看出,左上角矩阵每个元素加9就是右下角矩阵中的元素)  
	currow = ROW / 2;
	for (int i = 0; i < ROW / 2; i++, currow++) //i和j指向左上角
	{
		curcol = COL / 2;
		for (int j = 0; j < COL / 2; j++, curcol++)
		{
			arr[currow][curcol] = arr[i][j] + (ROW * COL / 4);

		}
	}

	//右上角矩阵(根据右下角矩阵计算,也是每个元素加9就是右上角矩阵中的元素)
	currow = 0;
	for (int i = ROW / 2; i < ROW; i++, currow++) //i和j指向右下角
	{
		curcol = COL / 2;
		for (int j = COL / 2; j < COL; j++, curcol++)
		{
			arr[currow][curcol] = arr[i][j] + (ROW * COL / 4);

		}
	}

	//左下角(根据右上角矩阵中的元素加9来计算左下角矩阵中的元素)
	currow = ROW / 2;
	for (int i = 0; i < ROW / 2; i++, currow++) //i和j指向右上角
	{
		curcol = 0;
		for (int j = COL / 2; j < COL; j++, curcol++)
		{
			arr[currow][curcol] = arr[i][j] + (ROW * COL / 4);

		}
	}
	//右半边 大于k+2的列  进行上下交换
	for (int i = 0; i < ROW / 2; i++)
	{
		for (int j = ROW / 2 + ROW / 4 + 2; j < COL; j++)
		{
			tmp = arr[i][j];
			arr[i][j] = arr[i + ROW / 2][j];
			arr[i + ROW / 2][j] = tmp;
		}
	}
	//交换左半边,两个中心节点
	tmp = arr[ROW / 4][COL / 4];
	arr[ROW / 4][COL / 4] = arr[ROW / 4 + ROW / 2][COL / 4];
	arr[ROW / 4 + ROW / 2][COL / 4] = tmp;

	//左半边,除(K+1,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;
			}
			tmp = arr[i][j];
			arr[i][j] = arr[i + ROW / 2][j];
			arr[i + ROW / 2][j] = tmp;
		}
	}

	for (int i = 0; i < ROW; i++)
	{
		for (int j = 0; j < COL; j++)
		{
			printf("%-3d", arr[i][j]);
		}
		printf("\n");
	}
#undef ROW
#undef COL
}
int main()
{
    Magic3();
    return 0;
}

运行结果:

 以上就是魔方阵的所有代码,写错的请各位大佬指正!!!

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值