新しく発言する  EXIT  インデックスへ

ライツアウト(LightsOut)をプログラムで解...


  ライツアウト(Lights Out)をプログラムで解く(PLAYモードを含む) 山中和義 2008/05/24 09:40:05 
  つづき 山中和義 2008/05/24 09:40:49 

  ライツアウト(Lights Out)をプログラムで解く(PLAYモードを含む) 山中和義 2008/05/24 09:40:05   ツリーへ
ライツアウト(Lights Out)をプログラムで解く(PLAYモードを含む)  返事を書く  ノートメニュー
山中和義 <drdlxujciw> 2008/05/24 09:40:05
!1色ライツアウト(Lights Out)を解く(PLAYモードを含む)

!プログラムを実行すると、プレイモードになる。
!左クリックで、マスを反転する。
!右クリックで、現在の盤面からの解答を表示して、プログラムが終了する。

!●技術メモ
!3×3の場合、各マスの位置を左上からの連番で表すと
! 123
! 456
! 789
!となる。
!
!スイッチ1の箇所すなわち位置(1,1)をクリックすると
! 12-
! 4--
! ---
!の位置が変化する。
!これを、作用sw$(1)="110100000"と表すことにする。
!排他的論理和(XOR)に対応させるために、変化するビットを1とする。


LET M=5 !行 ※盤の大きさ
LET N=5 !列

DATA 1,1,1,1,1 !初期の盤面 ※1:点灯、0:消灯
DATA 1,1,1,1,1
DATA 1,1,1,1,1
DATA 1,1,1,1,1
DATA 1,1,1,1,1
!------------------------------ ここまでがデータ


SET WINDOW 1,N+1,M+1,1 !表示領域
SET TEXT JUSTIFY "center","half" !配置基準

SUB PrintOut(M,N,ptn$) !盤面を表示する
SET DRAW mode hidden !ちらつき防止開始
FOR id=1 TO M*N
LET x=MOD((id-1),N)+1 !マスの座標
LET y=INT((id-1)/N)+1
SELECT CASE ptn$(id:id)
CASE "0"
SET AREA COLOR 2
CASE "1"
SET AREA COLOR 6
CASE ELSE
END SELECT
PLOT AREA: x,y; x+1,y; x+1,y+1; x,y+1 !矩形
PLOT TEXT ,AT x+0.5,y+0.5: STR$(id) !スイッチ番号
NEXT id
DRAW grid !格子
SET DRAW mode explicit !ちらつき防止終了
END SUB


LET ptn$="" !盤面

FOR i=1 TO M*N !盤面を設定する
READ t
LET ptn$=ptn$&STR$(t)
NEXT i
!!!PRINT ptn$


DIM sw$(M*N) !スイッチ

DIM f$(M)
FOR i=1 TO M !位置(i,j)を押すことで変化するマスを求める
FOR j=1 TO N

FOR k=1 TO M
LET f$(k)=REPEAT$("0",N)
NEXT k

LET f$(i)(j:j)="1" !中央
IF i>1 THEN LET f$(i-1)(j:j)="1" !上
IF i<M THEN LET f$(i+1)(j:j)="1" !下
IF j>1 THEN LET f$(i)(j-1:j-1)="1" !左
IF j<N THEN LET f$(i)(j+1:j+1)="1" !右

LET t=(i-1)*N+j !連番での位置
LET sw$(t)="" !ビット列を得る
FOR k=1 TO M
LET sw$(t)=sw$(t)&f$(k)
NEXT k

NEXT j
NEXT i
!FOR i=1 TO M*N !debug
! PRINT sw$(i)
!NEXT i
  つづき 山中和義 2008/05/24 09:40:49   ツリーへ
Re: ライツアウト(Lights Out)をプログラムで解く(PLAYモードを含む)  返事を書く  ノートメニュー
山中和義 <drdlxujciw> 2008/05/24 09:40:49
つづき



LET clr$=REPEAT$("0",M*N)

PRINT "履歴"
DO
CALL PrintOut(M,N,ptn$) !盤面の表示

IF ptn$=clr$ THEN !ゲームクリアなら
PRINT "完成!"
STOP
END IF

MOUSE POLL x,y,left,right

IF left=1 THEN !左クリックなら
LET id=(INT(y)-1)*N+INT(x) !連番での位置
PRINT id !履歴

CALL action(ptn$, sw$(id)) !スイッチ操作

WAIT DELAY 0.3 !間隔をとる
END IF
LOOP UNTIL right=1 !右クリックなら


PRINT "盤面:";ptn$ !現在の盤面の表示

PRINT "解答 ※順番は関係なし"

LET t0=TIME


!攻略法
!・上段の行から順に消して行く
! 次の行の消し方は、上の行に依存している。
! 5×5の場合、上段の行の消し方、2^5=32通りを確認すればよい。

FOR p=2^N-1 TO 0 STEP -1 !1行目のスイッチの組合せ
LET c$=ptn$

LET bit$=right$(REPEAT$("0",N)&BSTR$(p,2),N) !2進法表記で生成する
FOR i=1 TO N
IF bit$(i:i)="1" THEN CALL action(c$, sw$(i)) !その操作
NEXT i
LET op$=bit$ !記録 ※1:押下

FOR i=2 TO M !2行から最下行まで
LET t=(i-2)*N !1つ上の行をクリアする
LET op$=op$&c$(t+1:t+N) !記録
FOR j=1 TO N
IF c$(t+j:t+j)="1" THEN CALL action(c$, sw$(t+j+N)) !その操作
NEXT j
NEXT i

IF c$=clr$ THEN !順にクリアして、偶然にもクリアしたら
FOR i=1 TO M*N !解答の表示
IF op$(i:i)="1" THEN PRINT i;
NEXT i
PRINT
END IF
NEXT p


PRINT "計算時間=";TIME-t0


END


EXTERNAL SUB action(p$, sw$) !スイッチ操作
FOR i=1 TO LEN(p$) !ビット単位の排他的論理和
LET p$(i:i)=STR$(MOD(VAL(p$(i:i))+VAL(sw$(i:i)),2))
NEXT i
END SUB

 インデックスへ  EXIT
新規発言を反映させるにはブラウザの更新ボタンを押してください。