スタック* を少々拡張し, 任意の位置のデータが見れるようにしたデータ構造で一つの杭に積んである円盤の番号を保存することにし, これを三つ用意します.
以下の操作を提供する stack 型のオブジェクトがあるとします. すなわち
- init(int n) で n 個の int 値を格納できるよう初期化
- push(int data) で data をスタックにプッシュ
- int pop() でデータをスタックからポップ
- int depth() で現在のスタックの深さを参照
- int data(int position) で指定した位置の値を参照
- finalize() で終了処理を行う
とします.
仮のコードは以下のようになります.
#include <stdio.h>
#include <stdlib.h>
stack pegs[3];
int N, w;
static void
print()
{
int i, j, k;
w ミリ秒停止.
端末をクリアして 2行1桁目に移動.
for (i = 0; i < N; i++) {
for (j = 0; j < 3; j++) {
if (pegs[j].depth < N - i)
1 個の ' ', N個の ' ', 1個の '|', N個の ' ' および 1個の ' ' を出力.
else
1 個の ' ',
(N - pegs[j].data[N - i - 1]) 個の ' ',
pegs[j].data[N - i - 1] 個の '-',
1 個の '|',
pegs[j].data[N - i - 1] 個の '-',
(N - pegs[j].data[N - i - 1]) 個の ' ' および
1 個の ' ' を出力.
}
改行を出力.
}
(6*N + 9) 個の '=' と改行を出力.
}
static void
move(stack *src, stack *tmp, stack *dst, int n)
{
if (n == 0)
return;
move(src, dst, tmp, n - 1);
dst->push(src->pop());
print();
move(tmp, src, dst, n - 1);
}
int
main(int argc, char *argv[])
{
/*
* init
*/
N = (argc < 2)?3:atoi(argv[1]);
w = (argc < 3)?500:atoi(argv[2]);
pegs[0].init();
pegs[1].init();
pegs[2].init();
for (i = 0; i < N; i++)
pegs[0].push(N - i);
/*
* do
*/
print();
move(&pegs[0], &pegs[1], &pegs[2], N);
/*
* fainalize
*/
free(pegs[0].data);
free(pegs[1].data);
free(pegs[2].data);
return 0;
}
stack の実装.
- データ自体は構造体で定義します.
typedef _struct { int depth; int *data; } struct;stack s; に対して
- s.init(int n) は
s.data = (int *)malloc(n*sizeof(int)); s.depth = 0;
- s.push(int data) は
s.data[s.depth++] = data;
- s.pop() は
s.data[--s.depth];
- s.depth() は
s.depth
- s.data(int position) は
s.data[position]
- s.finalize() は
free(s.data);
のように書けます.
また, 利用される可能性のある最大の長さで, ‘ ‘, ‘-’, ‘=’ の連なった文字列を用意しておき, (用意した長さ – 出力したい長さ)番目の文字から出力することで任意の長さの ‘ ‘ や ‘-’ の連なった文字列を出力します.
それぞれのコード量が少ないので展開してしまいます. コードは以下のようになります.
#include <stdio.h>
#include <stdlib.h>
typedef struct _stack {
int depth;
int *data;
} stack;
stack pegs[3];
int N, w;
char *bar, *ws, *grnd;
char clsmv21[] = "\x1b[2J\x1b[2;1H";
static void
print()
{
int i, j, k;
usleep(w*1000);
fputs(clsmv21, stdout);
for (i = 0; i < N; i++) {
for (j = 0; j < 3; j++) {
if (pegs[j].depth < N - i)
printf(" %s|%s ", ws, ws);
else
printf(" %s%s|%s%s ",
ws + (pegs[j].data[N - i - 1]),
bar + (N - pegs[j].data[N - i - 1]),
bar + (N - pegs[j].data[N - i - 1]),
ws + (pegs[j].data[N - i - 1]));
}
putchar('\n');
}
fputs(grnd, stdout);
}
static void
move(stack *src, stack *tmp, stack *dst, int n)
{
if (n == 0)
return;
move(src, dst, tmp, n - 1);
dst->data[dst->depth++] = src->data[--src->depth];
print();
move(tmp, src, dst, n - 1);
}
int
main(int argc, char *argv[])
{
int i;
/*
* init
*/
N = (argc < 2)?3:atoi(argv[1]);
w = (argc < 3)?500:atoi(argv[2]);
pegs[0].data = (int *)malloc(N*sizeof(int));
pegs[0].depth = 0;
pegs[1].data = (int *)malloc(N*sizeof(int));
pegs[1].depth = 0;
pegs[2].data = (int *)malloc(N*sizeof(int));
pegs[2].depth = 0;
for (i = 0; i < N; i++)
pegs[0].data[pegs[0].depth++] = N - i;
/*
* for display
*/
bar = (char *)malloc((N + 1)*sizeof(char));
for (i = 0; i < N; i++)
bar[i] = '-';
bar[N] = '\0';
ws = (char *)malloc((N + 1)*sizeof(char));
for (i = 0; i < N; i++)
ws[i] = ' ';
ws[N] = '\0';
grnd = (char *)malloc((6*N + 11)*sizeof(char));
for (i = 0; i < 6*N + 9; i++)
grnd[i] = '=';
grnd[6*N + 9] = '\n';
grnd[6*N + 10] = '\0';
/*
* do
*/
print();
move(&pegs[0], &pegs[1], &pegs[2], N);
/*
* fainalize
*/
free(bar);
free(ws);
free(grnd);
free(pegs[0].data);
free(pegs[1].data);
free(pegs[2].data);
return 0;
}
Related Posts:
- ハノイとバベルの塔 第六階 – 端末アニメ in Java
- ハノイとバベルの塔 第三階 – C におけるモジュールの分離
- ハノイとバベルの塔 第二階 – 端末出力 C および Haskell
- ハノイとバベルの塔 第八階 – 端末アニメ in Ruby
- scheme で TCP エコーサーバ