質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

再帰

情報工学における再帰とは、プログラムのあるメソッドの処理上で自身のメソッドが再び呼び出されている処理の事をいいます。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

Q&A

解決済

2回答

3475閲覧

ハノイの塔の経過の表示

grape_ll

総合スコア83

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

再帰

情報工学における再帰とは、プログラムのあるメソッドの処理上で自身のメソッドが再び呼び出されている処理の事をいいます。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

0グッド

0クリップ

投稿2020/06/12 08:12

質問内容

典型的なハノイの塔で左端のモノを右端に移すのですが,その途中経過の表示のアイデアがでません.
例えば,円盤が五枚のとき,次のようにする必要があります.
0が一番小さい円盤です.
01234 ..... .....
.1234 ..... ....0
..234 ....1 ....0
..234 ...01 .....    *一部です

私の考えとしては配列を
box[3][n]
みたいなかんじで作って,ないところには-1,あるところには円盤の番号を入れようと思ったのですが,再帰の理解が甘いせいもあって全然書き方が分からなくて進まないのですが,この方法を実現するための工夫や,他のアイデアなどを教えてほしいです.
コードは以下のようなところで止まっています.

コード

C

1#include<stdio.h> 2#include<stdlib.h> 3void hanoi(int N,int d); 4int box[3][10]; 5int main(void){ 6 int N; 7 scanf("%d",&N); 8 hanoi(N,1); 9 int i,j; 10 for(i=0;i<3;i++){ 11 for(j=0;j<N;j++){ 12 if(i==0) box[i][j]=i; 13 else box[i][j]=-1; 14 } 15 } 16 17 return 0; 18} 19 20void hanoi(int N,int d){ 21 if(N==0) return; 22 hanoi(N-,-d); 23 24 int i.j; 25 for(i=0;i<3;i++){ 26 for(j=0;j<N;j++){ 27 if() 28 } 29 } 30 31 hanoi(N-1,-d); 32}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

以前作ったプログラムですが、同じように柱にある円盤を配列で管理しています。
0が円盤なしで、1が一番小さな円盤です。
プログラムとしては特段説明するほどのものでも無く、良くあるハノイの塔を再帰で解くアルゴリズムです。円盤を移動するごとに配列を更新して、表示しています。
表示はお好みに合わせてどうぞ。

工夫というほどのものでは無いですが、円盤の管理がし易いように、一番上に載っている円盤の位置を記憶する配列を用意しています。-1が円盤なし、0が円盤一枚です。

c

1#include <stdio.h> 2#include <stdlib.h> 3 4#define N 10 //円盤の枚数(デフォルト) 5#define M 3 //柱の本数(固定) 6#define MAX 32 //円盤の上限 7 8int peg[M][MAX]; //柱の状態 9int top[M]; //柱の一番上 10 11//柱の状態を表示 12void disp(void) 13{ 14 for (int i = 0; i < M; i++) { 15 printf("%c:", 'A' + i); 16 for (int j = 0; j < MAX ; j++) { 17 if (peg[i][j] > 0) 18 printf("%3d", peg[i][j]); 19 } 20 printf("\n"); 21 } 22} 23 24//円盤を移動 25void move(int s, int d) 26{ 27 int n = peg[s][top[s]]; //sの柱の一番上 28 peg[s][top[s]] = 0; //円盤を削除 29 peg[d][top[d]+1] = n; //dの柱に移動 30 31 top[s]--; //sの柱を一枚減らす 32 top[d]++; //dの柱を一枚増やす 33} 34 35//ハノイの塔を解く 36void hanoi(int no, int x, int y) 37{ 38 if (no < 1) return; 39 40 hanoi(no - 1, x, 6 - x - y); 41 42 move(x - 1, y - 1); //円盤を移動 43 printf("円盤[%d]を%d軸から%d軸へ移動\n", no, x, y); 44 disp(); //柱の状態を表示 45 46 hanoi(no - 1, 6 - x - y, y); 47} 48 49int main(void) 50{ 51 int n; 52 53 printf("ハノイの塔\n円盤の枚数:"); 54 scanf("%d", &n); 55 56 //柱の状態を初期化する 57 for (int i = 0; i < M; i++) 58 for (int j = 0; j < MAX; j++) 59 peg[i][j] = 0; //各柱には何もない 60 for (int i = 0; i < n; i++) 61 peg[0][i] = n - i; //Aの柱に円盤をセット 62 top[0] = n - 1; //Aの柱の最上位 63 top[1] = -1; //Bの柱は円盤無し 64 top[2] = -1; //Cの柱は円盤無し 65 66 disp(); //柱の状態を表示 67 68 hanoi(n, 1, 3); //ハノイの塔を解く 69}

