First Programming Project Part I
When teaching some one to program, I’m often tempted to talk about things like functions, structs, interfaces, front end vs back end, databases, heap vs stack, etc. These are parts of programming, but they aren’t very fun to learn about outside of a useful context. Really, what I should be teaching is not “how to program” but “how to solve problems with software.” I’ve written lots of code, I’ve worked with so many different databases, caching layers, 3rd party libraries, UI frontends and various middlewares that I’ve forgotten how it started. To get started with programming, all you need is a vision for what you want a computer to do. It doesn’t matter that you don’t know how to make the computer do it. It all starts with the vision. I remember the first program that I wrote as an 11 year old. I’m going to try to think through that process and show how I did it. It all started with the desire to write a simple game back in ‘84.
I wanted to write a number guessing game. The computer would come up with a number, but not tell me what the number was. I would guess and it would tell me if my guess was too high or too low. I’d keep guessing until I got it. Not a particulary amazing game by any stretch, but I wanted to see if I could do it. I wanted to play a game that I wrote. If it didn’t work I could always go back to the 2600.
In 1984 I had to look up things in a big three ring binder for the TI-99 4/A to figure out how to make the computer do things. I wrote my first proram using TI Basic which is a little hard to come by these days. For this post I’m going to use the free open source language Go. While learning to program, you may find yourself having to look through big thick books from time to time, but you’ll find most of the answers to your questions by googling.
First, I need to get the computer to run some code. I learn that for Go programs, the computer starts looking for instructions in a fuction called main
. I learned this by typing “how to run code using go” and reading the top article. There’s stuff in there about packages, imports and fucntions. What is a function? What is a package? Who cares? I’m just going to copy func main()
out of an article and paste it. So far I have:
func main(){
}
I’m going to leave the
package
andimport
stuff at the top out of the code snippets. The final program will include them.
When searching online for things about the Go programming language, use the term
golang
instead of just Go. This helps differentiate between Go the game and Go the programming language.
Next I need a random number from the computer, how do I do that? I want the number to be from 1 to 100. Again, I type “golang how to generate a random number from 1 to 100” into google’s search engine. Looks like there are lots of ways to do it. I read and read and find that rand.Intn(100)
will give me a random integer from 1 to 100 and fmt.Println
will print that number to the command line.
func main() {
fmt.Println(rand.Intn(100))
}
I run this code and I get back a number, 81! I run it again, 81. I run it again…81. Hmm. Seems like I should get a random number, but I get back the same one every time. I do some reading(again, to find something out go to google, type the word “golang” followed by your question) and learn that this random number generator (and lots of others) will generate the same sequence of numbers unless the seed changes. What is the seed? Wait, if I have to give a random seed to get a random number, I’m no closer to my goal than before. I need the computer to give me a random number without me giving it a seed! I keep reading and find out that you can pass time to the random (rand
) function as the seed. The current time is always changing so if we use time as the random seed, then every time we ask for a random number, we should get a new one. So I do this:
func main() {
var n int
rand.Seed(int64(time.Now().Nanosecond()))
n =rand.Intn(100)
}
A nanosecond is a billionth of a second. That should be different each time I run it. It’s possible I’ll get the same number now and then, but this is good enough for what I want to do. I just want to make a silly game! Now when I run my code I get a different number each time! Hurray!
Now I’m printing the number out to the command line. I don’t want to see the number, I want to guess it. So I read some more and discover the term variable. A variable let’s me store a value and use it later. This sounds promising. I have to give my variable a name so I give it the name n
(short for number).
var n int
rand.Seed(int64(time.Now().Nanosecond()))
n = rand.Intn(100)
fmt.Printf("Enter your guess: ")
I have a variable n that holds my random number. But I still have a problem. How do I get a guess from the player? Right now my code just prints the phrase "Enter your guess:"
but there’s no way to find out what the player typed. I do some more research and find out that fmt.Println
will put words on the commmand line, but fmt.Scanln
will take words from the command line. Interesting. I also learn that fmt.Println
automatically goes to a new line after it prints, but I want the guess to be on the same line, so I found out about fmt.Printf
which does the same thing, but no new line! I use fmt.Printf
to put words on the command line, and fmt.Scanln
to take words from the command line and put them into a different variable g
(short for guess). Now I’m here:
var n int
var g int
rand.Seed(int64(time.Now().Nanosecond()))
n = rand.Intn(100)
fmt.Printf("Enter your guess: ")
fmt.Scanln(&g)
Why does the
g
have a&
in front of it? You don’t have to know why at this point. You just know the code doesn’t work without it.
I have a random number now, but I don’t know what it is. I have a way to enter my guess, but I don’t know if I guessed correctly or not. I need to compare the two and print out something to the player depending on if they got it right or not. It’s like I want to say:
“If the guess equals the number, print out “You got it!”, otherwise say, “You got it wrong!”
I do some more reading and find out about IF
statements. Turns out the code I need to write is almost exactly what I wrote above:
var n int
var g int
rand.Seed(int64(time.Now().Nanosecond()))
n = rand.Intn(100)
fmt.Printf("Enter your guess: ")
fmt.Scanln(&g)
if g==n{
fmt.Println("You guessed it!")
} else {
fmt.Println("You got it wrong!")
}
Why
==
and not just=
? Again, you don’t have to know exactly why just yet, you just know that=
doesn’t work but==
does.
Turns out most of my guesses are wrong. Eventually I’ll get lucky and guess the right number, but I’d like to tell the user if they guessed too high or too low. I read some more about IF
statements and learn I can test for more than one scenario. I can do something like this:
func main() {
var n int
var g int
rand.Seed(int64(time.Now().Nanosecond()))
n = rand.Intn(100)
fmt.Printf("Enter your guess: ")
fmt.Scanln(&g)
if g == n {
fmt.Println("You guessed it!")
} else if g > n {
fmt.Println("Too high.")
} else {
fmt.Println("Too low.")
}
}
This is great! Now I can enter a guess and the computer will tell me if my guess is too high or too low. The problem is, I still only get one guess, but at least I know more about what was wrong with the guess. I want to keep on making guesses until I guess the number. I want to repeat the guessing code. I want to loop back to the part where I guess and try again. I read some more and discover something called a loop
. A loop
(also called a for loop) will execute a section of code and when the end of that section is reached, it’ll go back to the beginning. Perfect!
func main() {
var n int
var g int
rand.Seed(int64(time.Now().Nanosecond()))
n = rand.Intn(100)
for {
fmt.Printf("Enter your guess: ")
fmt.Scanln(&g)
if g == n {
fmt.Println("You guessed it!")
} else if g > n {
fmt.Println("Too high.")
} else {
fmt.Println("Too low.")
}
}
}
This works great! I can keep making guesses and eventually, with the handy hints given by the game, I can guess the number! The problem now is that once I guess the number I get prompted to keep on guessing, but the game should be over. Hmm.
After further reading, I realize I can solve this problem a number of different ways (this is true for just about any software problem). I could return
after I give the winning message. That effectively exits the program. I could also break
out of the for
loop and the program would exit when it reached the end of the code. I’m going to go with the break
method.
func main() {
var n int
var g int
rand.Seed(int64(time.Now().Nanosecond()))
n = rand.Intn(100)
for {
fmt.Printf("Enter your guess: ")
fmt.Scanln(&g)
if g == n {
fmt.Println("You guessed it!")
break
} else if g > n {
fmt.Println("Too high.")
} else {
fmt.Println("Too low.")
}
}
}
It works! Last thing I want to do is tell the player how many guesses they took. I need a variable to count the guesses. I’ll call this variable c
(short for count) and everytime I guess I want it to go up by 1. It takes a little time to figure out how to make the variable go up on its own, but varname = varname +1
seems to work. A little further reading shows I can print out a message to the command line that include a words and variable that holds the guess count.
func main() {
var n int
var g int
var c int
rand.Seed(int64(time.Now().Nanosecond()))
n = rand.Intn(100)
for {
fmt.Printf("Enter your guess: ")
fmt.Scanln(&g)
c = c + 1
if g == n {
fmt.Println("You guessed it!")
fmt.Println("No. Guesses: ", c)
break
} else if g > n {
fmt.Println("Too high.")
} else {
fmt.Println("Too low.")
}
}
}
That’s the game(full code here). There’s more we should add because there’s no telling what our players will enter as a guess. What if they enter -34
or 1034
or green
??? What if want to limit the guesses? What if we want to change the boundaries to something besides 1 too 100? I’ll finish that up in Part II.
Before I end I want to reiterate that a programmer does not have to know how to make the computer do something to write a program. All you need to do is have the vision of what you want and ask questions on the internet (or books) to answer the parts you don’t know. Overtime you’ll learn the basics and won’t have to look things up everytime. But you will always run into things you do not know how to do. Finding those answers, to me, is part of the fun of being a programmer.