Guess the Number

In this article we will build a complete guess the number game in Go. The game will run in the terminal. The purpose of this article is to show the basics of Go by building a fun little game. There is a Rust version of this game as well. You can see that article here. I wanted to find an application that I could create that would allow one to see the similarties as well as the differences between Go and Rust. I figured this could be fun.

Project Setup

We are going to need a few tools before we begin. You will need a text editor and the one that I feel has the best overall support for Go right now that is easy to use is VS Code. I also really recommend this editor if you plan on going through the Rust article I have written as well. VS Code supports extensions for both Go and Rust and I feel it will get you up and running quickly. I myself like to use NeoVim but if you aren’t familiar with Vim or NeoVim I would defnitely stick with VS Code for now. No sense in trying to learn an editor as complicated as Vim along with learning a new language. It will be very difficult. You can download VS Code here. Once you have it installed on your system I recommend going to the extensions tab on the left which looks like 4 blocks with one sticking up and typing in the search box Go. Also if you are going to do the Rust version you might as well search for Rust as well. Next we will go to the official Go website to download and install Go.Follow the installation wizard for your OS. Once you have Go installed we can run some commands. I have a set of optional commands but you can skip these as they aren’t needed any more when it comes to where you place your Go projects. Optional commands to run:

$ cd ~ 
$ mkdir go
$ cd go
$ mkdir bin
$ mkdir pkg
$ mkdir src

The above commands are optional and are no longer needed for your GOPATH. However if you want to create the directories you are more than welcome. Now the commands you can run on any system are:

$ cd Desktop
$ mkdir goProjects
$ cd goProjects
$ mkdir guessingGame
$ cd guessingGame
$ go mod init github.com/<github username>/guessingGame
$ code .

The above commands will change your working directory to your Desktop on your machine. From there you can create a new directory to store all of your Go projects. Then we change into that directory and create our guessingGame directory. We then change into that and initialize a Go module by running go mod init .... Finally we run code . to open up our project in VS Code. If you are getting an error about code not found or not a recognized command, something like that, then you need to open up VS Code and press ctrl + shift + p in order to bring up the command list and start to type path you should see Shell Command: Install 'code' command in PATH click that and then close out of VS Code and reopen your terminal and run the code . from your terminal again. We are now ready to start coding our game.

Creating Our File

From here we can right click on the left hand pane of VS code and select new file. We will call the file main.go. We are going to write some code to make sure that everything is working.

package main

import (
    "fmt"
    "math/rand"
)

func main() {
    randomNumber := rand.Intn(100) + 1
    fmt.Println(guess)
}

We can run our program to make sure that everything is working. Go ahead and run it multiple times to see what you get.

$ go run main.go

Uh oh, the program is only printing the number 82. Why is that? Let’s break this down a bit. We created a guess variable that using the Intn package from the Math/rand library. This produces a random number from 0 - 99 then we added the plus 1 making it 1 - 100 instead. The reason we are getting the same number over and over again is because random numbers on computers really aren’t that random. However there is a trick we can do to get a random number. Let’s modify our code to generate real random numbers.

package main

import (
    "fmt"
    "math/rand"
    "time"
)

func main() {
    seconds := time.Now().Unix()
    rand.Seed(seconds)
    randomNumber := rand.Int(100) + 1
    fmt.Println("I've chosen a random number between 1 and 100.")
    fmt.Println("Can you guess it?")
    fmt.Println(guess)
}

When we run this now we should be able to see several random numbers print out along with our messages about choosing a random number and whether or not the player can guess it. This is all coming together pretty well. Let’s go over what we did.

We are using the time.Now function to generate a random number based on the time it is. This helps us ensure that the seed number is unique each time our program is ran. We then used the rand.Seed function, which expecs an integer. We can’t pass it a Time value directly though so instead we use the Unix time format, which is an integer. Basically it’s the number of seconds that have passed since January 1, 1970. Not important but that’s why we are able to use it in this instance.

Getting Our Player’s Guess

We now need to get the input from our user. We can do that by adding a few more built in packages that Go has in it’s standard library. Update your imports to:

package main

import (
    "bufio"
    "fmt"
    "log"
    "math/rand"
    "os"
    "strconv"
    "strings"
    "time"
)

I will be leaving out some of the code from earlier as I don’t want to keep repeating the same lines. In our main function we will add the lines:

...
fmt.Println(randomNumber)

reader := bufio.NewReader(os.Stdin)

fmt.Print("Make a guess: ")
input, err := reader.ReadString('\n')
if err != nil {
    log.Fatal(err)
}
input = strings.TrimSpace(input)
guess, err := strconv.Atoi(input)
if err != nil {
    log.Fatal(err)
}

We have added the ability for our player to make a guess. We store it in the input variable. We first create a reader which will scan for user input. Once a player has input a number to guess we pass that to the input variable and then pass input to our strconv.Atoi function which converts strings to integers, and we store that in guess. The if statements like if err != nil those are our error handling. If you are new to Go, this might be a bit different from what you have done in the past. Go makes error handling a first class citizen so you will get used to seeing these lines of code the more you use the language.

Comparing Our Player’s Guess to the Random Number

We now have the ability to grab player input. Now all we need to do is run a comparison on whether or not the randomNumber is equal to the guess. If so then the player wins. Let’s add the condition now.

// No change to imports

func main() {
    // No changes made to above code. Place these next lines at the bottom of our main function
    if guess < randomNumber {
        fmt.Println("Too low!")
    } else if guess > target {
        fmt.Println("Too high!")
    }
}

We now have the ability to compare the guess to our randomNumber and print out a message to our players whether the guess was too high or too low. Perfect.

Game Loop

Now we need to allow the player to have a maximum of 10 guesses. We can do that using loops. Go is different from other languages as it only has the for keyword for looping. Now that’s not to say that you can’t create the other loops you might be used to from other languages. For our loop we are going to be using the traditional C style for loop. Let’s wrap our code in a for loop.

// nothing changed above this line
reader := bufio.NewReader(os.Stdin)

// add our for loop here
for guesses := 0; guesses < 10; guesses++ {
    fmt.Println("You have", 10 - guesses, "guesses left.")

    // add remaining code from main here
}

Great we now have our loop in place and we should be able to run the game and make our guesses and watch the count go down from 10 to show the remaining number of guesses. However we aren’t letting the player know if they win. The game just keeps looping. Let’s fix that now. In our main function where we have our if statements printing too high or too low let’s add an else statement.

if guess < randomNumber {

} else if guess > randomNumber {

} else {
    fmt.Println("You win!")
}

That’s it. Our game is finished. We can now remove the line of code that is printing out our randomNumber when we run the game. No need to let the player know what the number is before they have a chance to guess it.

Conclusion

That’s it. I hope you enjoyed seeing how to make a guess the number game with Go. It’s a fun exercise to see the same app built in different languages. I feel it helps you comprehend a new language and it’s syntax a bit easier.