程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> 編程綜合問答 >> c-請教一下魔方陣的問題。。

c-請教一下魔方陣的問題。。

編輯:編程綜合問答
請教一下魔方陣的問題。。

(每一行每一列以及對角線之和都相等的方陣)
要求輸出1--n*n的魔方陣
(。。用的方法不好。。但是不知道哪裡錯了>_<)

#include
#include
int main()
{
int m[15][15],k,n,i,j;
for(n=2;n%2==0;)
{printf("enter your number:");
scanf("%d",&n);}
for(k=1,i=1,j=(n+1)/2;k<=n;k++)
{
m[i][j]=k;
if(i==1)
{
if(j==n)
{
l=m[n][1];
if(l==0) {m[n][1]=k+1;i=n;j=1;}
else {m[i+1][j]=k+1;i=i+1;}
}
else {
l=m[n][j+1];
if(l==0) {m[n][j+1]=k+1;i=n;j=j+1;}
else {m[i+1][j]=k+1;i=i+1;}
}
}
else
{
if(j==n)
{
l=m[i-1][1];
if(l==0) {m[i-1][1]=k+1;i=i-1;j=1;}
else {m[i+1][j]=k+1;i=i+1;}
}
}
l=m[i-1][j+1];
if(l==0) {m[i-1][j+1]=k+1;i=i-1;j=j+1;}
else {m[i+1][j]=k+1;i=i+1;}
}

for(i=1;i<=n;i++)
{ for(j=1;j<=n;j++)
printf("%d\t",m[i][j]);
printf("\n");
}

return 0;}

最佳回答:


 // app2.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

#include<stdio.h>
#include<math.h>
#define MAX 30
int a[MAX][MAX];    // 幻方矩陣
int n,s;    // n:階數,s:幻方數
int x,y;
int i,j,k;
int total,m;
int ox,oy;
void main()
{
    void odd(int m, int index);
    void singleEven();
    void FourXFour();
    void doubleEven();

    do
    {
        printf("Please input n(3<=n[<=17]):\t");    // 屏幕可顯示的最大階數為17
        scanf("%d",&n);
        if(n<3) continue;   // 幻方最小階數
        s=n*(pow(n,2)+1)/2; // 幻方數
        printf("s=%d\n",s);
        if(n%2==1){
            // 奇階幻方
            ox=oy=0;
            odd(n,0);   // 從1開始填寫n階幻方
        }
        else if(n%4==0)
        {
            // 雙偶階幻方
            doubleEven();

        }
        else if(n%2==0)
        {
            // 單偶階幻方
            singleEven();

        }
        // 輸出制作好的n階幻方
        for(i=0;i<n;i++)
        {
            s=0;
            for(j=0;j<n;j++)
                s+=a[i][j],printf("%4d",a[i][j]);
            printf("\t=%d\n",s);
        }
        fflush(stdin);  // 清除多余或無效的輸入
    }while(1);
}
/* 奇數階幻方
最經典的填法是羅伯特法(樓梯法),填寫方法是這樣:
把1(或最小的數)放在第一行正中;按以下規律排列剩下的n×n-1個數: 
(1)每一個數放在前一個數的右上一格;
(2)如果這個數所要放的格已經超出了頂行那麼就把它放在底行,仍然要放在右一列;
(3)如果這個數所要放的格已經超出了最右列那麼就把它放在最左列,仍然要放在上一行;
(4)如果這個數所要放的格已經超出了頂行且超出了最右列,那麼就把它放在前一個數的下一行同一列的格內;
(5)如果這個數所要放的格已經有數填入,處理方法同(4)。
這種寫法總是先向“右上”的方向,象是在爬樓梯。
三階幻方:
   8   1   6
   3   5   7
   4   9   2    */
// 解奇階幻方的通用模塊
// m 為階數
// index 為起始標識
void odd(int m, int index)
{
    x=m/2;
    y=0;
    for(i=index+1;i<=index+pow(m,2);i++)
    {
        a[oy+y][ox+x]=i;
        if(i%m==0) y++;
        else x++,y--;
        // else x++,y+=2; Hourse法
        x=(x%m+m)%m;
        y=(y%m+m)%m;
    }
}
/* 單偶階幻方
n為偶數,且不能被4整除 (n=6,10,14,18,22……;n=4k+2,k=1,2,3,4,5……)
以n=10為例。這時,k=2
(1) 把方陣分為A,B,C,D四個象限,這樣每一個象限肯定是奇數階。
用樓梯法,依次在A象限,D象限,B象限,C象限按奇數階幻方的填法填數。
6階幻方第一步:
   8   1   6 | 26  19  24
   3   5   7 | 21  23  25
   4   9   2 | 22  27  20
-------------------------
  35  28  33 | 17  10  15
  30  32  34 | 12  14  16
  31  36  29 | 13  18  11
(2) 在A象限的中間行、中間格開始,按自左向右的方向,標出k格。
A象限的其它行則標出最左邊的k格。
將這些格,和C象限相對位置上的數,互換位置。
6階幻方第二步:
  35*  1   6 | 26  19  24
   3  32*  7 | 21  23  25
  31*  9   2 | 22  27  20
-------------------------
   8* 28  33 | 17  10  15
  30   5* 34 | 12  14  16
   4* 36  29 | 13  18  11
(3) 在B象限任一行的中間格,自右向左,標出k-1列。
(注:6階幻方由於k-1=0,所以不用再作B、D象限的數據交換)
將B象限標出的這些數,和D象限相對位置上的數進行交換,就形成幻方。
6階幻方:
  35   1   6 | 26  19* 24
   3  32   7 | 21  23* 25
  31   9   2 | 22  27* 20
-------------------------
   8  28  33 | 17  10* 15
  30   5  34 | 12  14* 16
   4  36  29 | 13  18* 11   */
