As I mentioned in a recent post I like to whip up a 'guess the number' game when learning a new language. It always seem to cover a bit of UI, math, decision making, looping, etc. I have worked on this version for Durex Forth (for C64) for far too long trying different ways to doing things. It came out a longish bit of code as I had to implement the random # generator (from Starting Forth) and numerical input, but it works
The lines are short as the C64 only has a 40 column screen and I can copy/paste into VICE is I use short lines in my text editor. I can already see ways to improve this code, like I don't need the second 2dup 2drop pair in ': correct?' but I guess that is always the case, you can always find a different way to accomplish the same thing.
Code:
( Silly guess the number game in Forth )
( File: guess )
hex ( BASE to HEX for includes )
include compat
include intest
include random
decimal ( base to DECIMAL for game )
create inbuffer 20 allot
10 constant maxval set
variable #guess
( generates random number from 0-maxval, counts
guesses taken with #guess )
: guessnum ( -- )
0 #guess ! maxval choose
begin ." Guess 0-" maxval .
1 #guess +! inbuffer input$
0 0 inbuffer count >number?
correct? until drop
" # of guesses: " #guesses @ .
;
( nr random#, ng guess -- f 0=incorrect )
: correct? ( nr ng -- f )
over 2dup < if ." Low! " 2drop 0
else 2dup > if ." High! " 2drop 0
else ." Correct " 2drop -1
then then cr
;
( File: intest )
( addr input buffer, $addr last char converted,
n# number of chars converted )
: input$ ( addr -- $addr n# )
dup 1+ 20 accept
swap c! ( char count save )
;
( dn double to hold result, addr n address and
count of chars to eval, -- , n #val, f=0 if NAN )
: >number? ( dn addr n -- n f )
>number
if 2drop 0 ( if f !=0 nan )
else 2drop
then
;
( File: random )
hex ( BASE in HEX )
variable rnd here rnd ! ( seed )
: random ( -- u )
rnd @ 7ABD * 1B0F + dup rnd !
;
: choose ( u maxval -- u rand )
random
um* swap drop ( 0 u within )
;