• ベストアンサー

配列を使って魔方陣

C言語を使って最近やっと配列ができるようになってきたんですが、どうしても魔方陣のやり方がわからないんです。教えてください。 魔方陣とは、1~n^2までの整数をn×nの正方形に並べ、どの行、どの列、どの対角線のn個の数の和も一定の値になるようにしたものです。 nは常に奇数を入力し、1番上の行の中央の列に1を置く事になります。 整数kまで置かれているとすると、k+1は次のように置かれる。 * kの置かれた場所の右斜め上(以下この場所をαと呼ぶ)が空いていれば、そこにk+1を置く。 * αがすでに他の数が置かれているとき、kの置かれている場所のすぐ下にk+1を置く。 * αが右上隅にはみ出す場合は、kの置かれている場所のすぐ下にk+1を置く。 * αが1番上の行からはみ出す場合は、場所αの1番下の列にk+1を置く。 * αが1番右上の列からはみ出す場合には、場所αの1番左の列にk+1を置く。 例)n=3のとき 8 1 6 3 5 7 4 9 2 まだまだ初心者なので詳しく教えていただけると嬉しいです。よろしくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
  • gimmick
  • ベストアンサー率49% (134/270)
回答No.1

次のコードでできると思います。n=19までは大丈夫そうでした。インデントに全角スペースを使っているので適当に置換してください。 ------------------------------------------------- #include<stdio.h> #define SIZE 5 /*奇数を指定*/ int mahoujin[SIZE][SIZE]; int sum_yoko[SIZE], sum_tate[SIZE], sum_naname[2]; int main() {   int i, j;   int row, col;   /*初期化*/   row = 0;   col = SIZE / 2;   mahoujin[row][col] = 1;   /*配列への書き込み*/   for (i = 2; i <= (SIZE * SIZE); i++) {     if (row == 0 && col >= (SIZE -1))       row++;     else if (row == 0)       row = (SIZE - 1), col++;     else if (col >= (SIZE -1))       row--, col = 0;     else if (mahoujin[row - 1][col + 1] == 0)       row--, col++;     else       row++;     mahoujin[row][col] = i;   }   /*検証*/   for (i = 0; i < SIZE; i++) {     for (j = 0; j < SIZE; j++) {       sum_yoko[i] += mahoujin[i][j]; /*横方向の合計を各行について計算*/       sum_tate[i] += mahoujin[j][i]; /*縦方向の合計を各列について計算*/     }     sum_naname[0] += mahoujin[i][i]; /*左上から右下への合計*/     sum_naname[1] += mahoujin[i][SIZE - 1 - i]; /*右上から左下への合計*/   }   for (i = 0; i < SIZE; i++) {     if (sum_yoko[i] != sum_naname[0] || sum_tate[i] != sum_naname[0]) {       printf("魔方陣の生成に失敗しました\n");       return 0;     }   }   if (sum_naname[0] != sum_naname[1]) {     printf("魔方陣の生成に失敗しました\n");     return 0;   }   /*画面出力*/   printf("サイズ%dの魔方陣\n", SIZE);   for (i = 0; i < SIZE; i++) {     for (j = 0; j < SIZE; j++)       printf("%4d", mahoujin[i][j]);     printf("\n");   }   return 0; }

osiato
質問者

お礼

とても詳しい回答ありがとうございます。 自分で作ったプログラムは検証のところが旨くいってなかったみたいです。 これを参考にしながらもう1度プログラムしてみたいと思います。 大変ありがとうございました。

その他の回答 (2)

noname#4564
noname#4564
回答No.3

ついでに、「作成したプログラムにバグがないことをどうやって検証するか」考えるとよいでしょう。 プログラムの書き方はたんなる出発点に過ぎません。 効率のよいテスト方法を考えることは、よい勉強になります。

osiato
質問者

お礼

バグ・・・ですか。 プログラムを作成して実行すると、いつもエラーが出ていたのは検証してなかったせいなんですね。 もっと勉強したいと思います。 再回答ありがとうございました。

noname#4564
noname#4564
回答No.2

  プログラムの実装以前に、魔方陣の作り方(数学的な意味での「解法」)を確認しなければ、正しいコードを書けません。 数学の教科書、参考書等で確認してみてください。  

