魔方阵(奇数行列,偶数行列(能被4整除的,不能被4整除的))
魔方阵
①:奇数行列
//奇数(行,列)
void MagicSquare1()
{
#define ROW 5
#define COL ROW
assert(ROW%2!=0);//ROW&1==1
int arr[ROW][COL] = {0};
arr[0][COL/2] = 1;
int currow = 0;
int curcol = COL/2;
for(int i=2;i<=ROW*COL;i++)
{
/*currow--;//1
if(currow < 0)
currow = ROW-1;*/
//currow = (currow==0 ? ROW-1 : currow-1);//2
currow = (currow-1+ROW)%ROW;//3
//curcol = (curcol==COL-1 ? 0 : curcol+1);
curcol = (curcol+1)%COL;
if(arr[currow][curcol] != 0)//有值
{
currow = (currow+2)%ROW;
curcol = (curcol-1+COL)%COL;
}
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()
{
MagicSquare1();
return 0;
}
②:偶数行列(不能被4整除)
//能被2整除,但不能被4整除
void MagicSquare2()
{
#define ROW 6
#define COL ROW
assert(ROW%2==0 && ROW%4!=0);
int arr[ROW][COL]={0};
int currow=0;
int curcol=COL/4;
//左上角方阵 按奇数处理
for(int i = 0;i<(ROW*ROW)/4;i++)
{
arr[currow][curcol]=i+1;
if(arr[(currow-1+ROW/2)%(ROW/2)][(curcol+1)%(ROW/2)] == 0)
{
currow = (currow-1+ROW/2)%(ROW/2);
curcol = (curcol+1)%(ROW/2);
}
else
{
currow = (currow+1)%(ROW/2);
}
}
//右下角方阵 等同于左上角每个数+(ROW*ROW/4)
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*ROW/4);
}
}
//右上角方阵 等同于右下角每个数+(ROW*ROW/4)
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*ROW/4);
}
}
//左下角方阵 等同于右上角每个数+(ROW*ROW/4)
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*ROW/4);
}
}
//左半边调换 若为最中间行,则从最中间列开始从左向右标注 (COL/4) 个数字 最后上下两部分关键字交换
int tmp=0;
for(int i=0;i<ROW/2;i++)
{
for(int j=0;j<COL/4;j++)
{
if(i==ROW/4)
{
j=COL/4;
}
tmp=arr[i][j];
arr[i][j]=arr[i+ROW/2][j];
arr[i+ROW/2][j]=tmp;
}
}
//右半边调换 标记 列 大于 ROW/2+ROW/4+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;
}
}
for(int i=0;i<ROW;i++)
{
for(int j=0;j<COL;j++)
{
printf("%-3d",arr[i][j]);
}
printf("\n");
}
}
int main()
{
MagicSquare2();
return 0;
}
③:偶数行列(能被4整除)
//能被2整除,也能被4整除 ROW=4k
//由左而右、由上而下,遇到没有记号的位置才填数字,但不管是否填入数字,每移动一格数字都要加1;
//自右下角开始,由右而左、由下而上,遇到没有数字的位置就填入数字,但每移动一格数字都要加1。
void MagicSquare3()
{
#define ROW 8
#define COL ROW
assert(ROW%4==0);
int arr[ROW][COL]={0};
int tmp=1; //从1开始依次赋值
for(int i=0;i<ROW;i++)
{
for(int j=0;j<COL;j++)
{
arr[i][j]=tmp;
tmp++;
}
}
int currow1 = 0;//主对角线行数
int curcol1 = 0;//主对角线列数
int currow2 = 0;//副对角线行数
int curcol2 = 0;//副对角线列数
for(int i=0;i<ROW/4;i++) //把n阶矩阵分为(n/4)*(n/4)个小4阶方阵中第一大行开始
{
for(int j = 0;j<COL/4;j++) //把n阶矩阵分为(n/4)*(n/4)个小4方阵的第一大列开始
{
currow1=4*i;
currow2=4*i;
curcol1=4*j;
curcol2=4*j+3;
for(int k = 0;k<4;k++)//每一个小4阶方阵主对角线和副对角线各有4个数
{
arr[currow1][curcol1] = ROW*ROW+1-arr[currow1][curcol1]; //主对角线数字转换,转换规则:当前位置赋值(ROW*ROW+1-原值)
currow1++;
curcol1++;
arr[currow2][curcol2] = ROW*ROW+1-arr[currow2][curcol2]; //副对角线数字转换,转换规则:当前位置赋值(ROW*ROW+1-原值)
currow2++;
curcol2--;
}
}
}
for(int i=0;i<ROW;i++)
{
for(int j=0;j<COL;j++)
{
printf("%-5d",arr[i][j]);
}
printf("\n");
}
}
int main()
{
MagicSquare3();
return 0;
}
至此,魔方阵各种情况完成,如果还有更简洁的方法,欢迎探讨。