アルファベットコネクション、ナンバーリンク

 投稿者:山中和義  投稿日:2010年12月 4日(土)11時36分11秒
  マスの中に書かれた同じ数字同士(文字同士)を線で結ぶパズル


!アルファベットコネクション、ナンバーリンク

!解 4通り
! A──┐  A──┐  A──┐  A┌─┐
! ・┌BA  ・┌BA  ・・BA  └┘BA
! CB┌C  CB・C  CB┘C  CB┘C
! └─┘・  └──┘  └──┘  └──┘

PUBLIC NUMERIC M,N
PUBLIC STRING L$

LET M=4 !行数
LET N=4 !列数

DATA "A..." !問題
DATA "..BA"
DATA "CB.C"
DATA "...."

LET L$="ABC" !連結文字


PUBLIC STRING S$ !初期状態
LET S$=""
FOR i=1 TO M
   READ t$
   LET S$=S$&t$
NEXT i

DIM A(M,N) !盤面(接続状況)
FOR i=1 TO M*N !盤面を符号化する
   LET t$=S$(i:i)
   LET xx=INT((i-1)/M)+1 !列
   LET yy=MOD(i-1,N)+1 !行
   IF POS(L$,t$)>0 THEN LET A(xx,yy)=ORD(t$) ELSE LET A(xx,yy)=-1
NEXT i

MAT PRINT A; !debug


FOR i=1 TO M*N !最初の文字を探す
   IF S$(i:i)=L$(1:1) THEN EXIT FOR
NEXT i
LET yy=INT((i-1)/M)+1
LET xx=MOD(i-1,N)+1
CALL try(A,1,xx,yy,4)


END

EXTERNAL SUB try(A(,),p,x,y,d) !バックトラック法で探索する
FOR dd=0 TO 3 !右、上、左、下に移動させる
   SELECT CASE dd
   CASE 0
      LET xx=x+1
      LET yy=y
   CASE 1
      LET xx=x
      LET yy=y-1
   CASE 2
      LET xx=x-1
      LET yy=y
   CASE 3
      LET xx=x
      LET yy=y+1
   CASE ELSE
   END SELECT
   IF (xx<1 OR xx>N) OR (yy<1 OR yy>M) THEN !盤面の範囲内なら
   ELSE

      LET t=A(yy,xx) !移動先に応じて
      IF t<0 THEN !障害物なし

         LET A(yy,xx)=dd !仮に移動させる
         LET w=A(y,x) !save it
         LET A(y,x)=d*4+dd

         CALL try(A,p,xx,yy,dd) !次へ、接続線を延ばす

         LET A(yy,xx)=-1 !元に戻す
         LET A(y,x)=w


      ELSEIF t=ORD(L$(p:p)) THEN !接続できたなら
         LET A(y,x)=d*4+dd

         IF p=LEN(L$) THEN !最後の文字なら、完成!!!
            MAT PRINT A; !debug

            !盤面を復号化する
            FOR i=1 TO M*N
               IF S$(i:i)>=L$(1:1) THEN !文字なら
                  LET t=ORD(S$(i:i))
                  IF t>=ORD("A") THEN !アルファベットなら
                     PRINT CHR$(ORD("A")-ORD("A")+t); !全角へ
                  ELSE !数字なら
                     PRINT CHR$(ORD("0")-ORD("0")+t);
                  END IF
               ELSE !接続線なら
                  LET yy=INT((i-1)/M)+1
                  LET xx=MOD(i-1,N)+1
                  ! d方向→dd方向への移動
                  !    d:  0    1    2    3    4
                  !    dd: -1 0 1 2 3 0 1 2 3 0 1 2 3 0 1 2 3 0 1 2 3
                  PRINT MID$("・─┘─┐┌│┐│─└─┌└│┘│→↑←↓",A(yy,xx)+2,1);
               END IF
               IF MOD(i,N)=0 THEN PRINT
            NEXT i

         ELSE
            FOR i=1 TO M*N !次の文字を探す
               IF S$(i:i)=L$(p+1:p+1) THEN EXIT FOR
            NEXT i
            LET yy=INT((i-1)/M)+1
            LET xx=MOD(i-1,N)+1
            CALL try(A,p+1,xx,yy,4) !次の文字へ

         END IF


      END IF

   END IF
NEXT dd
END SUB




●サンプル1 6×6

LET M=6 !行数
LET N=6 !列数

DATA "1....2" !問題
DATA "...3.."
DATA "......"
DATA "..4..."
DATA ".13.24"
DATA "......"

LET L$="1234" !連結文字


●サンプル2 7×7

LET M=7 !行数
LET N=7 !列数

DATA "......." !問題
DATA ".1.2.2."
DATA ".3...4."
DATA "...5..."
DATA "...6..."
DATA ".65314."
DATA "......."

LET L$="123456" !連結文字


8×8は、相当時間がかかります。
 

戻る