osiato
質問者

お礼

こんにちは。 魔方陣の作り方は紙に何度も書いて確認しているのですが、いざプログラムというとわからなくなってしまうんです。 それは私の力不足という訳で・・・(^^; 回答ありがとうございました。

関連するQ&A

  • 普遍的な魔方陣はありますか。

    各行・各列の和が一定の値になる、整数魔方陣、有理数魔方陣、実数魔方陣、複素数魔方陣、多元数魔方陣は、有り得ますか。

  • ラテン方陣と魔方陣

    魔方陣について、縦と横の和が同じで(斜めは考えない)、すべての数が一回ずつしか現れないものとします。ラテン方陣という縦の各列も横の各列も同じ数字が一回しか現れないものと定義づけます。このラテン方陣は作り方により2種類にわかれ、この2種のラテン方陣を組み合わせた方陣をオイラー方陣と名づけます。たとえば、3×3のラテン方陣は 123   123         312 と 231         231   312 となり、これを組み合わせた3次のオイラー方陣は       (1,1)(2,2)(3,3)       (3,2)(1,3)(2,1)       (2,3)(3,1)(1,2) となります。 これらの定義条件下において次の定理を証明してほしいのですが。 定理. n×nの二つのラテン方陣からできるオイラー方陣にお いて、nが奇数ならば、(1,1)、(1,2)、・・・(n,n)のすべての組が方陣内にちょうど一回ずつ現れる。 どうかよろしくお願いしますm(__)m       

  • 5次の超魔方陣の問題

    五次の超魔方陣を左右に一度ずつコピーした数の列をさらに上下に一度ずつコピーしてできる、全体で225個からなる数の表をこしらえる。この数表から、連続した5行5列のマスを任意に切り出す。このとき、この5行5列のマスはやはり超魔方陣になっている。この理由が何でしょうか?五次に魔方陣はなんとか出来ました。  11 24 7 20 3  これをコピーして225個から数の表を作ったのですが、そこ 4 12 25 8 16  からよく分かりません。どうすれば説明できるでしょうか? 17 5 13 21 9  10 18 1 14 22  23 6 19 2 15

  • 魔方陣

    9×9方陣は9個の3×3方陣に分けられるが 0から80の数を使ってこの9個の方陣も 行、列ともに同じ和になるような 9×9方陣(行、列ともに同じ和)を考えてください。

  • エクセルのVBAでの7×7の魔方陣とは……

    講義の宿題で7×7の魔方陣をVBAで解いてこいといわれました。 しかしながら自分のスキルではどうにもなりませんでした。 自分はIFやDim等までしか習っていません。 課題の注意点としては 1から49までの数値を検出 「1」は1行目の中央(4列目)に書き出す 基本的に、数値の書き出す順番は斜め上に移動 また、書き込む数値を「7」で割った場合の余りが「1」の時 書き込みの場所は下方向に移動する。 枠をはみ出した場合   上にはみ出した(行)の場合  7行目に   右にはみ出した(列)の場合  1列目に  それぞれ移動 以上のような条件でエクセルのVBEを用いて解きたいのですが、どうにも分かりません。自分でも様々なサイトで調べてみたところどれも難しすぎて理解できませんでした。 心優しき方は教えていただけると幸いです。 よろしくお願いします。

  • 魔方陣

    上辺中央から始めて右上斜に進みつつ、縁を越えたときは対辺に飛び、既に埋まった目に当たったときは下に逃げる。この方法で奇数字の魔方陣が生成されることの証明を御教示ねがえませんでしょうか。粗筋だけでも結構です。

  • 魔方陣のつくりかた

    JAVAを習い始めの初心者です。夏休みの宿題で「5×5の魔方陣を2次配列を使って作りましょう」という事なのですが、さっぱりです。問題は、 (1)全てのます目に0を代入し、0列の真中に1を入れる。 (2)最後に入れた位置の左斜め上の位置を候補位置とする。候補位置が欄外になる場合は、欄外にも魔方陣があるものと考え、対応する位置を候補位置とする。 (3)既に数字が設定されたいたら最後に入れた位置の右の位置に数字をいれる。 助けてください。よろしくお願いします。

  • ラテン方陣に関して

    1 2 3 4 5 2 3 4 5 1 3 4 5 1 2 4 5 1 2 3 5 1 2 3 4 のように、縦、横、同じ数が一度しか出でこない方陣を「ラテン方陣」と言うそうです。通常の「魔方陣」とは違って、「ラテン方陣」の場合、縦・横は絶対に合計が同じになりますが、対角の合計は同じでなくても、いいみたいです。 今、9 × 9 のラテン方陣が、全部で何通り、存在するのかや、それをコンピューターやソフトかなにかで、簡単に計算することができるのか、そういうことを頼める業者はないものなのかで、とても困っています。 9 × 9 のラテン方陣とは 1 2 3 4 5 6 7 8 9 2 3 4 5 6 7 8 9 1 3 4 5 6 7 8 9 1 2 4 5 6 7 8 9 1 2 3 5 6 7 8 9 1 2 3 4 6 7 8 9 1 2 3 4 5 7 8 9 1 2 3 4 5 6 8 9 1 2 3 4 5 6 7 9 1 2 3 4 5 6 7 8 ですが、この方陣の行と列をどのように入れ替えても、ラテン方陣、縦・横、同じ数字は一度しか出てこないラテン方陣ができ、その数は、きっと、ものすごい数のパターンがあると思います。 順番が1 2 3 4 5 6 7 8 9 でなくても、 1 3 5 7 9 2 4 6 8 3 5 7 9 2 4 6 8 1 5 7 9 2 4 6 8 1 3 7 9 2 4 6 8 1 3 5 9 2 4 6 8 1 3 5 7 2 4 6 8 1 3 5 7 9 4 6 8 1 3 5 7 9 2 6 8 1 3 5 7 9 2 4 8 1 3 5 7 9 2 4 6 のようなものもあります。 このようなラテン方陣を作成できるソフトや、何通りあるのかを調べるには、一体、どうしたらいいのでしょうか。 最後にもう一つだけお願いしたいのですが、とりあえずのところ、1 2 3 4 5 6 7 8 9という9個の数字の並べ方が、何通りあるのか、どなたか教えて下さい。 9の ! (階乗)で計算するのでしょうか?

  • n次の奇数魔方陣をつくるプログラム

    どうしてもエラーが出てしまいます。少なくとも、「int mahojin[n+1][n+1],i,j,k;」あたりの行が間違っているらしいのですが、なぜだかわかりません。アドバイスお願いします!!(スペースが上手く入らなくて、全角スペースを使ってますが気にしないでください。) #include<stdio.h> int main(void) {  int n;  printf("n(ただし、nは奇数)=?");scanf("%d",&n);  int mahojin[n+1][n+1],i,j,k;  j=(n+2)/2;i=0;  for(k=1;k<=n*n;k++){     if((k%n)==1)      i++;     else {      i--;j++;     }     if(i==0)      i=n;     if(j>n)      j=1;     mahojin[i][j]=k;   }   printf(" %d次の魔方陣 \n",n);   for(i=1;i<=n;i++){     for(j=1;j<=n;j++)      printf("%4d",mahojin[i][j]);     printf("\n");   }   return 0; }

  • 奇数魔方陣

    下記のプログラム(奇数魔方陣) について最初のfor文からどのような処理が行われているかわかりません。 { int mahoujin[10][10],x,y,i,n = 7; x = n / 2 + 1; y = 1; mahoujin[x][y] = 1; for( i = 2; i <= n * n; i++ ){ if( i % n == 1 ){ y = y + 1; }else{ x = x + 1; y = y - 1; } if( x > n ) x = 1; if( y < 1 ) y = n; mahoujin[x][y] = i; } for( y = 1; y <= n; y++ ){ for( x = 1; x <= n; x++ ){ printf( "%3d ", mahoujin[x][y] ); } printf( "\n" ); } 特にわからないのがif文で分岐になるところどのようなことが行われているかがわからないです。どなたか教えて頂けるとうれしいです。