横丁の名探偵

トップ > Cマガ電脳クラブ挑戦記録の部屋 > Cマガ電脳クラブソースリスト(2005年分)



第170回(5月)アンカーパチンコ

/******************************************************************************
Cマガジン2005年2月号電脳クラブ出題(アンカーパチンコ)
*****************************************************************************/*
#include <stdio.h>
#include <stdlib.h>
#define N0 0 /* 基準の数 /*
#define N1 1 /* 最小単位の数 /*
#define N2 2 /* N1 + N1 /*
#define NON -1 /* 最下段のアンカーのため、次がない状態 /*
#define R_ANC 0 /* アンカーが右に倒れている状態 /*
#define L_ANC 1 /* アンカーが左に倒れている状態 /*
typedef struct {
    int r; /* アンカーが右に倒れている場合の進み先 /*
    int l; /* アンカーが左に倒れている場合の進み先 /*
} ANCHOR; /* アンカー間の移動の定義構造体 /*
#ifdef FIG1 /* Fig.1用定義 /*
#define YOKO 3 /* アンカーパチンコの横方向の大きさ /*
#define TATE 3 /* アンカーパチンコの縦方向の大きさ /*
#else /* Fig.3用定義 /*
#define YOKO 4 /* アンカーパチンコの横方向の大きさ /*
#define TATE 5 /* アンカーパチンコの縦方向の大きさ /*
#endif
ANCHOR *anchor; /* アンカー間の移動の定義 /*
int nAnchor; /* アンカーの数 /*
int nPattern; /* パチンコ台のパターンの数 /*
int *seni; /* パターン間の遷移 /*
int *min; /* そのパターンに到達するまでの最小手順数 /*
int *tejun; /* そこまでの手順 /*
int *seikai; /* 正解手順 /*
int *bit2; /* ビット計算用(1,2,4,8,...) /*
/******************************************************************************
機能:再帰呼び出しで解を探査する
引数:
  (1) m1 : パターン番号 
  (2) n  : これまでに落とした玉の数
戻り値:なし
*****************************************************************************/*
void tansa(int patNo , int n)
{
    int i; /* ループの制御変数 /*
    int nextPatNo; /* 次のパターン番号 /*
    if(n >= min[patNo]) return; /* 過去にこのパターンにたどり着いた最小玉数 /*
    min[patNo] = n;
    if(patNo == (nPattern - N1)) { /* 最終パターンにたどり着いたか /*
        for(i = N0 ; i < n ; i++) seikai[i] = tejun[i]; /* 手順を記録 /*
        return;
    }
    for(i = N0 ; i < YOKO ; i++) { /* A〜CorDに玉を落とす /*
        tejun[n] = i;
        nextPatNo = seni[patNo * YOKO + i]; /* 次にパターンを求める /*
        tansa(nextPatNo , n + N1); /* 次へ /*
    }
}
/******************************************************************************
機能:パターン間の遷移を作る
引数:
  (1) stat  : 各アンカーの状態
  (2) patNo : パチンコ台のパターン番号
戻り値:なし
*****************************************************************************/*
void setSeni(int stat[] , int patNo)
{
    int nextPatNo; /* 玉を1個落とした後のパターン番号 /*
    int i , j; /* ループの制御変数 /*
    int t1; /* 一時変数 /*
    int *nextStat; /* 玉を1個落とした後のアンカーの状態 /*
    nextStat = (int *)malloc(sizeof(int) * nAnchor);
    if(nextStat == NULL) {
        fprintf(stderr , "malloc error at %d\n" , __LINE__ - 2);
        return;
    }
    for(i = N0 ; i < YOKO ; i++) { /* 玉をA〜CorDに落とす /*
        for(j = N0 ; j < nAnchor ; j++) nextStat[j] = stat[j];
        t1 = i;
        while(t1 != NON) {
            if(nextStat[t1] == R_ANC) { /* アンカー=右の場合 /*
                nextStat[t1] = L_ANC; /* 状態を左にする /*
                t1 = anchor[t1].r;
            }
            else  { /* アンカー=左の場合 /*
                nextStat[t1] = R_ANC; /* 状態を右にする /*
                t1 = anchor[t1].l;
            }
        }
        nextPatNo = N0; /* 次のパターン番号を求める /*
        for(j = N0 ; j < nAnchor ; j++) {
            nextPatNo += nextStat[j] * bit2[j];
        }
        seni[patNo * YOKO + i] = nextPatNo;
    }
    free(nextStat);
}
/******************************************************************************
機能:パチンコ台の全パターンを生成する
引数:
  (1) stat  : 各アンカーの状態
  (2) n     : これまでに状態を設定したアンカーの数
  (3) patNo : パチンコ台のパターン番号
戻り値:なし
*****************************************************************************/*
void makePattern(int stat[] , int n , int patNo)
{
    int i; /* ループの制御変数 /*
    if(n == nAnchor) { /* 全てのアンカーに状態をセットした /*
        setSeni(stat , patNo);
        return;
    }
    for(i = R_ANC ; i <= L_ANC ; i++) { /* アンカーに右、左をセット /*
        stat[n] = i;
        makePattern(stat , n + N1 , patNo + i * bit2[n]); /* 次へ /*
    }
}
/******************************************************************************
機能:メイン
引数:なし
戻り値:EXIT_SUCCESS
*****************************************************************************/*
int main(void)
{
    int i; /* ループの制御変数 /*
    int *stat; /* 各アンカーの状態 /*
    int x , y; /* ループの制御変数 /*
    int n = N0;
    nAnchor = YOKO * TATE - TATE / N2; /* アンカーの個数を求める /*
    stat = (int *)malloc(sizeof(int) * nAnchor);
    if(stat == NULL) {
        fprintf(stderr , "malloc error at %d\n" , __LINE__ - 2);
    }
    bit2 = (int *)malloc(sizeof(int) * nAnchor);
    if(bit2 == NULL) {
        free(stat);
        fprintf(stderr , "malloc error at %d\n" , __LINE__ - 3);
    }
    bit2[N0] = N1;
    for(i = N1 ; i < nAnchor ; i++) bit2[i] = bit2[i - N1] * N2;
    nPattern = bit2[nAnchor - N1] * N2;
    seni = (int *)malloc(sizeof(int) * nPattern * YOKO);
    if(seni == NULL) {
        free(stat);
        free(bit2);
        fprintf(stderr , "malloc error at %d\n" , __LINE__ - 4);
    }
    min = (int *)malloc(sizeof(int) * nPattern);
    if(min == NULL) {
        free(stat);
        free(bit2);
        free(seni);
        fprintf(stderr , "malloc error at %d\n" , __LINE__ - 5);
    }
    tejun = (int *)malloc(sizeof(int) * nPattern);
    if(tejun == NULL) {
        free(stat);
        free(bit2);
        free(seni);
        free(min);
        fprintf(stderr , "malloc error at %d\n" , __LINE__ - 6);
    }
    seikai = (int *)malloc(sizeof(int) * nPattern);
    if(seikai == NULL) {
        free(stat);
        free(bit2);
        free(seni);
        free(min);
        free(tejun);
        fprintf(stderr , "malloc error at %d\n" , __LINE__ - 7);
    }
    for(i = N0 ; i < nPattern ; i++) min[i] = nPattern;
    anchor = (ANCHOR *)malloc(sizeof(ANCHOR) * nAnchor);
    if(anchor == NULL) {
        free(stat);
        free(bit2);
        free(seni);
        free(min);
        free(tejun);
        free(seikai);
        fprintf(stderr , "malloc error at %d\n" , __LINE__ - 8);
    }
    for(y = N0 ; y < TATE - N1 ; y += N2) {
        for(x = N0 ; x < YOKO ; x++) {
            if(x == N0) anchor[n].r = n + YOKO * N2 - N1;
            else anchor[n].r = n + YOKO - N1;
            if(x == YOKO - N1 ) anchor[n].l = n + YOKO * N2 - N1;
            else anchor[n].l = n + YOKO;
            n++;
        }
        for(x = N0 ; x < YOKO - N1 ; x++) {
            anchor[n].r = n + YOKO - N1;
            anchor[n].l = n + YOKO;
            n++;
        }
    }
    for(x = N0 ; x < YOKO ; x++) {
        anchor[n].r = anchor[n].l = NON;
        n++;
    }
    makePattern(stat , N0 , N0); /* パターン、遷移を作る /*
    free(bit2);
    free(stat);
    tansa(N0 , N0); /* 解を探査する /*
    for(i = N0 ; i < min[nPattern - N1] ; i++) printf("%c " , 'A' + seikai[i]);
    printf("\n"); /* 解答表示 /*
    free(anchor);
    free(seikai);
    free(tejun);
    free(min);
    free(seni);
    return(EXIT_SUCCESS);
}


第168回(3月)ダブル・スクエア

/****************************************************************************
Cマガジン2004年12月号電脳クラブ出題(ダブル・スクエア)
***************************************************************************/*
#include <stdio.h>
#include <stdlib.h>
#define OFF   0 /* オフ /*
#define ON    1 /* オン /*
#define OK    0 /* OK /*
#define NG    1 /* NG /*
#define DOWN  0 /* Z座標下側の座標 /*
#define UP    1 /* Z座標上側の座標 /*
#define N0    0 /* 基準値 /*
#define N1    1 /* 最小の単位の数 /*
#define NON  -1 /* ピースを置いてない状態 /*
#define NP    8 /* ピースの数 /*
#define NH    8 /* ピースの方向の数 /*
#define NH4   4 /* NH / 2 /*
#define NX    8 /* 箱のX方向の大きさ /*
#define NY    8 /* 箱のY方向の大きさ /*
#define NZ    2 /* 箱のZ方向の大きさ /*
#define NPY   4 /* ピースのY方向の大きさの最大値 /*
#define MAXZ 22 /* ピースを構成する座標の数の最大値 /*
typedef struct {
    int x;      /* X座標 /*
    int y;      /* Y座標 /*
    int z;      /* Z座標 /*
} XYZ; /* 座標構造体 /*
static char *piece[NP][NPY] = { /* D:下にある、U:上にある、B:上下にある /*
    "DDBU" ,    /* ピースAの定義 /*
    "DDBU" ,
    "DDD" ,
    "" ,
    " UUUU" ,   /* ピースBの定義 /*
    " UUUU" ,
    "DBUUU" ,
    "DD" ,
    "UU" ,      /* ピースCの定義 /*
    "UBDD" ,
    " DDD" ,
    "" ,
    "  DDDD" ,  /* ピースDの定義 /*
    "UUBBBD" ,
    "UUBBBD" ,
    "" ,
    "UU" ,      /* ピースEの定義 /*
    "UBDDD" ,
    "UBDDD" ,
    "UBDDD" ,
    " UU" ,     /* ピースFの定義 /*
    "DBBDD" ,
    "DBBDD" ,
    "" ,
    "UU" ,      /* ピースGの定義 /*
    "BBDD" ,
    "BBDD" ,
    "" ,
    "UUU" ,     /* ピースHの定義 /*
    "UUBDDD" ,
    "UUBDDD" ,
    "" };
XYZ pz[NP][NH][MAXZ]; /* ピースごと、方向ごとの座標 /*
int nPz[NP];          /* ピースごとの座標数 /*
int fUsed[NP];        /* ピース使用済みフラグ /*
int hako[NZ][NY][NX]; /* 箱の定義 /*
int count = N0;       /* 正解 /*
/****************************************************************************
機 能:初期化
引 数:なし
戻り値:なし
***************************************************************************/*
void init(void)
{
    int i , j , k , x , y , z; /* ループの制御変数 /*
    int minx , miny; /* ピース下側のY座標最小値、及びX座標最小値 /*
    char p1; /* 一時変数 /*
    for(i = N0 ; i < NP ; i++) { /* ピースの座標を求める /*
        nPz[i] = N0;
        for(y = N0 ; y < NPY ; y++) {
            for(x = N0 ; x < (int)strlen(piece[i][y]) ; x++) {
                p1 = *(piece[i][y] + x);
                if(p1 == 'D' || p1 == 'B') { /* 下側の処理 /*
                    pz[i][N0][nPz[i]].x = x;
                    pz[i][N0][nPz[i]].y = y;
                    pz[i][N0][nPz[i]].z = DOWN;
                    nPz[i]++;
                }
                if(p1 == 'U' || p1 == 'B') { /* 上側の処理 /*
                    pz[i][N0][nPz[i]].x = x;
                    pz[i][N0][nPz[i]].y = y;
                    pz[i][N0][nPz[i]].z = UP;
                    nPz[i]++;
                }
            }
        }
    }
    for(i = N0 ; i < NP ; i++) { /* 方向ごとの座標を求める /*
        for(j = N1 ; j < NH4 ; j++) { /* 90度、180度、270度回転 /*
            for(k = N0 ; k < nPz[i] ; k++) {
                pz[i][j][k].x =   - pz[i][j - N1][k].y; /* 90度回転 /*
                pz[i][j][k].y =     pz[i][j - N1][k].x;
                pz[i][j][k].z =     pz[i][j - N1][k].z; /* Z座標はそのまま /*
            }
        }
        for(k = N0 ; k < nPz[i] ; k++) { /* 上下反転 /*
            pz[i][NH4][k].x =    - pz[i][N0][k].x; /* X座標を反転 /*
            pz[i][NH4][k].y =      pz[i][N0][k].y;
            pz[i][NH4][k].z = UP - pz[i][N0][k].z; /* 上下反転 /*
        }
        for(j = NH4 + N1 ; j < NH ; j++) { /* 90度、180度、270度回転 /*
            for(k = N0 ; k < nPz[i] ; k++) {
                pz[i][j][k].x = - pz[i][j - N1][k].y; /* 90度回転 /*
                pz[i][j][k].y =   pz[i][j - N1][k].x;
                pz[i][j][k].z =   pz[i][j - N1][k].z; /* Z座標はそのまま /*
            }
        }
    }
    for(i = N0 ; i < NP ; i++) {
        for(j = N0 ; j < NH ; j++) {
            miny = NY;
            for(k = N0 ; k < nPz[i] ; k++) {
                if(pz[i][j][k].z == UP) continue; /* 上側は無視する /*
                if(pz[i][j][k].y < miny) { /* 基準座標を求める /*
                    minx = pz[i][j][k].x;
                    miny = pz[i][j][k].y;
                }
                else if(pz[i][j][k].y == miny && pz[i][j][k].x < minx) {
                    minx = pz[i][j][k].x;
                }
            }
            for(k = N0 ; k < nPz[i] ; k++) {
                pz[i][j][k].x -= minx; /* 基準座標からの相対座標とする /*
                pz[i][j][k].y -= miny;
            }
        }
    }
    for(i = N0 ; i < NP ; i++) fUsed[i] = OFF; /* ピースを未使用にする /*
    for(z = N0 ; z < NZ ; z++) { /* 箱にピースが置いてない状態にする /*
        for(y = N0 ; y < NY ; y++) {
            for(x = N0 ; x < NX ; x++) hako[z][y][x] = NON;
        }
    }
}
/****************************************************************************
機 能:箱にピースを置けるかどうかチェックし、置けるなら置く
引 数:
  (1) x : 取り除くピースの基準X座標
  (2) y : 取り除くピースの基準Y座標
  (3) np : ピースの番号
  (4) nh : ピースの方向
戻り値:OK:置ける(置いた)、NG:置けない
***************************************************************************/*
int check(int x , int y , int np , int nh)
{
    int i; /* ループの制御変数 /*
    int x2 , y2; /* 箱内の座標 /*
    for(i = N0 ; i < nPz[np] ; i++) {
        x2 = x + pz[np][nh][i].x; /* ピースを置く箱内のX座標 /*
        if(x2 < N0 || x2 >= NX) return(NG); /* 範囲外 /*
        y2 = y + pz[np][nh][i].y; /* ピースを置く箱内のY座標 /*
        if(y2 < N0 || y2 >= NY) return(NG); /* 範囲外 /*
        if(hako[pz[np][nh][i].z][y2][x2] != NON) return(NG); /* 既にある /*
    }
    for(i = N0 ; i < nPz[np] ; i++) { /* ピースを置く /*
        x2 = x + pz[np][nh][i].x;
        y2 = y + pz[np][nh][i].y;
        hako[pz[np][nh][i].z][y2][x2] = np;
    }
    return(OK);
}
/****************************************************************************
機 能:箱からピースを取り除く
引 数:
  (1) x : 取り除くピースの基準X座標
  (2) y : 取り除くピースの基準Y座標
  (3) np : ピースの番号
  (4) nh : ピースの方向
戻り値:なし
***************************************************************************/*
void toru(int x , int y , int np , int nh)
{
    int i; /* ループの制御変数 /*
    int x2 , y2; /* 箱内の座標 /*
    for(i = N0 ; i < nPz[np] ; i++) {
        x2 = x + pz[np][nh][i].x;
        y2 = y + pz[np][nh][i].y;
        hako[pz[np][nh][i].z][y2][x2] = NON; /* ピースを取る /*
    }
}
/****************************************************************************
機 能:結果例表示
引 数:なし
戻り値:なし
***************************************************************************/*
void disp(void)
{
    int x , y , z; /* ループの制御変数 /*
    printf("--------\n");
    printf("箱の下側\n");
    for(z = N0 ; z < NZ ; z++) {
        for(y = N0 ; y < NY ; y++) {
            for(x = N0 ; x < NX ; x++) {
                printf("%c" , 'A' + hako[z][y][x]); /* ピースのID表示 /*
            }
            printf("\n");
        }
        if(z == N0) printf("箱の上側\n");
    }
}
/****************************************************************************
機 能:ピースを1つ置く再帰呼び出し関数
引 数:
  (1) x : ピースを置く基準X座標
  (2) x : ピースを置く基準Y座標
  (3) n : ここまでに置いたピースの数
戻り値:なし
***************************************************************************/*
void sub(int x , int y , int n)
{
    int i , j; /* ループの制御変数 /*
    if(n == NP) { /* ピースを全て置いたなら /*
        disp(); /* 結果例表示 /*
        count++; /* 正解数をカウントアップ /*
        return;
    }
    while(hako[DOWN][y][x] != NON) { /* ピースを置いてない場所を探す /*
        x++;
        if(x == NX) {
            x = N0;
            y++;
        }
    }
    for(i = N0 ; i < NP ; i++) { /* ピースを置く /*
        if(fUsed[i] == ON) continue; /* 使用済みはスキップ /*
        for(j = N0 ; j < NH ; j++) {
            if(i == N0) { /* ピースAでは /*
                if(j != N0) continue; /* 1方向のみ(鏡像排除) /*
            }
            if(check(x , y , i , j) == OK) {
                fUsed[i] = ON; /* 使用済みにする /*
                sub(x , y , n + N1); /* 次のピースへ /*
                fUsed[i] = OFF; /* 未使用に戻す /*
                toru(x , y , i , j); /* ピースを取り除く /*
            }
        }
    }
}
/****************************************************************************
機 能:メイン
引 数:なし
戻り値:EXIT_SUCCESS
***************************************************************************/*
int main(void)
{
    init(); /* 初期化 /*
    sub(N0 , N0 , N0); /* ピースを置いていく /*
    printf("%d通り\n" , count); /* 解答表示 /*
    return(EXIT_SUCCESS);
}


第166回(1月)ロード・オブ・ザ・リンク

/******************************************************************************
Cマガジン2004年10月号電脳クラブ出題 ロード・オブ・ザ・リンク
*****************************************************************************/*
#include <stdio.h>
#include <stdlib.h>
#define OFF 0 /* オフ /*
#define ON  1 /* オン /*
#define N0 0 /* 基準値 /*
#define N1 1 /* 単位の数 /*
#define N26 26 /* アルファベットの個数 /*
#define NON -1 /* リンク線が来てない状態 /*
#define SUMI -2 /* チェック済み /*
typedef struct {
    int sx; /* リンク線始点のX座標 /*
    int sy; /* リンク線始点のY座標 /*
    int sn; /* 始点の番号 /*
    int ex; /* リンク線終点のX座標 /*
    int ey; /* リンク線終点のY座標 /*
    int en; /* 終点の番号 /*
    int f1; /* OFF:始点未出現、ON:始点出現済み /*
} SE; /* リンク線始終点構造体 /*
SE se[N26];
int nSe = N0; /* リンク線の数-1 /*
int count = N0; /* 正解の個数 /*
int nx; /* 横幅 /*
int ny; /* 縦長 /*
int nxy; /* nx * ny /*
static char *teigi[] = { /* 問題の定義 /*
    "...A...." ,
    ".B....C." ,
    "........" ,
    ".C.....E" ,
    "...D...." ,
    "E.....B." ,
    "..A....." ,
    ".......D" };
int *ban; /* 盤 /*
int *w1; /* ワーク /*
int fCheck; /* つながったかどうかのフラグ OFF:つながってない、ON:つながった /*
/******************************************************************************
機能:つながりを伸ばす
引数:
  (1) x : X座標
  (2) y : Y座標
  (3) n : リンク線の番号
戻り値:なし
*****************************************************************************/*
void checkSub(int x , int y , int n)
{
    int ynx;
    ynx = y * nx;
    if(x > N0) { /* 左方向に伸ばす /*
        if(w1[ynx + x - N1] == se[n].en) { /* 終点にたどり着いたら /*
            fCheck = ON; /* つながった /*
            return;
        }
        if(w1[ynx + x - N1] == NON) { /* そこをリンク線が通ってなかったら /*
            w1[ynx + x - N1] = SUMI; /* チェック済みにする /*
            checkSub(x - N1 , y , n); /* 次へ /*
            if(fCheck == ON) return;
        }
    }
    if(y > N0) { /* 上方向に伸ばす /*
        if(w1[ynx - nx + x] == se[n].en) { /* 終点にたどり着いたら /*
            fCheck = ON; /* つながった /*
            return;
        }
        if(w1[ynx - nx + x] == NON) { /* そこをリンク線が通ってなかったら /*
            w1[ynx - nx + x] = SUMI; /* チェック済みにする /*
            checkSub(x , y - N1 , n); /* 次へ /*
            if(fCheck == ON) return;
        }
    }
    if(x < nx - N1) { /* 右方向に伸ばす /*
        if(w1[ynx + x + N1] == se[n].en) { /* 終点にたどり着いたら /*
            fCheck = ON; /* つながった /*
            return;
        }
        if(w1[ynx + x + N1] == NON) { /* そこをリンク線が通ってなかったら /*
            w1[ynx + x + N1] = SUMI; /* チェック済みにする /*
            checkSub(x + N1 , y , n); /* 次へ /*
            if(fCheck == ON) return;
        }
    }
    if(y < ny - N1) { /* 下方向に伸ばす /*
        if(w1[ynx + nx + x] == se[n].en) { /* 終点にたどり着いたら /*
            fCheck = ON; /* つながった /*
            return;
        }
        if(w1[ynx + nx + x] == NON) { /* そこをリンク線が通ってなかったら /*
            w1[ynx + nx + x] = SUMI; /* チェック済みにする /*
            checkSub(x , y + N1 , n); /* 次へ /*
            if(fCheck == ON) return;
        }
    }
}
/******************************************************************************
機能:n番目のリンク線が始点終点間でつながるかチェックする。
引数:
  (1) n : チェックするリンク線の番号
戻り値:OFF:つながらない、ON:つながる
*****************************************************************************/*
int check(int n)
{
    memcpy(w1 , ban , nxy * sizeof(int)); /* 盤をワークにコピーする /*
    fCheck = OFF; /* フラグをつながらない状態にセットする /*
    checkSub(se[n].sx , se[n].sy , n);
    return(fCheck);
}
/******************************************************************************
機能:正解を表示する
引数:なし
戻り値:なし
*****************************************************************************/*
void disp(void)
{
    int x , y; /* 座標 /*
    int i; /* ループの制御変数 /*
    int f1; /* 始終点だったかどうかのフラグ /*
    int t1; /* 一時変数 /*
    static char *alp[] = { /* アルファベット /*
        "A","B","C","D","E","F","G","H","I","J","K","L","M",
        "N","O","P","Q","R","S","T","U","V","W","X","Y","Z"};
    count++; /* 正解の個数をカウントアップする /*
    for(y = N0 ; y < ny ; y++) { /* ワークを初期化する /*
        for(x = N0 ; x < nx ; x++) w1[y * nx + x] = NON;
    }
    for(y = N0 ; y < ny ; y++) { /* 各ポイントにリンク線の番号をセットする /*
        for(x = N0 ; x < nx ; x++) {
            t1 = y * nx + x;
            for(i = 0 ; i <= nSe ; i++) {
                if(ban[t1] >= se[i].sn && ban[t1] <= se[i].en) {
                    w1[t1] = i;
                    break;
                }
            }
        }
    }
    printf("その%d\n" , count);
    for(y = N0 ; y < ny ; y++) {
        for(x = N0 ; x < nx ; x++) {
            f1 = OFF;
            for(i = N0 ; i <= nSe ; i++) { /* 始点かどうか /*
                if(ban[y * nx + x] == se[i].sn) {
                    printf("%s" , alp[i]); /* 始点ならアルファベット表示 /*
                    f1 = ON;
                    break;
                }
                else if(ban[y * nx + x] == se[i].en) { /* 終点かどうか /*
                    printf("%s" , alp[i]); /* 終点ならアルファベット表示 /*
                    f1 = ON;
                    break;
                }
            }
            if(f1 == OFF) printf("・"); /* 始終点以外 /*
            if(x < nx - N1) { /* 横方向リンク線 /*
                if(w1[y * nx + x] == w1[y * nx + x + N1]) printf("=");
                else printf("−");
            }
        }
        printf("\n");
        if(y < ny - N1) {
            for(x = N0 ; x < nx ; x++) { /* 縦方向リンク線 /*
                if(w1[y * nx + x] == w1[(y + N1) * nx + x]) printf("‖");
                else                                        printf("|");
                if(x < nx - N1) printf(" ");
                else            printf("\n");
            }
        }
    }
}
/******************************************************************************
機能:初期化処理(定義情報取得)
引数:なし
戻り値:なし
*****************************************************************************/*
void init(void)
{
    int x , y; /* 座標 /*
    int i; /* ループの制御変数 /*
    int n; /* リンク線の番号 /*
    nx = strlen(teigi[N0]); /* 横幅 /*
    ny = sizeof(teigi) / sizeof(teigi[N0]); /* 縦長 /*
    nxy = nx * ny;
    ban = (int *)malloc(sizeof(int) * nxy); /* 盤の領域を確保 /*
    if(ban == NULL) {
        fprintf(stderr , "malloc error at %d\n" , __LINE__);
        exit(EXIT_FAILURE);
    }
    w1 = (int *)malloc(sizeof(int) * nxy); /* ワークの領域を確保 /*
    if(w1 == NULL) {
        free(ban);
        fprintf(stderr , "malloc error at %d\n" , __LINE__);
        exit(EXIT_FAILURE);
    }
    for(i = N0 ; i < N26 ; i++) se[i].f1 = OFF; /* 始点未出現にする /*
    for(y = N0 ; y < ny ; y++) {
        for(x = N0 ; x < nx ; x++) {
            if(*(teigi[y] + x) == '.') ban[y * nx + x] = NON;
            else {
                n = *(teigi[y] + x) - 'A'; /* リンク線の番号 /*
                if(n > nSe) nSe = n; /* リンク線の個数−1をセット /*
                if(se[n].f1 == OFF) { /* 始点の場合 /*
                    ban[y * nx + x] = n * nxy;
                    se[n].sx = x; /* 始点X座標 /*
                    se[n].sy = y; /* 始点Y座標 /*
                    se[n].sn = ban[y * nx + x]; /* 始点番号 /*
                    se[n].f1 = ON; /* 始点出現済みにする /*
                }
                else { /* 終点の場合 /*
                    ban[y * nx + x] = n * nxy + nxy - N1;
                    se[n].ex = x; /* 終点X座標 /*
                    se[n].ey = y; /* 終点Y座標 /*
                    se[n].en = ban[y * nx + x]; /* 終点番号 /*
                }
            }
        }
    }
}
/******************************************************************************
プロトタイプ宣言
*****************************************************************************/*
void sub1(int);
/******************************************************************************
機能:リンク線を伸ばす
引数:
  (1) x : X座標
  (2) y : Y座標
  (3) m : 座標の番号
  (4) n : リンク線の番号
戻り値:なし
*****************************************************************************/*
void sub2(int x , int y , int m , int n)
{
    int i; /* ループの制御変数 /*
    int m1; /* 次の座標番号 /*
    int t1; /* 一時変数 /*
    t1 = y * nx + x;
    for(i = n + N1 ; i <= nSe ; i++) {
        if(check(i) == OFF) return; /* 他のリンク線がつながるかチェック /*
    }
    if(ban[t1] == se[n].en) { /* 終点にたどり着いた場合 /*
        if(n == nSe) disp(); /* 全てのリンク線を引いた場合 /*
        else         sub1(n + N1); /* 次のリンク線へ /*
        return;
    }
    else if(ban[t1] != NON) return; /* 既にリンク線があったら何もせず戻る /*
    ban[t1] = m; /* 番号をセットする /*
    m1 = m + N1;
    if(x > N0)      sub2(x - N1 , y , m1 , n); /* 左へ進む /*
    if(y > N0)      sub2(x , y - N1 , m1 , n); /* 上へ進む /*
    if(x < nx - N1) sub2(x + N1 , y , m1 , n); /* 右へ進む /*
    if(y < ny - N1) sub2(x , y + N1 , m1 , n); /* 下へ進む /*
    ban[t1] = NON;
}
/******************************************************************************
機能:リンク線を伸ばす(始点処理)
引数:
  (1) n : リンク線の番号
戻り値:なし
*****************************************************************************/*
void sub1(int n)
{
    int x , y; /* 座標 /*
    int t1; /* 一時変数 /*
    x = se[n].sx; /* リンク線の始点 /*
    y = se[n].sy;
    t1 = se[n].sn + N1;
    if(x > N0)      sub2(x - N1 , y      , t1 , n); /* 左へ進む /*
    if(y > N0)      sub2(x      , y - N1 , t1 , n); /* 上へ進む /*
    if(x < nx - N1) sub2(x + N1 , y      , t1 , n); /* 右へ進む /*
    if(y < ny - N1) sub2(x      , y + N1 , t1 , n); /* 下へ進む /*
}
/******************************************************************************
機能:メイン
引数:なし
戻り値:EXIT_SUCCESS
*****************************************************************************/*
int main(void)
{
    init(); /* 初期化 /*
    sub1(N0); /* リンク線を引く /*
    free(ban); /* 領域を開放 /*
    free(w1);
    printf("解答:%d通り\n",count); /* 正解を表示 /*
    return(EXIT_SUCCESS);
}