Kirjoittelin Miinaharava pelin 8th ohjelmointikielellä. Tyhjien ruutujen paljastus rutiini on iteratiivinen rekursiivisen sijaan.
lähdekoodi datatiedostoineen löytyypi täältä.
\ \ Simple Minesweeper game for 8th \ needs math/matrix "gfx/n0.png" app:asset img:new var, zero-img "gfx/n1.png" app:asset img:new var, one-img "gfx/n2.png" app:asset img:new var, two-img "gfx/n3.png" app:asset img:new var, three-img "gfx/n4.png" app:asset img:new var, four-img "gfx/n5.png" app:asset img:new var, five-img "gfx/n6.png" app:asset img:new var, six-img "gfx/n7.png" app:asset img:new var, seven-img "gfx/n8.png" app:asset img:new var, eight-img "gfx/tile.png" app:asset img:new var, tile-img "gfx/tinted1.png" app:asset img:new var, tinted1-img "gfx/tinted2.png" app:asset img:new var, tinted2-img "gfx/explosion.png" app:asset img:new var, explosion-img "gfx/mine.png" app:asset img:new var, mine-img "gfx/flag.png" app:asset img:new var, flag-img "snd/explosion.ogg" app:asset snd:new var, explosion-snd "snd/zero.ogg" app:asset snd:new var, zero-snd true app:isgui ! var gui var finished var uncovered var cleared var mines \ max number of mines : EASY 15 ; : NORMAL 20 ; : HARD 25 ; NORMAL var, difficulty : BRDSZ 10 ; : BRDSZI BRDSZ 2 n:+ ; : TILESIZE 32 ; : NUMTILES 10 ; : UNSELECTED 0 ; : SELECTED 1 ; : MARKED 16 ; : MINE 32 ; var state-board var draw-board BRDSZI BRDSZI n:* q:new var, zero-queue : rand10 rand-pcg n:abs 9 n:mod 1 n:+ ; : place-mine rand10 rand10 2dup state-board @ mat:@ dup MINE n:band not if MINE n:bor swap mat:! drop mines @ n:1+ mines ! else 2drop 2drop then ; : init-board false finished ! 0 uncovered ! 0 cleared ! 0 mines ! [ 1,1,1,1,1,1,1,1,1,1,1,1, 1,0,0,0,0,0,0,0,0,0,0,1, 1,0,0,0,0,0,0,0,0,0,0,1, 1,0,0,0,0,0,0,0,0,0,0,1, 1,0,0,0,0,0,0,0,0,0,0,1, 1,0,0,0,0,0,0,0,0,0,0,1, 1,0,0,0,0,0,0,0,0,0,0,1, 1,0,0,0,0,0,0,0,0,0,0,1, 1,0,0,0,0,0,0,0,0,0,0,1, 1,0,0,0,0,0,0,0,0,0,0,1, 1,0,0,0,0,0,0,0,0,0,0,1, 1,1,1,1,1,1,1,1,1,1,1,1 ] [ ` BRDSZI ` , ` BRDSZI ` ] mat:new state-board ! [] [ ` BRDSZ ` , ` BRDSZ ` ] mat:new draw-board ! ' place-mine difficulty @ times gui @ "lbl" g:child cleared @ " CLEARED: %3d %%" s:strfmt g:text drop ; locals: : mines? \ x y -- num-mines "y" w:! "x" w:! 0 "c" w:! ( "row" w:! ( "row" w:@ state-board @ mat:@ nip MINE n:band if "c" w:@ n:1+ "c" w:! then ) "x" w:@ n:1- "x" w:@ n:1+ loop ) "y" w:@ n:1- "y" w:@ n:1+ loop "c" w:@ ; : mine? \ x y -- bool state-board @ mat:@ nip MINE n:band if true else false then ; : selected? \ x y -- status state-board @ mat:@ nip SELECTED n:band if true else false then ; : marked? \ x y -- status state-board @ mat:@ nip MARKED n:band if true else false then ; : selected-or-marked? \ x y -- bool state-board @ mat:@ nip SELECTED MARKED n:bor n:band if true else false then ; : init-queue zero-queue @ q:clear drop ; : add-queue \ x y -- 2 a:close zero-queue @ swap q:push drop ; : select \ x y -- 2dup state-board @ mat:@ nip SELECTED n:bor state-board @ mat:! drop ; : set-board \ x y value -- draw-board @ mat:! drop ; locals: : uncover-queue "y" w:! "x" w:! ( "row" w:! ( dup "col" w:! "row" w:@ selected-or-marked? not if "col" w:@ "row" w:@ 2dup add-queue select then ) "x" w:@ n:1- "x" w:@ n:1+ loop ) "y" w:@ n:1- "y" w:@ n:1+ loop ; : cascade zero-queue @ repeat q:pop a:open 2dup mines? dup >r 0 n:= if \ Add code to play zero-snd rdrop 2dup n:1- >r n:1- r> 9 draw-board @ mat:! drop 1 uncovered n:+! uncover-queue else n:1- >r n:1- r> r> draw-board @ mat:! drop 1 uncovered n:+! then q:len 0 n:= if drop break then again ; \ : draw0 "gui" w:@ tile-img @ "x" w:@ TILESIZE n:* "y" w:@ TILESIZE n:* g:image-at drop ; : draw1 "gui" w:@ one-img @ "x" w:@ TILESIZE n:* "y" w:@ TILESIZE n:* g:image-at drop ; : draw2 "gui" w:@ two-img @ "x" w:@ TILESIZE n:* "y" w:@ TILESIZE n:* g:image-at drop ; : draw3 "gui" w:@ three-img @ "x" w:@ TILESIZE n:* "y" w:@ TILESIZE n:* g:image-at drop ; : draw4 "gui" w:@ four-img @ "x" w:@ TILESIZE n:* "y" w:@ TILESIZE n:* g:image-at drop ; : draw5 "gui" w:@ five-img @ "x" w:@ TILESIZE n:* "y" w:@ TILESIZE n:* g:image-at drop ; : draw6 "gui" w:@ six-img @ "x" w:@ TILESIZE n:* "y" w:@ TILESIZE n:* g:image-at drop ; : draw7 "gui" w:@ seven-img @ "x" w:@ TILESIZE n:* "y" w:@ TILESIZE n:* g:image-at drop ; : draw8 "gui" w:@ eight-img @ "x" w:@ TILESIZE n:* "y" w:@ TILESIZE n:* g:image-at drop ; : draw9 "gui" w:@ zero-img @ "x" w:@ TILESIZE n:* "y" w:@ TILESIZE n:* g:image-at drop ; : draw10 "gui" w:@ explosion-img @ "x" w:@ TILESIZE n:* "y" w:@ TILESIZE n:* g:image-at drop ; : draw11 "gui" w:@ mine-img @ "x" w:@ TILESIZE n:* "y" w:@ TILESIZE n:* g:image-at drop ; : draw16 "gui" w:@ flag-img @ "x" w:@ TILESIZE n:* "y" w:@ TILESIZE n:* g:image-at drop ; [ ' draw0 , ' draw1 , ' draw2 , ' draw3 , ' draw4 , ' draw5 , ' draw6 , ' draw7 , ' draw8 , ' draw9 , ' draw10 , ' draw11 , ' noop , ' noop , ' noop , ' noop , ' draw16 , ' noop , ' noop , ' noop , ' noop , ' noop , ' noop , ' noop , ' noop , ' noop , ' noop , ' noop , ' noop , ' noop , ' noop , ' noop , ' noop , ' noop , ' noop ] var, drawtable : inside-board? \ x y -- bool 0 TILESIZE BRDSZ n:* n:int n:between swap 0 TILESIZE BRDSZ n:* n:int n:between and ; : screen-tile? \ screen-x screen-y -- tile-x tile-y TILESIZE n:/ n:int >r TILESIZE n:/ n:int r> ; : tile-board? \ tile-x tile-y -- board-x board-y n:1+ >r n:1+ r> ; : board-tile? n:1- >r n:1- r> ; : draw-coords? \ tile-x tile-y -- draw-x draw-y TILESIZE n:* n:int >r TILESIZE n:* n:int r> ; : mark \ x y -- 2dup 2dup state-board @ mat:@ nip MARKED n:bor state-board @ mat:! drop board-tile? 2dup draw-board @ mat:@ nip MARKED n:bor draw-board @ mat:! drop ; : unmark \ x y -- 2dup 2dup state-board @ mat:@ nip MARKED n:bnot n:band state-board @ mat:! drop board-tile? 2dup draw-board @ mat:@ nip MARKED n:bnot n:band draw-board @ mat:! drop ; : show-mines ( >r ( r@ 2dup mine? if board-tile? 11 set-board else 2drop then ) 1 BRDSZ loop rdrop ) 1 BRDSZ loop ; locals: : ondraw "gui" w:! ( "y" w:! ( dup "x" w:! "y" w:@ draw-board @ mat:@ nip drawtable @ swap caseof ) 0 BRDSZ n:1- loop ) 0 BRDSZ n:1- loop finished @ not if "gui" w:@ g:mousepos? 2dup inside-board? if screen-tile? tile-board? 2dup selected? not if 2dup marked? not if board-tile? draw-coords? tinted1-img @ -rot g:image-at else board-tile? draw-coords? tinted2-img @ -rot g:image-at then else 2drop then else 2drop then drop then ; : onmouse-up finished @ if 2drop drop ;; then g:mouse? "left" m:@ if -rot screen-tile? tile-board? 2dup selected-or-marked? not if 2dup mine? not if 2dup select init-queue add-queue cascade else show-mines board-tile? 10 set-board \ Add code to play explosion-snd true finished ! then then else "right" m:@ if -rot screen-tile? tile-board? 2dup selected-or-marked? not if mark else 2dup marked? if unmark then then then then 2drop uncovered @ BRDSZ BRDSZ n:* mines @ n:- n:/ 100 n:* cleared ! uncovered @ mines @ n:+ BRDSZ BRDSZ n:* n:= if show-mines true finished ! then gui @ "lbl" g:child cleared @ " CLEARED: %3d %%" s:strfmt g:text drop ; : easy drop [ [ "Game", 0, "New game", 1, "Quit", 2 ], [ "Difficulty", 3, "Easy", { "id" : 4, "checked" : true }, "Normal", { "id" : 5, "checked" : false }, "Hard", { "id" : 6, "checked" : false } ] ] g:menu-update EASY difficulty ! init-board ; : normal drop [ [ "Game", 0, "New game", 1, "Quit", 2 ], [ "Difficulty", 3, "Easy", { "id" : 4, "checked" : false }, "Normal", { "id" : 5, "checked" : true }, "Hard", { "id" : 6, "checked" : false } ] ] g:menu-update NORMAL difficulty ! init-board ; : hard drop [ [ "Game", 0, "New game", 1, "Quit", 2 ], [ "Difficulty", 3, "Easy", { "id" : 4, "checked" : false }, "Normal", { "id" : 5, "checked" : false }, "Hard", { "id" : 6, "checked" : true } ] ] g:menu-update HARD difficulty ! init-board ; : onMenuSelected n:1- [ ' init-board , ' g:quit , ' noop , ' easy , ' normal , ' hard ] case drop ; : onsize 2drop BRDSZ TILESIZE n:* dup 56 n:+ g:size g:invalidate drop ; { "kind" : "win", "buttons" : 5, "title" : "Minesweeper", "wide" : 320, "high" : 376, "center" : true, "bg" : "lightsteelblue", "font" : "Arial 10", "size" : "onsize", "children" : [ { "kind" : "menubar", "name" : "menu", "bounds" : "0,0,parent.width, 24", "menu-selected" : "onMenuSelected", "menu" : [ [ "Game", 0, "New game", 1, "Quit", 2 ], [ "Difficulty", 3, "Easy", { "id" : 4, "checked" : false }, "Normal", { "id" : 5, "checked" : true }, "Hard", { "id" : 6, "checked" : false } ] ] }, { "kind" : "label", "font" : "Arial 18, bold", "bounds": "0,24,parent.right,56", "justify" : ["hleft", "vcenter"], "name" : "lbl" }, { "kind" : "box", "bounds": "0, lbl.bottom, 320, 376", "name" : "canvas", "mouse-up" : "onmouse-up", "draw" : "ondraw", "timer" : ( g:invalidate ) , "timer-period" : 20 } ] } var, gui-desc : app:main gui-desc @ g:new gui ! init-board ;
Aihe on jo aika vanha, joten et voi enää vastata siihen.