Uuden 8th beta version testaajana ajattelin kirjoitella kokeeksi miinaharava pelin, jotta voisin verrata miten uusi Nuklear pohjainen GUI toimii verrattuna vanhaan JUCE toteutukseen verrattuna.
Alla suoraviivainen miinaharavan toteutus, mikä käyttää iteratiivista toteutusta tyhjien ruutujen paljastamiseen rekursiivisen toteutuksen sijasta.
\
\ Simple Minesweeper game for 8th
\
"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
needs nk/gui
true var, handle-click
var finished
var uncovered
var cleared
var mines
\ max number of mines
15 constant EASY
20 constant NORMAL
25 constant HARD
NORMAL var, difficulty
0 constant EASY-MENU
1 constant NORMAL-MENU
2 constant HARD-MENU
NORMAL-MENU var, difficulty-selection
10 constant BRDSZ
BRDSZ 2 n:+ constant BRDSZI
32 constant TILESIZE
10 constant NUMTILES
0 constant UNSELECTED
1 constant SELECTED
16 constant MARKED
32 constant MINE
10 constant EXPLOSION-IMAGE
11 constant MINE-IMAGE
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 !
[] [ ` BRDSZI ` , ` BRDSZI ` ] mat:new draw-board !
' place-mine difficulty @ times ;
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 \ x y --
"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
rdrop
2dup
9 draw-board @ mat:! drop
1 uncovered n:+!
uncover-queue
else
r> draw-board @ mat:! drop
1 uncovered n:+!
then
q:len 0 n:= if drop break then
again ;
: mark \ x y --
2dup 2dup state-board @ mat:@ nip
MARKED n:bor state-board @ mat:! drop
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
2dup draw-board @ mat:@ nip
MARKED n:bnot n:band draw-board @ mat:! drop ;
: show-mines
( >r ( r@ 2dup mine? if MINE-IMAGE set-board else 2drop then ) 1 BRDSZ loop rdrop ) 1 BRDSZ loop ;
: handle-mouse-input \ expects rect on r-stack
finished @ if
rdrop ;;
then
nk:BUTTON_LEFT r@ false nk:clicked? if
handle-click @ if
"x" w:@ "y" w:@ 2dup selected-or-marked? not if
2dup
mine? not if
2dup select
init-queue
add-queue
cascade
else
show-mines
EXPLOSION-IMAGE set-board
true finished !
then
then
else
true handle-click !
then
else
nk:BUTTON_RIGHT r@ false nk:clicked? if
"x" w:@ "y" w:@ 2dup selected-or-marked? not if
mark
else
2dup marked? if
unmark
then
then
then
then
rdrop
uncovered @ BRDSZ BRDSZ n:* mines @ n:- n:/ 100 n:* cleared !
uncovered @ mines @ n:+ BRDSZ BRDSZ n:* n:= if
show-mines
true finished !
then ;
: draw-tile \ image --
"x" w:@ TILESIZE n:* "y" w:@ TILESIZE n:* TILESIZE TILESIZE 4 a:close swap "white" nk:draw-image ;
: draw-unselected-tile
"x" w:@ TILESIZE n:* "y" w:@ TILESIZE n:* TILESIZE TILESIZE 4 a:close dup >r
dup nk:hovered? finished @ not and if
tinted1-img @
else
tile-img @
then
"white" nk:draw-image
handle-mouse-input ;
: draw-flag-tile
"x" w:@ TILESIZE n:* "y" w:@ TILESIZE n:* TILESIZE TILESIZE 4 a:close dup >r
dup nk:hovered? finished @ not and if
tinted2-img @
else
flag-img @
then
"white" nk:draw-image
handle-mouse-input ;
[ ' draw-unselected-tile ,
( one-img @ draw-tile ) ,
( two-img @ draw-tile ) ,
( three-img @ draw-tile ) ,
( four-img @ draw-tile ) ,
( five-img @ draw-tile ) ,
( six-img @ draw-tile ) ,
( seven-img @ draw-tile ) ,
( eight-img @ draw-tile ) ,
( zero-img @ draw-tile ) ,
( explosion-img @ draw-tile ) ,
( mine-img @ draw-tile ) ,
' noop ,
' noop ,
' noop ,
' noop ,
' draw-flag-tile ] var, drawtable
locals:
: draw-tiles
( "y" w:! ( dup "x" w:! "y" w:@ draw-board @ mat:@ nip drawtable @ swap caseof ) 1 BRDSZ loop ) 1 BRDSZ loop ;
: easy-menu
"Difficulty" nk:TEXT_LEFT [200,200] nk:menu-begin if
25 1 nk:layout-row-dynamic
"Easy" nk:TEXT_CENTERED mine-img @ ( EASY difficulty ! init-board EASY-MENU difficulty-selection ! false handle-click ! ) nk:menu-item-image
"Normal" nk:TEXT_CENTERED ( NORMAL difficulty ! init-board NORMAL-MENU difficulty-selection ! false handle-click ! ) nk:menu-item-label
"Hard" nk:TEXT_CENTERED ( HARD difficulty ! init-board HARD-MENU difficulty-selection ! false handle-click ! ) nk:menu-item-label
nk:menu-end then ;
: normal-menu
"Difficulty" nk:TEXT_LEFT [200,200] nk:menu-begin if
25 1 nk:layout-row-dynamic
"Easy" nk:TEXT_CENTERED ( EASY difficulty ! init-board EASY-MENU difficulty-selection ! false handle-click ! ) nk:menu-item-label
"Normal" nk:TEXT_CENTERED mine-img @ ( NORMAL difficulty ! init-board NORMAL-MENU difficulty-selection ! false handle-click ! ) nk:menu-item-image
"Hard" nk:TEXT_CENTERED ( HARD difficulty ! init-board HARD-MENU difficulty-selection ! false handle-click ! ) nk:menu-item-label
nk:menu-end then ;
: hard-menu
"Difficulty" nk:TEXT_LEFT [200,200] nk:menu-begin if
25 1 nk:layout-row-dynamic
"Easy" nk:TEXT_CENTERED ( EASY difficulty ! init-board EASY-MENU difficulty-selection ! false handle-click ! ) nk:menu-item-label
"Normal" nk:TEXT_CENTERED ( NORMAL difficulty ! init-board NORMAL-MENU difficulty-selection ! false handle-click ! ) nk:menu-item-label
"Hard" nk:TEXT_CENTERED mine-img @ ( HARD difficulty ! init-board HARD-MENU difficulty-selection ! false handle-click ! ) nk:menu-item-image
nk:menu-end then ;
: game-menu
nk:menubar-begin
nk:STATIC 25 3 nk:layout-row-begin
90 nk:layout-row-push
"Game" nk:TEXT_LEFT [120,200] nk:menu-begin if
25 1 nk:layout-row-dynamic
"New" nk:TEXT_LEFT ( init-board false handle-click ! ) nk:menu-item-label
"Quit" nk:TEXT_LEFT ' bye nk:menu-item-label
nk:menu-end then
[ ' easy-menu , ' normal-menu , ' hard-menu ] difficulty-selection @ caseof
200 nk:layout-row-push
cleared @ "CLEARED: %3d %%" s:strfmt nk:TEXT_CENTERED "white" nk:label-colored
nk:menubar-end ;
var font1
: new-win
{
name: "main",
wide: 384,
high: 384,
bg: "palegreen",
fonts: {
font2: ["tahoma:24", "arial:24", "ubuntu:24"]
},
font: "font1",
title: "Minesweeper"
}
\ because we load font1 after this bit is compiled, we'll load it directly
"fonts" m:@
"font1" font1 @ m:!
drop
\ invoke nk:win to create the outermost window from the JSON definition:
nk:win ;
: main-render
{
bg: "DimGray",
font: "font2",
padding: [0,0],
flags: [ @nk:WINDOW_NO_SCROLLBAR ]
}
nk:begin
game-menu
draw-tiles
nk:end ;
: app:main
\ in order to be cross-platform, let's use a system font chosen by our library:
font:system 0 a:_@
\ let it be 16 pixels high. Font string format is "/path/to/font.ttf:pixelsize".
\ There are other acceptable inputs to font:new, see the documentation:
"%s:16" s:strfmt font:new font1 !
new-win
init-board
' main-render 200 nk:render-loop ;Mua alkaa heti närästää kun näkee tällaisia konstruktiota.
jalski kirjoitti:
"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...
: draw1 "x" w:@ TILESIZE n:* "y" w:@ TILESIZE n:* TILESIZE TILESIZE 4 a:close one-img @ "white" nk:draw-image ; : draw2 "x" w:@ TILESIZE n:* "y" w:@ TILESIZE n:* TILESIZE TILESIZE 4 a:close two-img @ "white" nk:draw-image ; : draw3 "x" w:@ TILESIZE n:* "y" w:@ TILESIZE n:* TILESIZE TILESIZE 4 a:close three-img @ "white" nk:draw-image ; : draw4 "x" w:@ TILESIZE n:* "y" w:@ TILESIZE n:* TILESIZE TILESIZE 4 a:close four-img @ "white" nk:draw-image ; : draw5 "x" w:@ TILESIZE n:* "y" w:@ TILESIZE n:* TILESIZE TILESIZE 4 a:close five-img @ "white" nk:draw-image ; : draw6 "x" w:@ TILESIZE n:* "y" w:@ TILESIZE n:* TILESIZE TILESIZE 4 a:close six-img @ "white" nk:draw-image ; : draw7 "x" w:@ TILESIZE n:* "y" w:@ TILESIZE n:* TILESIZE TILESIZE 4 a:close seven-img @ "white" nk:draw-image ; : draw8 "x" w:@ TILESIZE n:* "y" w:@ TILESIZE n:* TILESIZE TILESIZE 4 a:close eight-img @ "white" nk:draw-image ;
Vaikea kuvitella että kyseessä olisi kielen puute, vaikka en 8th:ää tunnekaan.
Grez kirjoitti:
Mua alkaa heti närästää kun näkee tällaisia konstruktiota.
Mikäs tuossa nyt närästää? Olisihan tuon voinut faktoroida paremmin laittamalla kuvat taulukkoon ja kirjoittaa sana mikä toteuttaa piirtämiseen vaadittavan yhteisen koodin. En nähnyt tarpeelliseksi kun noita erilaisia ruutuja ei kauhean montaa ole ja pari tapausta niistä pitää kuitenkin käsitellä erikseen, lukea hiiren syöte ja tarvittaessa korostaa hiirikursorin alla oleva ruutu...
Siistin koodia nyt kuitenkin vähän... ;)
Näyttääpi tältä.
Aihe on jo aika vanha, joten et voi enää vastata siihen.