garage/snippets/lispbox/guess.lisp

49 lines
1.6 KiB
Common Lisp

;; Simple number guessing game in Common Lisp
(defmacro while (condition &body body)
"While `condition' is not nil, evaluate `body'."
`(loop while ,condition do (progn ,@body)))
(defun make-random (max)
"Generate a random number up to `max' using a new random state."
(let ((*random-state* (make-random-state t)))
(random max)))
(defun read-integer ()
(parse-integer (read-line *query-io*) :junk-allowed t))
(defun attempt-guess (number)
"Run one round of a number guessing game where `number'
is the number the user is trying to guess."
(let ((guess nil)
(incorrect t))
(loop do
(format *query-io* "Enter a number: ")
(force-output *query-io*)
(setf guess (read-integer))
(format t
(cond
((< guess number) "The number is larger than ~D~%")
((> guess number) "The number is smaller than ~D~%")
(t "Correct! The number was ~D~%"))
guess)
(when (= guess number)
(setf incorrect nil))
while incorrect))
t)
(defun begin-number-guessing-game (&key one-shot (maximum 100))
"If `one-shot' is t, run one round of a number guessing game.
Otherwise run a chain of games until the user wants to stop.
In both cases, `:maximum' is the maximum possible number."
(when one-shot
(return-from begin-number-guessing-game
(attempt-guess (make-random maximum))))
(let ((playing nil))
(loop do
(attempt-guess (make-random maximum))
(setf playing (y-or-n-p "Play again?"))
(format t "~%")
while playing)))