テトロミノの箱詰めパズル

 投稿者:山中和義  投稿日:2009年12月14日(月)10時56分39秒
  「C言語による最新アルゴリズム事典」より tetromin.c -- テトロミノの箱詰めパズル
LET Pieces=5 !駒の数
LET Col=5 !盤の短辺の長さ ※5は固定
LET Row=8 !盤の長辺の長さ
LET PieceSize=4 !駒の大きさ
LET MaxSymmetry=8 !駒の置き方の最大数
LET MaxSite=(Col+1)*Row-1
LET LimSite=(Col+1)*(Row+1)

DIM board$(0 TO LimSite-1)
DIM NAME$(0 TO 2-1, 0 TO Pieces-1)
DIM symmetry(0 TO Pieces-1)
DIM shape(0 TO Pieces-1, 0 TO MaxSymmetry-1, 0 TO (PieceSize-1)-1)
DIM REST(0 TO Pieces-1)

LET count=0 !解答数
CALL initialize
CALL try(0)

SUB initialize
   local site, piece, state

   FOR site=0 TO MaxSite-1 !盤をつくる
      IF MOD(site,Col+1)=Col THEN LET board$(site)="*" ELSE LET board$(site)=""
   NEXT site
   FOR site=MaxSite TO (LimSite-1)-1
      LET board$(site)="*"
   NEXT site
   LET board$(LimSite-1)="" !番人
   ! ┌─┐Col+1
   !      * ┐
   !      * │
   !      * │
   !      * │
   !      * │Row+1
   !      * │
   !      * │
   !      * │← MaxSite-1
   ! *****  ┘
   !      ↑ LimSite-1

   FOR piece=0 TO Pieces-1 !駒を読み込む
      LET REST(piece)=2 !2枚ずつ
      READ NAME$(1,piece),NAME$(0,piece), symmetry(piece) !名称、個数
      FOR state=0 TO symmetry(piece)-1
         FOR site=0 TO (PieceSize-1)-1
            READ shape(piece,state,site) !形状
         NEXT site
      NEXT state
   NEXT piece
END SUB

SUB found !解の表示
!!!local i,j
   LET count=count+1
   PRINT "解";count
   FOR i=0 TO Col-1
      FOR j=i TO MaxSite-1 STEP Col+1
         PRINT board$(j);
      NEXT j
      PRINT
   NEXT i
END SUB

SUB try(site) !再帰的に試みる
   local piece,state,s0,s1,s2

   LET piece=0
   DO WHILE piece<Pieces !未使用の駒に対して
      IF REST(piece)=0 THEN
      ELSE

         LET REST(piece)=REST(piece)-1 !この駒を使用する

         LET state=0
         DO WHILE state<symmetry(piece) !すべての向きに置いてみる
            LET s0=site+shape(piece,state,0)

            IF board$(s0)<>"" THEN !ここに四角1が置ければ
            ELSE
               LET s1=site+shape(piece,state,1)

               IF board$(s1)<>"" THEN !四角2
               ELSE
                  LET s2=site+shape(piece,state,2)

                  IF board$(s2)<>"" THEN !四角3
                  ELSE
                     LET board$(site),board$(s0),board$(s1),board$(s2)=NAME$(REST(piece),piece)

                     LET temp=site !次の空き位置を探す
                     DO
                        LET temp=temp+1
                     LOOP WHILE board$(temp)<>""
                     IF temp<MaxSite THEN CALL try((temp)) ELSE CALL found

                     LET board$(site),board$(s0),board$(s1),board$(s2)=""

                  END IF !continue
               END IF
            END IF

            LET state=state+1
         LOOP

         LET REST(piece)=REST(piece)+1 !未使用

      END IF !continue

      LET piece=piece+1
   LOOP
END SUB


! tetromin.dat -- テトロミノの駒の形のデータ

!配列borad$()の要素番号と盤上配置との関係
!    site
!     ↓
!      * 1 2 3
!  4 5 6 7 8 9
! 101112131415
! 161718192021
! └ Col+1 ┘ ※Col=5

DATA "O","o", 1 !名称、個数
DATA 1,6,7 !形状 s0,s1,s2

DATA "I","i", 2
DATA 1,2,3
DATA 6,12,18

DATA "T","t", 4
DATA 1,2,7
DATA 5,6,7
DATA 5,6,12
DATA 6,7,12

DATA "Z","z", 4
DATA 1,5,6
DATA 1,7,8
DATA 5,6,11 !裏
DATA 6,7,13

DATA "L","l", 8
DATA 1,2,6
DATA 1,2,8
DATA 1,6,12
DATA 1,7,13
DATA 4,5,6 !裏
DATA 6,7,8
DATA 6,11,12
DATA 6,12,13


END


!投稿(記述例)、情報、アルゴリズム、パズル、移植
 

戻る