幻方编程
⑴ 幻方 问题 n 幻方编程问题
n(n为奇数)阶幻方实现方法:
⑴ 将1放在第一行中间一列;
⑵ 从2开始直到n×n止各数依次按下列规则存放按45°方向行走,如向右上每一个数存放的行比前一个数的行数减1,列数加1
⑶ 如果行列范围超出矩阵范围,则回绕,例如1在第1行,则2应放在最下一行,列数同样加1; ⑷ 如果按上面规则确定的位置上已有数,或上一个数是第1行第n列时则把下一个数放在上一个数的下面。
代码如下:
#include"stdio.h"
#include"math.h"
int a[10][10]; //定义一个二维数组存放数据,大小根据测试的阶数确定
void ins(int n)
{
int x,y,m;
x=0;
y=n/2;
for(m=1;m<=n*n;m++) //依次将1~n*n赋值给二维数组
{
a[x][y]=m;// 将1放在第一行中间一列
if(m%n!=0)
{
x--; // 从2开始直到n×n止各数依次按下列规则存放:按45度方向行走
y++;
if(x<0) // 如果行列范围超出矩阵范围,则回绕
x=x+n;
if(y==n)
y=n-y;
}
else
{
x++;
if(x==n)
x=x-n;
}
}
}
main()
{
int i,j,n;
scanf("%d",&n);//输入阶数
ins(n); //调用函数
for(i=0;i<n;i++) //打印出幻方
{
for(j=0;j<n;j++)
printf("%4d",a[i][j]); //格式化输出
puts(""); //打印2个空行
puts("");
}
getch(); //win_TC下的语句用于停住画面,其他开发环境下无需
}
⑵ 4×4幻方 C++
#include<iostream.h>
#include<iomanip.h>
#include<string>
#define max 100
int magic[max][max];
class HF //幻方
{
private:
int n; //幻方的阶乘数
int x,y; //数组的下标,X轴 Y轴
int i,j; //循环变量
int di,dx,dy; //单偶数幻方用
int oucs; //偶数常数
int temp;
public:
void accept(); //接受数据
void jshf(); //奇数阶乘幻方
void souhf(); //双偶数幻方
void dsouhf(); //单偶数幻方
void operate(); //运算 组合
void display(); //显示结果
};
void HF::accept() //接受数据
{
cout<<"请输入幻方的阶乘数 n : ";
cin >>n;
}
void HF::jshf() //奇数幻方 (2n+1)(连续摆数法)
{
x=n/2,y=0; //X Y表示 数轴(设左上角为(0,0))
for (i=1;i<=n*n;i++)
{
magic[y][x] =i; //给x*y个格子赋值
if (i%n==0) //右上角有数,放在下面
y++;
else if (y==0) //超出上边界
x++,y=n-1;
else if (x==n-1) //超出右边界
x=0,y--;
else ///正常情况
x++,y--;
}
}
void HF::souhf() //双偶数幻方(对称法)
{
for (x=0;x<n/2;x++) //两个for 就提取四分之一的数 (左上角)
for (y=0;y<n/2;y++)
if((x+y)%2==0) //等价于书上涂黄格 做标记
{
magic[x][y]= -1;
magic[x][n-y-1]= -1;
magic[n-x-1][y]= -1;
magic[n-x-1][n-y-1]= -1;
}
for(x=0;x<n;x++)
for(y=0;y<n;y++)
{
oucs=x*n+y; //oucs为偶数常数
if(magic[x][y]== -1) //给做标记的数赋值
magic[x][y]=n*n-oucs;
else
magic[x][y]=oucs+1; //给未做标记的数赋值
}
}
void HF::dsouhf() //单偶数阶(2(2m+1))幻方(斯特雷奇法)
{
for (di=0;di<4;di++) //幻方的分块
{
switch (di)
{
case 0: //左上的一块 A
dx=0,dy=0;
break;
case 1: //右下的一块 B
dx=n/2,dy=n/2;
break;
case 2: //右上的一块 C
dx=n/2,dy=0;
break;
case 3: //左下的一块 D
dx=0;dy=n/2;
break;
default:
break;
}
x=(n/2)/2,y=0; // 1/4 的 第一行中间的数
int nhsq; // 1/2 n的平方
nhsq=(n/2)*(n/2);
for (i=1;i<=nhsq;i++)//给双偶数幻方赋值
{
magic[y+dy][x+dx]=i+nhsq*di;
if(i % (n / 2) == 0) //右上角有数
y++;
else if(y==0) //当超出上面的边界时
x++,y=n/2-1;
else if(x == n / 2 - 1) //当超出右面的边界时
x=0,y--;
else //正常情况下
x++,y--;
}
}
int nm;
nm=(n / 2 - 1) / 2 ;
for (j=1;j<nm+1;j++) //交换A和D的第二行起m个数字 J指的是数组的列
{
temp=magic[(n/2)/2][j];
magic[(n/2)/2][j]=magic[(n/2+1)/2+n/2-1][j];//把A中的 中间一行,第二个数开始M个数(左上1/4)给D
magic[(n/2+1)/2+n/2-1][j]=temp; //把D中间一行,第二个数开始M个数(左下1/4)给A
}
for (i=0;i<n/2;i++) //交换A和D其它行的数字
{
if(i==(n/2)/2) ////I指的是数组的行
continue; //如果到了中间的数,跳出循环
for(j=0;j<nm;j++)
{
temp = magic[i][j];
magic[i][j]=magic[n/2+i][j];
magic[n/2+i][j]=temp;
}
}
for (i=0;i<n/2;i++) //交换C和B最后m-1行的数字
for (j=n-1;j>n-nm;j--)
{
temp=magic[i][j];
magic[i][j]=magic[n/2+i][j];
magic[n/2+i][j]=temp;
}
}
void HF::operate()
{
system("cls");
cout <<setw(45)<<" 幻方的制作 "<<endl;
cout <<setw(45)<<"==================================="<<endl;
cout <<setw(45)<<" "<<endl;
cout <<setw(49)<<" 1. 奇数阶幻方 "<<endl;
cout <<setw(49)<<" 2. 偶数阶幻方 "<<endl;
cout <<setw(47)<<" 请选择(1或2,0:退出) "<<endl;
cout <<setw(45)<<"==================================="<<endl;
int choice;
cout<<"请输入选择:";
cin>>choice;
if(choice==1)
{
accept(); //调用接受的数据
if (n%2==0 ||n<=0)
cout <<"错误,请输入正奇数: "<<endl;
else
{
jshf(); //调用奇数阶乘幻方的计算
display(); //调用显示结果
}
}
else if (choice == 2)
{
accept(); //调用接受的数据
if(n==2)
cout <<"2 不存在幻方"<<endl;
else
{
if(n%2==1 || n<=0)
cout <<"错误,请输入正偶数:"<<endl;
else if (n%4==0)
{
souhf(); //调用双偶阶乘幻方的计算
display(); //调用显示结果
}
else
{
dsouhf(); //调用单双偶阶乘幻方的计算
display(); //调用显示结果
}
}
}
else if (choice==0)
cout <<"本次执行终止 ! !"<<endl;
else
cout <<"本次执行终止 : 原因 错误的输入 "<<endl;
}
void HF::display() //显示结果
{
cout<<endl;
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
cout<<setw(4)<<magic[i][j];
cout<<endl<<endl;
}
}
void main()
{
HF hf;
char replay;
replay='y';
while (replay='y') //循环操作
{
hf.operate();
cout<<endl<<endl<<"还想再来一次吗?是(y),否(按任意键) ";
cin>>replay;
cout<<endl<<endl;
if(replay !='y')
return ;
}
}
⑶ 五阶幻方(要填入的数字是1-25)
18 24 `5 `6 12
10 11 17 23 `4
22 `3 `9 15 16
14 20 21 `2 `8
1` 7` 13 19 25
9 `3 22 16 15
21 20 14 `8 `2
13 `7 `1 25 19
5 `24 18 12 `6
17 11 10 `4 23
17 24 `1 8 15
23 `5 `7 14 16
`4 `6 13 20 22
10 12 19 21 `3
11 18 25 `2 `9
下面这些构造方法都是比较适合于编程的.构造幻方分奇数阶幻方、4n型偶数幻方、4n+2型的偶数幻方(以下简称双偶数、单偶数).
构造奇数阶较简单,常用的是连续摆数法.下面的n均指阶数,在这里(y,x)表示第y横行的第x个数.
(1)在第一行的正中间(即[1,(n+1)/2])放上1 (2)若数a的位置在(y,x),则a+1的位置在:(y-1,x+1),若有这个位子且里面没数 (n,x+1),若y=1且x1 (y+1,x),若x=n且y=1或(y,x)已经有数.(y,x)已经有数的充要条件是a=n(mod n) (3)所构成的(n×n)方即为一个幻方.
我们还可以把连续摆数法推广,先定义几个概念:
普通向量:正常走步的情况.(即上面第一种情况)正常走步记作(b,a).中断向量:即走到(1,n)这个格子或(y,x)已经有数的情况.记作(d,c) 下面是几个推广的情况:(1,-1)(0,1);(1,-1)(0,2);(2,1)(1,-2);(2,1)(1,-1);(2,1)(1,0);(2,1)(1,2)
下面是构造双偶数阶幻方:
对称法:把双偶数型的幻方分成四个正方形,在左上角正方形中每行每列各取一半打上○(实际上就是使无论从每行还是每列来看都刚好有一半有○,一半无○.)然后向剩下的三个小方块中映象(镜像对称),于是整个方阵都布好了○.(用电脑实行则可以选择在该布○的地方填上-1).
接下来该填数了.适用于电脑的方法:向所有格子内填数,(推荐x,y分别从1~n的双重计数循环):若(y,x)没有○,则填入(y-1)*n+x;若(y,x)中有○,则填入(n-y+1)*n+x+1.适用于笔算的方法:从左上角依次1~n*n填数,遇上○则不填,这个数字还是要跳过去.填完后,把方阵旋转180度后再从1~n*n往○里填数,没有○的地方就不填,跳过数字.因为对称的原理,因此这回填的数刚好是上次跳过的数,这次跳过的刚好是上次填过的数.就形成了一个双偶数阶幻方.
下面介绍一下构造单偶数阶幻方的方法——斯特雷奇法
仍然是把单偶数阶幻方分成A、B、C、D四个小方阵,若按平面直角坐标系来看则第一、二、三、四象限分别为A、C、B、D(请一定注意A、B、C、D的位置!)再用连续摆数法将A、B、C、D填入数字,A方阵用1~a^2,B方阵用(a^2+1)~2a^2,C方阵用(2a^2+1)~3a^2,D用数字(3a^2+1~4a^2).其中a=n/2.
这样的方阵还需进行调整.在A的中间一行左侧第2列起取m个方格(这里m=(n-2)/4),即取((n/4+0.5),2)~((n/4+0.5),(2+m))这几个方格,再取A中其它行的左边m个方格.把这些方格中的数字同D中相应方格中的数字对调.然后在C中各列的从右边起的m-1个方格重的数字同B中对调.
这样形成的大方阵就是幻方了.
⑷ 怎样用c语言编写幻方
你的这个问题实际上包括两个问题:
1、幻方的算法
2、怎样用C语言实现幻方的算法
这两个问题是大不同的。
关于幻方的算法,或者叫幻方填法,目前有很多种,拉丁正交、马步法等等,针对奇数或者偶数(又分单偶数和双偶数)等有不同的算法,但这些算法只是帮你找到幻方的一个或多个实例(不会是全部),而同阶数的幻方到底有多少个,那只有用穷举法了,比如4阶幻方,基本4阶幻方共7040个,剔除旋转翻转的,即具有独立结构的共880个;4阶完美幻方共84个,具有独立结构的共48个。
对于高阶幻方(比如超过8阶),穷举法实际上是不可行的,因为它的穷举时间将是天文数字(以目前主流PC),所以不要试图用计算机穷举高阶幻方的全部结果,那将是徒劳的。
如果你只是需要1个实例,那么推荐你使用MATLAB语言工具,因为它提供了幻方函数magic(n),不需要编程,直接从命令窗口输入就可以得到答案。
至于第二个问题,当然你首先会C语言,剩下的就是编程技巧问题了,而这个问题是无从回答的。相信你问的是第一个问题。
以上的回答虽然没有明确给出答案,但相信对你会有帮助。
⑸ 如何用c语言编程使三阶幻方不等
这个打印n阶的 0<n<=15是奇数 我在下面帮你改了个3阶的
/* bookp33.c 打印魔方阵程序 */
/* 谭浩强,C程序设计题解与上机指导,33页 */
/* 在tc30下编译通过 */
/* 2001.12.12 */
void main()
{
int a[16][16],i,j,k,p,m,n;
p=1;
while(p==1)
{ printf("请输入n.(0<n<=15,n是奇数.)\n");
scanf("%d",&n);
if((n>=0)&&(n<=15)&&(n%2!=0))
{ printf("矩阵阶数是:%d\n",n);
p=0;
}
}
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
a[i][j]=0;
/* 建立魔方阵 */
j=n/2+1;
a[1][j]=1;
for(k=2;k<=n*n;k++)
{ i=i-1;
j=j+1;
if((i<1)&&(j>n))
{ i=i+2;
j=j-1;
}
else
{if(i<1) i=n; if(j>n) j=1; }
if(a[i][j]==0)
a[i][j]=k;
else
{ i=i+2;
j=j-1;
a[i][j]=k;
}
}
/* 输出 */
for(i=1;i<=n;i++)
{ for(j=1;j<=n;j++)
printf(" %3d",a[i][j]);
printf("\n");
}
}
*************3阶的************
int main()
{
int a[16][16],i,j,k,n;
n=3;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
a[i][j]=0;
/* 建立魔方阵 */
j=n/2+1;
a[1][j]=1;
for(k=2;k<=n*n;k++)
{ i=i-1;
j=j+1;
if((i<1)&&(j>n))
{ i=i+2;
j=j-1;
}
else
{if(i<1) i=n; if(j>n) j=1; }
if(a[i][j]==0)
a[i][j]=k;
else
{ i=i+2;
j=j-1;
a[i][j]=k;
}
}
/* 输出 */
for(i=1;i<=n;i++)
{ for(j=1;j<=n;j++)
printf(" %3d",a[i][j]);
printf("\n");
}
return (1);
}
⑹ C语言编程幻方输入问题
#include <stdio.h>
#define N 3
int fun(int (*a)[N])
{ int i,j,m1,m2,row,colum;
m1=m2=0;
%判断对角线的和不否相等 不相等返回0
for(i=0; i<N; i++)
{ j=N-i-1; m1+=a[i][i]; m2+=a[i][j]; }
if(m1!=m2) return 0;
for(i=0; i<N; i++) {
/**********found**********/
row=colum=0;
%判断行row 列colum的和 是否相等 不相等返回0
for(j=0; j<N; j++)
{ row+=a[i][j]; colum+=a[j][i]; }
/**********found**********/
if( (row!=colum) || (row!=m1) ) return 0;
}
/**********found**********/
%判断完毕是幻方返回1
return 1;
}
main()
{ int x[N][N],i,j;
%输入矩阵x
printf("Enter number for array:\n");
for(i=0; i<N; i++)
for(j=0; j<N; j++) scanf("%d",&x[i][j]);
printf("Array:\n");
%输出矩阵
for(i=0; i<N; i++)
{ for(j=0; j<N; j++) printf("%3d",x[i][j]);
printf("\n");
}
%根据fun的值输出结果
if(fun(x)) printf("The Array is a magic square.\n");
else printf("The Array isn't a magic square.\n");
}
你要是符合C规则的矩阵输入方法否可以啊??? 你看输出矩阵那块 输出的矩阵跟你输入的是不是一样啊 要是一样 结果都是对的 一般的就是 列之间用空格 行之间用回车 这段程序的重点是为什么把 判断对角线写在前面吧????要是顺序反了 判断是不全面的
⑺ 六阶幻方怎么解
下面是六阶幻方的其中一个答案:
=================================================
28 4 3 31 35 10
36 18 21 24 11 1
7 23 12 17 22 30
8 13 26 19 16 29
5 20 15 14 25 32
27 33 34 6 2 9
注意:这个幻方的每行每列对角线的六个数之和为111(幻和为111),还有一个特点就是中间的十六个数也构成一个四阶幻方哦,幻和为74。希望满意答案。
=====================================================================
下面介绍一下奇数幻方,双偶,单偶幻方的常见规律。
一、 N 为奇数时,最简单。
(1) 将1放在第一行中间一列;
(2) 从2开始直到n×n止各数依次按下列规则存放:
按 45°方向行走,如向右上
每一个数存放的行比前一个数的行数减1,列数加1
(3) 如果行列范围超出矩阵范围,则回绕。
例如1在第1行,则2应放在最下一行,列数同样加1;
(4) 如果按上面规则确定的位置上已有数,或上一个数是第1行第n列时,
则把下一个数放在上一个数的下面。
============================
二、 N为4的倍数时
采用对称元素交换法。
首先把数1到n×n按从上至下,从左到右顺序填入矩阵
然后将方阵的所有4×4子方阵中的两对角线上位置的数关于方阵中心作对
称交换,即a(i,j)与a(n-1-i,n-1-j)交换,所有其它位置上的数不变。
(或者将对角线不变,其它位置对称交换也可)
===========================
三、N 为其它偶数时
当n为非4倍数的偶数(即4n+2形)时:首先把大方阵分解为4个奇数(2m+1阶)子方阵。
按上述奇数阶幻方给分解的4个子方阵对应赋值
上左子阵最小(i),下右子阵次小(i+v),下左子阵最大(i+3v),上右子阵次大(i+2v)
即4个子方阵对应元素相差v,其中v=n*n/4
四个子矩阵由小到大排列方式为 ① ③
④ ②
然后作相应的元素交换:a(i,j)与a(i+u,j)在同一列做对应交换(j<t或j>n-t+2),
a(t-1,0)与a(t+u-1,0);a(t-1,t-1)与a(t+u-1,t-1)两对元素交换
其中u=n/2,t=(n+2)/4 上述交换使每行每列与两对角线上元素之和相等。
=================================================================
下面给出C语言编程实现任意幻方的解答:
========================
#include"stdio.h"
#include"math.h"
int a[256][256];
int sum;
int check();
void ins(int n);
main()
{
int i,j,n,k,t,p,x;
scanf("%d",&n);
sum=(n*n+1)*n/2;
if(n%2==1)//奇数幻方
{
ins(n);
k=n;
}
if(n%4==2)//单偶数幻方
{
k=n/2;
ins(k);
for(i=0;i<k;i++)
for(j=0;j<k;j++)
{
a[j+k]=a[j]+2*k*k;
a[i+k][j]=a[j]+3*k*k;
a[i+k][j+k]=a[j]+k*k;
}
t=(n-2)/4;
for(i=0;i<k;i++)
for(j=0;j<k;j++)
{
if((j<t)&&(i<t))
{
p=a[j];a[j]=a[i+k][j];a[i+k][j]=p;
}
if((j<t)&&(i>k-t-1))
{
p=a[j];a[j]=a[i+k][j];a[i+k][j]=p;
}
if((i>=t&&i<=k-t-1)&&(j>=t&&j<t*2))
{
p=a[j];a[j]=a[i+k][j];a[i+k][j]=p;
}
if(j>1&&j<=t)
{
p=a[j+k];a[j+k]=a[i+k][j+k];a[i+k][j+k]=p;
}
}
}
if(n%4==0)//双偶数幻方
{
x=1;
for(i=0;i<n;i++)
for(j=0;j<n;j++)
a[j]=x++;
for(i=0;i<n;i++)
for(j=0;j<n;j++)
{
if(i%4==0&&abs(i-j)%4==0)
for(k=0;k<4;k++)
a[i+k][j+k]=n*n-a[i+k][j+k]+1;
else if(i%4==3&&(i+j)%4==3)
for(k=0;k<4;k++)
a[i-k][j+k]=n*n-a[i-k][j+k]+1;
}
}
if(check(n)==1)
{
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
printf("%5d",a[j]);
printf("\n");
}
return ;
}
}
int check(int n)//检验是否是幻方
{
int i,j,sum1=0,sum2;
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
sum1+=a[j];
if(sum1!=sum) return 0;
sum1=0;
}
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
sum1+=a[j];
if(sum1!=sum) return 0;
sum1=0;
}
for(sum1=0,sum2=0,i=0,j=0;i<n;i++,j++)
{
sum1+=a[j];
sum2+=a[n-j-1];
}
if(sum1!=sum) return 0;
if(sum2!=sum) return 0;
else return 1;
}
void ins(int n)//单偶数幻方的输入
{ int x,y,m;
x=0;y=n/2;
for(m=1;m<=n*n;m++)
{
a[x][y]=m;
if (m%n!=0)
{
x--;y++;
if(x<0) x=x+n;
if(y==n) y=n-y;
}
else
{
x++;
if(x==n) x=x-n;
}
}
}
=====================================
说明:以上C语言程序,复制到TXT文本,然后,另存为XXX.c文件,利用编程软件,编译这个文件,再保持到电脑,以后想用,直接点击就会运行。运行后,可以随意输入一个幻方阶数,就会自动生成一个幻方组合出来。
再说明一点:以上C程序仅供参考,我刚才编译过,因为是中文输入法输入的,所以不通过,需要把上边的标点符号切换到英文输入法,再输入才可以通过编译。
以下程序是可以通过编译,只是奇数幻方的C程序,还有,我命令它阶数范围是1~15阶的奇数幻方。
==================================
#include "stdio.h"
void main()
{
int a[18][18],i,j,k,p,n;
p=1;
while(p==1)
{
printf("Enter n(n=1 to
15):");
scanf("%d",&n);
if(n!=0 && n<=17 &&
n%2!=0)
p=0;
}
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
a[i][j]=0;
j=n/2+1;
a[1][j]=1;
for(k=2;k<=n*n;k++)
{
i--;
j++;
if(i<1 && j>n)
{
i+=2;
j--;
}
else
{
if(i<1) i=n;
if(j>n) j=1;
}
if(a[i][j]==0)
a[i][j]=k;
else
{
i+=2;
j--;
a[i][j]=k;
}
}
/*输出幻方阵*/
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
printf("%3d ",a[i][j]);
printf("\n");
}
system("pause");
}
==================================
第一:奇数幻方利用“楼梯法”和“杨辉法”很简单就能制作出来,可能上面描述的单偶,双偶幻方不是很详细,你可以上网查找一下相关资料,都会有图文解说的,很直观,规律看起来也很简单。
第二:关于编程可以解出幻方,可以进行了解,但是可不能一直只利用它哦,得自己琢磨推算幻方,例如利用推理法也可以把所有的幻方推算出来,这样才能更好地学习(我不用上面的规律也可以把任何一个幻方都推算出来,当然,高次幻方就相对比较难了)。