配列を一つで、円盤がどの柱にあるか管理する方法もあります。
この方がプログラムはシンプルになりますが、表示がちょっと面倒です。

C

1#include <stdio.h> 2 3#define N 6 //円盤の枚数(デフォルト) 4#define MAX 32 5 6char disk[MAX]; //円盤を記録 7 8//塔の状態を表示 9void Disp(int n) 10{ 11 if (n > 0) printf("%d回目\n", n); 12 for (int p = 'A'; p < 'C' + 1; ++p) { //柱の'A'から'C'まで 13 printf("%c:", p); //柱を表示 14 for (int j = N; j >= 0; --j) { //大きな円盤から表示 15 if (disk[j] == p) { //円盤がその柱にあれば 16 printf("%2d", j + 1); //円盤を表示 17 } 18 } 19 printf("\n"); 20 } 21 printf("//-----\n"); 22} 23 24//ハノイの塔を解く 25void Hanoi(int n, char X,char Y,char Z) 26{ 27 static int k = 0; 28 if (n > 0) { 29 Hanoi(n - 1, X, Z, Y); 30 disk[n - 1] = Z; //移動先を記録 31 Disp(++k); 32 Hanoi(n - 1, Y, X, Z); 33 } 34} 35 36int main(void) 37{ 38 int n; 39 40 printf("ハノイの塔\n円盤の枚数:"); 41 if (scanf("%d", &n) < 1) return 1; 42 if (n < 1 && MAX < n) n = N; 43 44 for (int i = 0; i < n; ++i) { 45 disk[i] = 'A'; //'A'の柱に全ての円盤がある 46 } 47 Disp(0); //初期状態を表示 48 Hanoi(n, 'A', 'B', 'C'); 49}

投稿2020/06/12 13:35

編集2020/06/12 13:58
Bull

総合スコア986

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

grape_ll

2020/06/13 01:10

ご丁寧に二つも教えてくださりありがとうございます. 参考にしつつ自分でも考えてみようと思います.
guest

0

私なら、文字配列にして終端に '\0' を置いて "%s" で文字列出力しちゃいます。

c

1char tower[3][10]; // '\0' で初期化される 2 3(中略) 4 5 scanf("%d", &N); 6 for (int i = 0; i < N; i++) { 7 tower[0][i] = '0' + i; 8 tower[1][i] = '.'; 9 tower[2][i] = '.'; 10 } 11 printf("%s %s %s\n", tower[0], tower[1], tower[2]);

動作プログラムを書いておきます。

c

1#include <stdio.h> 2 3char tower[3][10]; 4 5void hanoi(int n, int from, int buffer, int to) { 6 if (n > 1) hanoi(n - 1, from, to, buffer); 7 8 int f = 0; while (tower[from][f] == '.') f++; 9 int t = 0; while (tower[to][t + 1] == '.') t++; 10 tower[to][t] = tower[from][f]; 11 tower[from][f] = '.'; 12 printf("%s %s %s\n", tower[0], tower[1], tower[2]); 13 14 if (n > 1) hanoi(n - 1, buffer, from, to); 15} 16 17int main(void) { 18 int N; 19 scanf("%d", &N); 20 for (int i = 0; i < N; i++) { 21 tower[0][i] = '0' + i; 22 tower[1][i] = '.'; 23 tower[2][i] = '.'; 24 } 25 printf("%s %s %s\n", tower[0], tower[1], tower[2]); 26 hanoi(N, 0, 1, 2); 27 return 0; 28}

投稿2020/06/12 08:57

編集2020/06/12 15:11
shiracamus

総合スコア5406

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

grape_ll

2020/06/13 01:11

実際のコードまで書いてくださりありがとうございます. 参考にして自分でも考えてみたいと思います.
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問