#include<iostream.h>
#include<conio.h>
#define max 50
#define size 15
int test____print(int matrix[max][max],int order);
void test__print(int matrix[max][max],int matrixA[max][max],int matrixB[max][max],int matrixC[max][max],int matrixD[max][max],int ord);
void jishujie(int matrix[max][max],int x,int y,int ord);
int main()
{
int order;
cout<<"请输入阶数:";
while(cin>>order)
{
//奇数阶算法
/***************************************************************************************
奇数阶幻方最经典的填法是罗伯法。填写的口诀:
1居首行正中央,
依次右上莫相忘。
上出格时往下放,
右出格时往左放。
排重便往自下放,
右上出格一个样。
******************************************************************************************/
if(order%2==1)
{
int matrix[max][max]={0},count,row=0,coclum=order/2;
for(count=1;count<=order*order;count++)
{
matrix[row][coclum]=count;
if(count%order==0)
row++;
else
{
row=(row==0)? order-1:row-1;
coclum=(coclum==order-1)? 0:coclum+1;
}
}
int m=0;
for(int i=0;i<order;i++)
for(int j=0;j<order;j++)
{
m++;
cout<<matrix[i][j]<<"\t";
if(m%order==0)
cout<<endl<<endl;
}
cout<<"请输入阶数:";
}
//双偶数的算法
/*******************************************************************************************
所谓双偶阶幻方就是当n可以被4整除时的偶阶幻方,即4K阶幻方。在说解法之前我们先说明一个"互补数"定义:
就是在n阶幻方中,如果两个数的和等于幻方中最大的数与1的和(即n×n+1),我们称它们为一对互补数。如
在三阶幻方中,每一对和为10的数,是一对互补数 ;在四阶幻方中,每一对和为17的数,是一对互补数。
双偶数阶幻方最经典的填法是海尔法。填写的方法是:
以八阶幻方为例 :
先写出顺序数组 :
1 2 3 4 |5 6 7 8
9 10 11 12 |13 14 15 16
17 18 19 20 |21 22 23 24
25 26 27 28 |29 30 31 32
------------------------------------------>
33 34 35 36 |37 38 39 40
41 42 43 44 |45 46 47 48
49 50 51 52 |53 54 55 56
57 58 59 60 |61 62 63 64
然后平均划分成4份,类似直角坐标系,然后使每个小方阵的对角线元素换成它的互补数
(互补数为:数组最大数加一 如:8*8+1=65)
64 2 3 61 |60 6 7 57
A 9 55 54 12 |13 51 50 16 B
17 47 46 20 |21 43 42 24
40 26 27 37 |36 30 31 33
-----------------|------------------>
32 34 35 29 |28 38 39 25
C 41 23 22 44 |45 19 18 48
49 15 14 52 |53 11 10 56 D
8 58 59 5 |4 62 63 1
|
以八阶幻方为例 :
先写出顺序数组 :
1 2 3 4 5 6 7 8
9 10 11 12 13 14 15 16
17 18 19 20 21 22 23 24
25 26 27 28 29 30 31 32
33 34 35 36 37 38 39 40
41 42 43 44 45 46 47 48
49 50 51 52 53 54 55 56
57 58 59 60 61 62 63 64
然后平均划分成4份,类似直角坐标系,然后使每个小方阵的对角线元素换成它的互补数
(互补数为:数组最大数加一 如:8*8+1=65)
64 2 3 61 |60 6 7 57
A 9 55 54 12 |13 51 50 16 B
17 47 46 20 |21 43 42 24
40 26 27 37 |36 30 31 33
-----------------|------------------
32 34 35 29 |28 38 39 25
C 41 23 22 44 |45 19 18 48
49 15 14 52 |53 11 10 56 D
8 58 59 5 |4 62 63 1
|
*********************************************************************************************/
if(order%4==0) //双偶
{
int matrix[max][max];
int m=1+order*order,count=1;
for(int row=0;row<order;row++)
for(int coclum=0;coclum<order;coclum++)
matrix[row][coclum]=count++;
if(order==4)
{
for(int i=0,j=0,p=0,k=3,n=0;n<4;n++)
{
matrix[i][j]=m-matrix[i][j];
i++;
j++;
matrix[p][k]=m-matrix[p][k];
p++;
k--;
}
test____print(matrix,order);
cout<<"请输入阶数:";
}
else
{
for(int i=0,j=0,p=0,k=order/2-1,n=0;n<order/2;n++) //A部分
{
matrix[i][j]=m-matrix[i][j];
i++;
j++;
matrix[p][k]=m-matrix[p][k];
p++;
k--;
}
for(int i=0,j=order/2,p=0,k=order-1,n=0;n<order/2;n++)//B部分
{
matrix[i][j]=m-matrix[i][j];
i++;
j++;
matrix[p][k]=m-matrix[p][k];
p++;
k--;
}
for(int i=order/2,j=0,p=order/2,k=order/2-1,n=0;n<order/2;n++) //C部分
{
matrix[i][j]=m-matrix[i][j];
i++;
j++;
matrix[p][k]=m-matrix[p][k];
p++;
k--;
}
for(int i=order/2,j=order/2,p=order/2,k=order-1,n=0;n<order/2;n++) //D部分
{
matrix[i][j]=m-matrix[i][j];
i++;
j++;
matrix[p][k]=m-matrix[p][k];
p++;
k--;
}
test____print(matrix,order);
cout<<"请输入阶数:";
}
}
/* ***********************************************************************************************
单偶数阶幻方(斯特拉兹法)
所谓单偶阶幻方就是当n不可以被4整除时的偶阶幻方,即4K+2阶幻方。如(n=6,10,14……)的幻方。
单偶数阶幻方最经典的填法是斯特拉兹法。填写的方法是:
以10阶幻方为例。这时,k=2。
(1)把魔方阵分为A,B,C,D四个象限,这样每一个象限肯定是奇数阶。
用罗伯法,依次在A象限,D象限,B象限,C象限按奇数阶幻方的填法填数。
17 24 1 8 15 |67 74 51 58 65
23 5 7 14 16 |73 55 57 64 66
4 6 13 20 22 |54 56 63 70 72
10 12 19 21 3 |60 62 69 71 53
11 18 25 2 9 |61 68 75 52 59
-------------------------------------------->
92 99 76 83 90 |42 49 26 33 40
98 80 82 89 91 |48 30 32 39 41
79 81 88 95 97 |29 31 38 45 47
85 87 94 96 78 |35 37 44 46 28
86 93 100 77 84 |36 43 50 27 34
|
(2)在A象限的中间行、中间格开始,按自左向右的方向,标出k格。
A象限的其它行则标出最左边的k格。将这些格,和C象限相对位置上的数互换位置。
92 99 1 8 15 |67 74 51 58 65
98 80 7 14 16 |73 55 57 64 66
4 6 88 95 22 |54 56 63 70 72
85 87 19 21 3 |60 62 69 71 53
86 93 25 2 9 |61 68 75 52 59
------------------------------------------------->
17 24 76 83 90 |42 49 26 33 40
23 5 82 89 91 |48 30 32 39 41
79 81 13 20 97 |29 31 38 45 47
10 12 94 96 78 |35 37 44 46 28
11 18 100 77 84 |36 43 50 27 34
(3)在B象限所有行的中间格,自右向左,标出k-1格。
(注:6阶幻方由于k-1=0,所以不用再作B、D象限的数据交换),将这些格,和D象限相对位置上的数互换位置。
92 99 1 8 15 |67 74 26 58 65
98 80 7 14 16 |73 55 32 64 66
4 6 88 95 22 |54 56 38 70 72
85 87 19 21 3 |60 62 44 71 53
86 93 25 2 9 |61 68 50 52 59
--------------------------------------------------------->
17 24 76 83 90 |42 49 51 33 40
23 5 82 89 91 |48 30 57 39 41
79 81 13 20 97 |29 31 63 45 47
10 12 94 96 78 |35 37 69 46 28
11 18 100 77 84 |36 43 75 27 34
*****************************************************************************************************/
if(order%2==0&&order%4!=0) //单偶数
{
int matrixA[max][max],matrixB[max][max],matrixC[max][max],matrixD[max][max],matrix[max][max];
int a[size][size],b[size][size],c[size][size],d[size][size];
//将每个象限的数组变成奇数阶
jishujie(matrixA,1,order*order/4,order/2);
jishujie(matrixB,1+order*order/2,order*order*3/4,order/2);
jishujie(matrixC,1+order*order*3/4,order*order,order/2);
jishujie(matrixD,1+order*order/4,order*order/2,order/2);
int k=(order-2)/4;
if(k==1)
{
//从A象限中间行中间格开始,按自左向右的方向,标出K格。A象限的其他行则标出最左行的K格,与C相同位置的数进行互换
for(int i=0;i<order/2;i++) //把A,C象限需要交换的数保留起来
for(int j=0;j<k;j++)
{
if(i==order/4)
{
for(int p=order/4,r=0;r<k;r++,j++,p++) //r用来控制循环次数
{
a[i][j]=matrixA[i][p];
c[i][j]=matrixC[i][p];
}
break; //终止内循环,开始下一次外循环. 且i自增1,即从order/4+1开始
}
else
{
a[i][j]=matrixA[i][j];
c[i][j]=matrixC[i][j];
}
}
for(int i=0;i<order/2;i++) //交换AC象限的数
for(int j=0;j<k;j++)
{
if(i==order/4)
{
for(int p=order/4,r=0;r<k;r++,j++,p++) //r用来控制循环次数
{
matrixA[i][p]=a[i][j];
matrixC[i][p]=c[i][j];
}
break; //终止内循环,开始下一次外循环. 且i自增1,即从order/4+1开始
}
else
{
matrixA[i][j]=c[i][j];
matrixC[i][j]=a[i][j];
}
}
test__print(matrix,matrixA,matrixB,matrixC,matrixD,order);
cout<<"请输入阶数:";
}
else
{
//从A象限中心的数 向右标出K格,与C相同位置的数进行交换
for(int i=0;i<order/2;i++) //把A,C象限需要交换的数保留起来
for(int j=0;j<k;j++)
{
if(i==order/4)
{
for(int p=order/4,r=0;r<k;r++,j++,p++) //r用来控制循环次数
{
a[i][j]=matrixA[i][p];
c[i][j]=matrixC[i][p];
}
break; //终止内循环,开始下一次外循环. 且i自增1,即从order/4+1开始
}
else
{
a[i][j]=matrixA[i][j];
c[i][j]=matrixC[i][j];
}
}
for(int i=0;i<order/2;i++) //把A,C象限需要交换的数保留起来
for(int j=0;j<k;j++)
{
if(i==order/4)
{
for(int p=order/4,r=0;r<k;r++,j++,p++) //r用来控制循环次数
{
matrixA[i][p]=a[i][j];
matrixC[i][p]=c[i][j];
}
break; //终止内循环,开始下一次外循环. 且i自增1,即从order/4+1开始
}
else
{
matrixA[i][j]=c[i][j];
matrixC[i][j]=a[i][j];
}
}
//交换BD象限的数
for(int i=0;i<order/2;i++) //把BD象限需要交换的数保留起来
for(int j=order/4;j>1;j--)
{
b[i][j]=matrixB[i][j];
d[i][j]=matrixD[i][j];
}
for(int i=0;i<order/2;i++) //交换BD象限的数
for(int j=order/4;j>1;j--)
{
matrixB[i][j]=d[i][j];
matrixD[i][j]=b[i][j];
}
test__print(matrix, matrixA, matrixB,matrixC,matrixD,order);
cout<<"请输入阶数:";
}
}
}
getch();
return 0;
}
int test____print(int matrix[max][max],int order) //双偶数的输出函数
{
int m=0;
for(int i=0;i<order;i++)
for(int j=0;j<order;j++)
{
m++;
cout<<matrix[i][j]<<"\t";
if(m%order==0)
cout<<endl<<endl;
}
cout<<endl;
}
void jishujie(int matrix[max][max],int x,int y,int ord) //将单偶数每个象限的数奇数阶化
{
int row=0,coclum=ord/2;
for(int count=x;count<=y;count++)
{
matrix[row][coclum]=count;
if(count%ord==0)
row++;
else
{
row=(row==0)? ord-1:row-1;
coclum=(coclum==ord-1)? 0:coclum+1;
}
}
}
//将ABCD四个象限的数付给数组matrix[][],使得单偶数以矩阵的形式输出
void test__print(int matrix[max][max],int matrixA[max][max],int matrixB[max][max],int matrixC[max][max],int matrixD[max][max],int ord)
{
for(int i=0;i<ord/2;i++) //将A象限的数付给matrix[][]的第一个1/4
for(int j=0;j<ord/2;j++)
matrix[i][j]=matrixA[i][j];
for(int i=0,m=0;i<ord/2;i++,m++) //将B象限的数付给matrix[][]第二个的1/4
for(int j=ord/2,n=0;j<ord;j++,n++)
matrix[i][j]=matrixB[m][n];
for(int i=ord/2,m=0;i<ord;i++,m++) //将C象限的数付给matrix[][]的第三个1/4
for(int j=0,n=0;j<ord/2;j++,n++)
matrix[i][j]=matrixC[m][n];
for(int i=ord/2,m=0;i<ord;i++,m++) //将D象限的数付给matrix[][]的第四个1/4
for(int j=ord/2,n=0;j<ord;j++,n++)
matrix[i][j]=matrixD[m][n];
int m=0;
for(int i=0;i<ord;i++)
for(int j=0;j<ord;j++)
{
m++;
cout<<matrix[i][j]<<"\t";
if(m%ord==0)
cout<<endl<<endl;
}
}
我的幻方
最新推荐文章于 2019-03-23 14:05:18 发布