void singleEven()
{
    int temp;
    // 步驟一
    // A象限
    ox=oy=0;
    odd(n/2,pow(n/2,2)*0);
    // D象限
    ox=oy=n/2;
    odd(n/2,pow(n/2,2)*1);
    // B象限
    ox=n/2,oy=0;
    odd(n/2,pow(n/2,2)*2);
    // C象限
    ox=0,oy=n/2;
    odd(n/2,pow(n/2,2)*3);
    // 對已經按ADBC象限以奇階方式填充的幻方做處理
    m=(n-2)/4;
    for(i=0;i<n/2;i++)
    {   
        // 步驟二
        for(j=0;j<m;j++)
        {
            k=(i==n/4)?n/4+j:j;
            temp=a[i][k];
            a[i][k]=a[i+n/2][k];
            a[i+n/2][k]=temp;
        }
        // 步驟三
        for(j=0;j<m-1;j++)
        {
            k=n/2+n/4+j;
            temp=a[i][k];
            a[i][k]=a[i+n/2][k];
            a[i+n/2][k]=temp;
        }
    }
}
/* 雙偶階幻方
n為偶數,且能被4整除 (n=4,8,12,16,20……;n=4k,k=1,2,3,4,5……)
互補:如果兩個數字的和,等於幻方最大數和最小數的和,即 n*n+1,稱為互補。*/
/* 四階幻方
將數字從左到右、從上到下按順序填寫:
   1   2   3   4
   5   6   7   8
   9  10  11  12
  13  14  15  16
將對角線上的數字,換成與它互補的數字。
這裡,n×n+1 = 4×4+1 = 17;
把1換成17-1 = 16;
把6換成17-6 = 11;
把11換成17-11 = 6;
把16換成17-16 = 1;
……
換完後就是一個四階幻方。
  16*  2   3  13*
   5  11* 10*  8
   9   7*  6* 12
   4* 14  15   1* */
void FourXFour()
{
    // 對已填寫數字的4階幻方進行對角線互補替換
    for(i=0;i<4;i++)
    {
        a[oy+i][ox+i]=total-a[oy+i][ox+i];
        a[oy+i][ox+(4-i-1)]=total-a[oy+i][ox+(4-i-1)];
    }
}
/* 對於n=4k階幻方,我們先把數字按順序填寫。
   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*4把它劃分成k*k個方陣。
因為n是4的倍數,一定能用4*4的小方陣分割。
   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
然後把每個小方陣的對角線上的數字換成互補的數字,就構成幻方。
  64*  2   3  61*| 60*  6   7  57*
   9  55* 54* 12 | 13  51* 50* 16
  17  47* 46* 20 | 21  43* 42* 24
  40* 26  27  37*| 36* 30  31  33*
---------------------------------
  32* 34  35  29*| 28* 38  39  25*
  41  23* 22* 44 | 45  19* 18* 48
  49  15* 14* 52 | 53  11* 10* 56 
   8* 58  59   5*|  4* 62  63   1* */
void doubleEven()
{
    // 填寫數字
    x=y=0;
    for(i=1;i<=pow(n,2);i++)
    {
        a[y][x]=i;
        if(i%n==0) x=0,y++;
        else x++;
    }
    total=1+pow(n,2);   // 最大數和最小數的和
    // 以 4x4 大小分割幻方
    m=n/4;
    x=y=0;
    ox=oy=0;
    for(k=1;k<=pow(m,2);k++)
    {
        // 對每個 4x4 幻方做對角互補替換
        FourXFour();
        if(k%m==0) ox=0,oy+=4;
        else ox=k%m*4;  // 轉移到下一個 4x4 幻方
    }
}

Please input n(3<=n[<=17]): 3
s=15
8 1 6 =15
3 5 7 =15
4 9 2 =15
Please input n(3<=n[<=17]): 5
s=65
17 24 1 8 15 =65
23 5 7 14 16 =65
4 6 13 20 22 =65
10 12 19 21 3 =65
11 18 25 2 9 =65
Please input n(3<=n[<=17]):

源程序略有點問題,我順手修改了
出處
http://blog.csdn.net/cmutoo/article/details/5487157

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved