Programming in Go

When I start learning a new programming language I often write the program to play the “Guess the Animal” game to get a feel for the language. Below is a simple version of this game written in Go.  The program starts “knowing” only about two animals, but as you play it it “learns” more, by asking you to provide new animals and new questions.

Here is the code. Enjoy!


package main

import (
	"bufio"
	"fmt"
	"os"
)

type Question struct {
	text      string
	yesAnswer *Question
	noAnswer  *Question
}

func yesOrNo(prompt string) (answer string) {
	fmt.Printf("%s [y/n]? ", prompt)
	fmt.Scanln(&answer)
	return answer
}

func (q *Question) isLeaf() bool {
	return q.yesAnswer == nil && q.noAnswer == nil
}

func (q *Question) ask() (result *Question, answer string) {
	answer = yesOrNo(q.text)
	if answer == "y" {
		result = q.yesAnswer
	} else {
		result = q.noAnswer
	}
	return result, answer
}

var root *Question

func initialize() *Question {
	shark := Question{"shark", nil, nil}
	cat := Question{"cat", nil, nil}
	return &Question{"Is it a mamal", &cat, &shark}
}

func addAnimal(q *Question) {
	var animal, question string
	fmt.Printf("Ok. I give up. What animal is it? ")
	fmt.Scanln(&animal)
	fmt.Printf(
		"Enter a question to tell a difference between %s and %s: ",
		animal, q.text)
	reader := bufio.NewReader(os.Stdin)
	line, _, _ := reader.ReadLine()
	question = string(line)
	answer := yesOrNo(fmt.Sprintf("And for %s the answer is", 
		animal))
	oldAnimal := Question{q.text, nil, nil}
	q.text = question
	newAnimal := Question{animal, nil, nil}
	if answer == "y" {
		q.yesAnswer = &newAnimal
		q.noAnswer = &oldAnimal
	} else {
		q.yesAnswer = &oldAnimal
		q.noAnswer = &newAnimal
	}
}

func play() {
	var answer string
	currentQuestion := root
	for !currentQuestion.isLeaf() {
		currentQuestion, answer = currentQuestion.ask()
	}
	answer = yesOrNo(fmt.Sprintf("Is it a %s", 
		currentQuestion.text))
	if answer == "y" {
		fmt.Printf("OK!!! Got it!!\n")
	} else {
		addAnimal(currentQuestion)
	}
}

func main() {
	root = initialize()
	quit := "n"
	for quit == "n" {
		play()
		quit = yesOrNo("Quit ")
	}
}

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s