The “Guess-my-number” game in LISP.

João Augusto Perin
4 min readMay 20, 2020

Well hi there! 🙋‍♂️

First of all I should say that the following post was originally made by me on my old tumblr page, meant for portuguese readers. It was more like a study diary. Every time I come up with new exciting thins I’d post there. But now, this is the correct place, so here it goes. Hope you enjoy it. 😃

You probably already heard or maybe even made a game like this. It works like this:

> (guess-my-number) 50 > (smaller) 25 > (smaller) 12 > (bigger) 18 > (bigger) 21 > (bigger) 23

To make this game we’ll have to make 3 functions and 2 global variables, namely:

Defining the small and big Variables

A variable that is defined globally in Lisp is called a top-level definition. We can create new top-level definitions with the defparameter function:

> (defparameter *small* 1) *SMALL* > (defparameter *big* 100) *BIG*

The function name defparameter is a bit confusing, since it doesn’t really have anything to do with parameters. What it does is let you define a global variable. The first argument we send to defparameter is the name of the new variable.

Altough it’s just a convention, it’s higly recommended to use the earmuffs (the asteristics after & before) a global variable name.

An Alternative Global Variable Definition Function

When you set the value of a global variable using defparameter, any value previously stored in the variable will be overwritten:

> (defparameter *foo* 5) FOO > *foo* 5 24 Chapter 2 > (defparameter *foo* 6) FOO > *foo* 6

As you can see, when we redefine the variable foo, its value changes. Another command that you can use for declaring global variables, called defvar, won’t overwrite previous values of a global variable:

> (defvar *foo* 5) FOO > *foo* 5 > (defvar *foo* 6) FOO > *foo* 5

Some Lispers prefer to use defvar instead of defparameter when defining global variables. In this book, however, we’ll be using defparameter exclusively.

Our guess-my-number game has the computer respond to the player’s request to start the game, and then to requests for either smaller or bigger guesses. For these, we need to define three global functions: guess-my-number, smaller, and bigger. We’ll also define a function to start over with a different number, called start-over. In Common Lisp, functions are defined with defun, like this:

(defun function_name (arguments) ...)

First, we specify the name and arguments for the function. Then we follow it up with the code that composes the function’s logic.

Defining the guess-my-number Function

The first function we’ll define is guess-my-number. This function uses the values of the big and small variables to generate a guess of the player’s number. The definition looks like this:

> (defun guess-my-number () (ash (+ *small* *big*) -1)) GUESS-MY-NUMBER

The empty parentheses, (), after the function name guess-my-number indicate that this function doesn’t require any parameters.

We implement this in the guess-my-number function by first adding the numbers that represent the high and low limits, then using the arithmetic shift function, ash, to halve the sum of the limits and shorten the result

Defining the smaller and bigger Functions

Now we’ll write our smaller and bigger functions. Like guess-my-number, these are global functions defined with defun:

> (defun smaller ()(setf *big* (1- (guess-my-number))) (guess-my-number)) SMALLER > (defun bigger () (setf *small* (1+ (guess-my-number))) (guess-my-number)) BIGGER

First, we use defun to start the definition of a new global function smaller. Because this function takes no parameters, the parentheses are empty.

Next, we use the setf function to change the value of our global variable big Y. Since we know the number must be smaller than the last guess, the biggest it can now be is one less than that guess. The code (1- (guess-my-number)) calculates this: It first calls our guess-my-number function to get the most recent guess, and then it uses the function 1-, which subtracts 1 from the result.

Finally, we want our smaller function to show us a new guess. We do this by putting a call to guess-my-number as the final line in the function body Z. This time, guess-my-number will use the updated value of big, causing it to calculate the next guess. The final value of our function will be returned automatically, causing our new guess (generated by guess-my-number) to be returned by the smaller function.

The bigger function works in exactly the same manner, except that it raises the small value instead. After all, if you call the bigger function, you are saying your number is bigger than the previous guess, so the smallest it can now be (which is what the small variable represents) is one more than the previous guess. The function 1+ simply adds 1 to the value returned by guess-my-number.

Defining the start-over Function

To complete our game, we’ll add the function start-over to reset our global variables:

(defun start-over () (defparameter *small* 1) (defparameter *big* 100) (guess-my-number))

And voilla, our game is done! Hope you learned today! See ya :)

Originally published at https://www.tumblr.com on May 20, 2020.

--

--

João Augusto Perin

I don’t know how to describe myself actually…maybe a hypothetical jedi? God no…that sounds like a bad album title from an underground 80’s band.