patternMinor
Number guessing game in Racket
Viewed 0 times
gamenumberracketguessing
Problem
I decided to learn a Lisp-ish language and I am discovering a very weird and new syntax. The obligatory first program, that also uses all the fundamentals, is the number guessing game.
- Did I define too few or too many constants?
- Is my code properly spaced and indented?
- Is there a cleaner way to exit the loop than
error?
- Is it too imperative? Is it even possible to write the number guessing game functionally?
- Is it OK to
define nullandset!?
#lang racket
(define NUM 12)
(define TRIES 6)
(define CORRECT "Correct! Well guessed!")
(define TOO_LOW "... Too Low ...")
(define TOO_HIGH "... Too high ...")
(define (num_message player_num)
(if (= player_num NUM)
CORRECT
(if (> player_num NUM)
TOO_HIGH
TOO_LOW
)
)
)
(define (number-guessing-game)
(define out null)
(for ([i (range TRIES)])
(set! out (num_message (read)))
(print out)
(when (equal? out CORRECT)
(print "You won")
(error "Exiting")
)
)
(print "Too many attempts")
)
(number-guessing-game)Solution
Winning shouldn't be considered an error. If you want a way to exit from the for-loop, use
In
I'm not happy about the use of a string comparison to detect the winning condition: the
It would be more elegant for
The
The
Conventionally, words in identifiers are
#:break. But for and set! aren't really idiomatic in Lisp-like languages. Instead, it is more common to use recursion and let, which conform to the functional programming paradigm.In
num_message, you can use a cond instead of nested ifs.I'm not happy about the use of a string comparison to detect the winning condition: the
number-guessing-game function needs to know what congratulatory message to expect from num_message. You've worked around that problem by defining some string constants, which gives them more importance than one would expect.It would be more elegant for
num_message not to have NUM fixed, and for number-guessing-game not to have NUM and TRIES fixed.The
number-guessing-game function would be clearer if it were broken up, because it is actually doing two things: play one guess, and conditionally repeat.The
print calls should probably be displayln instead, to also write a trailing newline.Conventionally, words in identifiers are
separated-by-hyphens rather than underscores. Closing parentheses don't get their own line.#lang racket
(define NUM 12)
(define TRIES 6)
(define (num-message delta)
(cond [( delta 0) "... Too high ..."]
[else "Correct! Well guessed!"]))
(define (guess-number target)
(let ([delta (- (read) target)])
(displayln (num-message delta))
(zero? delta)))
(define (number-guessing-game target tries)
(cond [(zero? tries) (displayln "Too many attempts")]
[(guess-number target) (displayln "You won")]
[else (number-guessing-game target (- tries 1))]))
(number-guessing-game NUM TRIES)Code Snippets
#lang racket
(define NUM 12)
(define TRIES 6)
(define (num-message delta)
(cond [(< delta 0) "... Too low ..."]
[(> delta 0) "... Too high ..."]
[else "Correct! Well guessed!"]))
(define (guess-number target)
(let ([delta (- (read) target)])
(displayln (num-message delta))
(zero? delta)))
(define (number-guessing-game target tries)
(cond [(zero? tries) (displayln "Too many attempts")]
[(guess-number target) (displayln "You won")]
[else (number-guessing-game target (- tries 1))]))
(number-guessing-game NUM TRIES)Context
StackExchange Code Review Q#87075, answer score: 5
Revisions (0)
No revisions yet.