幻方編程
⑴ 幻方 問題 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");
}
==================================
第一:奇數幻方利用「樓梯法」和「楊輝法」很簡單就能製作出來,可能上面描述的單偶,雙偶幻方不是很詳細,你可以上網查找一下相關資料,都會有圖文解說的,很直觀,規律看起來也很簡單。
第二:關於編程可以解出幻方,可以進行了解,但是可不能一直只利用它哦,得自己琢磨推算幻方,例如利用推理法也可以把所有的幻方推算出來,這樣才能更好地學習(我不用上面的規律也可以把任何一個幻方都推算出來,當然,高次幻方就相對比較難了)。