魔方阵(奇数和偶数阶)的编写

1、奇数阶魔方阵的数字规律
(1)自然数1出现在第一行的正中间;
(2)若填入的数字在第一行(不在第n列),则下一个数字在第n行(最后一行)且列数加1(列数右移一列);
(3)若填入的数字在该行的最右侧,则下一个数字就填在上一行的最左侧;
(4)一般地,下一个数字在前一个数字的右上方(行数少1,列数加1);
(5)若应填的地方已经有数字或在方阵之外,则下一个数字就填在前一个数字的下方。(一般地,n的倍数的下一个数字是在该数的下方。)

//奇数魔方阵
void Magic1()
{
#define ROW 5//定义宏行数为5
#define COL ROW//定义宏列数等于行数,则一共要放1~25这25个数

	assert(ROW%2 != 0);//断言判断是否为奇数阶

	int arr[ROW][COL] = {0};//将二维数组初始化为0

	int currow = 0;//指向第一行
	int curcol = COL/2;//指向中间那列
	arr[currow][curcol] = 1;//将第一行中间的数赋值为1,第一个数存入了二维数组
	for(int i=2; i<=ROW*COL; i++)//从2开始放,终止条件是25存入二维数组
	{
		if(arr[(currow-1+ROW)%ROW][(curcol+1)%COL] == 0)//i存放的位置是上一个的上一行且为下一列的这个位置,但要保证这个位置没有存放数,此处值为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");
	}
}
int main()
{
	Magic1();//调用
	return 0;
}

2、偶数魔方阵

(1)不能被4整除

偶数魔方阵,且不能被4整除   (4K+2)
1.将其划分4个奇数魔方阵,左上角将1~ROW*COL/4,按照奇数魔方阵的规则放进去,接下来是右下,右上,左下,依次赋值
上下标记的数字进行交换
标记的规则:

1.右半边大于k+2的列(从1开始)
2.左半边,上下两个块最中心的点进行交换
3.左半边小于中心列的列(除了上下半边最中心的行的第一列的那个值不用交换)(从1开始)

void Magic3()
{
#define ROW 10
#define COL ROW
	assert(ROW%2==0 && ROW%4!=0);
	int arr[ROW][COL] = {0};

	int currow = 0;
	int curcol = ROW/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;
	}

	//右下角
	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);
			//curcol++;
		}
		//currow++;
	}

	//右上角
	currow = 0;
	for(int i=ROW/2; i<ROW; i++, currow++)
	{
		curcol = COL/2;
		for(int j=COL/2; j<COL; j++,curcol++)
		{
			arr[currow][curcol] = arr[i][j]+(ROW*COL/4);
			//curcol++;
		}
		//currow++;
	}


	//左下角
	currow = ROW/2;
	for(int i=0; i<ROW/2; i++, currow++)
	{
		curcol = 0;
		for(int j=COL/2; j<COL; j++,curcol++)
		{
			arr[currow][curcol] = arr[i][j]+(ROW*COL/4);
			//curcol++;
		}
		//currow++;
	}
	//2.改标记点,先改右半边大于k+2的列   k=ROW/4   右半边的k=ROW/4+ROW/2   右半边的k+2 = ROW/4+ROW/2+2
	for(int j=ROW/4+ROW/2+2; j<COL; j++)//j现在就指向大于k+2的那一列  如果j合法,则上下交换
	{
		for(int i=0; i<ROW/2; i++)
		{
			int tmp = arr[i][j];
			arr[i][j] = arr[i+ROW/2][j];
			arr[i+ROW/2][j] = tmp;
		}
	}

	//3.左半边,上下两个块的中心点
	int 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;

	//4.左半边小于k+1的列(除了上下半边最中心的行的第一列的那个值不用交换)(从1开始)
	for(int i=0; i<ROW/2; i++)
	{
		for(int j=0; j<ROW/4; j++)
		{
			if(i==ROW/4 && j==0)
			{
				continue;
			}
			int 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");
	}

}
int main()
{
	Magic3();
	return 0;
}

(2)能被4整除

1:把魔方阵分为上下左右4个n/2*n/2的小的方阵,左上角和右下角的n/2*n/2的小矩阵

2:偶行偶列,奇行奇列赋值为0,其余赋值为1;右上角和左上角的n/2*n/2的小矩阵,偶行奇列,奇行偶列赋值为0,其余赋值为1。

3:从魔方阵由左到右,由上到下开始赋值,赋值为从n*n到1,若遇到原来填入方阵中的0,则跳过此格;

4:从魔方阵由左到右,由上到下开始赋值,赋值为从1到n*n,若遇到原来填入方阵中的1,则跳过此格;

5:填完数据后则完成 双偶数魔方阵;

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;

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是C语言实现n奇数魔方阵的代码和解释: ```c #include <stdio.h> #include <stdlib.h> #include <assert.h> int **Magic1(int n) //奇数魔方阵 { assert(n%2 != 0); //判断n是否为奇数,如果不是则终止程序 int **arr = (int **)malloc(sizeof(int *)*n); //创建二维数组存放魔方阵 for(int i = 0;i<n;i++) { arr[i] = (int *)calloc(n,sizeof(int)); //所有元素赋值为零,以判断每个位置上是否放置了有效数字 } int row = 0; //从第0行开始 int col = n/2; //从第n/2列开始 for(int i = 0;i<n*n;i++) { arr[row][col] = i+1; //从1开始赋值 if(arr[(row-1+n)%n][(col+1)%n] == 0) { //如果当前位置的前一行下一列数字是0,则把下一个数字放在那里 row = (row-1+n)%n; col = (col+1)%n; } else { //否则放在当前位置的下一行同列 row = (row+1)%n; } } return arr; } int main() { int n = 5; //定义魔方阵数 int **arr = Magic1(n); //生成n魔方阵 for(int i = 0;i<n;i++) { for(int j = 0;j<n;j++) { printf("%d ",arr[i][j]); //输出魔方阵 } printf("\n"); } return 0; } ``` 解释: 1. 首先判断n是否为奇数,如果不是则终止程序。 2. 创建一个二维数组存放魔方阵,所有元素赋值为零,以判断每个位置上是否放置了有效数字。 3. 从第0行正中开始赋值,从第n/2列开始赋值。 4. 如果当前位置的前一行下一列数字是0,则把下一个数字放在那里,否则放在当前位置的下一行同列。 5. 返回生成魔方阵

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值