diff --git a/snippets/lispbox/guess.lisp b/snippets/lispbox/guess.lisp new file mode 100644 index 0000000..0130ac8 --- /dev/null +++ b/snippets/lispbox/guess.lisp @@ -0,0 +1,49 @@ +;; 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)))