mirror of
https://github.com/coding-horror/basic-computer-games.git
synced 2025-12-22 07:10:42 -08:00
160 lines
3.4 KiB
Go
160 lines
3.4 KiB
Go
package main
|
|
|
|
import (
|
|
"bufio"
|
|
"fmt"
|
|
"log"
|
|
"os"
|
|
"strings"
|
|
)
|
|
|
|
type node struct {
|
|
text string
|
|
yesNode *node
|
|
noNode *node
|
|
}
|
|
|
|
func newNode(text string, yes_node, no_node *node) *node {
|
|
n := node{text: text}
|
|
if yes_node != nil {
|
|
n.yesNode = yes_node
|
|
}
|
|
if no_node != nil {
|
|
n.noNode = no_node
|
|
}
|
|
return &n
|
|
}
|
|
|
|
func (n *node) update(newQuestion, newAnswer, newAnimal string) {
|
|
oldAnimal := n.text
|
|
|
|
n.text = newQuestion
|
|
|
|
if newAnswer == "y" {
|
|
n.yesNode = newNode(newAnimal, nil, nil)
|
|
n.noNode = newNode(oldAnimal, nil, nil)
|
|
} else {
|
|
n.yesNode = newNode(oldAnimal, nil, nil)
|
|
n.noNode = newNode(newAnimal, nil, nil)
|
|
}
|
|
}
|
|
|
|
func (n *node) isLeaf() bool {
|
|
return (n.yesNode == nil) && (n.noNode == nil)
|
|
}
|
|
|
|
func listKnownAnimals(root *node) {
|
|
if root == nil {
|
|
return
|
|
}
|
|
|
|
if root.isLeaf() {
|
|
fmt.Printf("%s ", root.text)
|
|
return
|
|
}
|
|
|
|
if root.yesNode != nil {
|
|
listKnownAnimals(root.yesNode)
|
|
}
|
|
|
|
if root.noNode != nil {
|
|
listKnownAnimals(root.noNode)
|
|
}
|
|
}
|
|
|
|
func parseInput(message string, checkList bool, rootNode *node) string {
|
|
scanner := bufio.NewScanner(os.Stdin)
|
|
token := ""
|
|
|
|
for {
|
|
fmt.Println(message)
|
|
scanner.Scan()
|
|
inp := strings.ToLower(scanner.Text())
|
|
|
|
if checkList && inp == "list" {
|
|
fmt.Println("Animals I already know are:")
|
|
listKnownAnimals(rootNode)
|
|
fmt.Println()
|
|
}
|
|
|
|
if len(inp) > 0 {
|
|
token = inp
|
|
} else {
|
|
token = ""
|
|
}
|
|
|
|
if token == "y" || token == "n" {
|
|
break
|
|
}
|
|
}
|
|
return token
|
|
}
|
|
|
|
func avoidVoidInput(message string) string {
|
|
scanner := bufio.NewScanner(os.Stdin)
|
|
answer := ""
|
|
for {
|
|
fmt.Println(message)
|
|
scanner.Scan()
|
|
answer = scanner.Text()
|
|
|
|
if answer != "" {
|
|
break
|
|
}
|
|
}
|
|
return answer
|
|
}
|
|
|
|
func printIntro() {
|
|
fmt.Println(" Animal")
|
|
fmt.Println(" Creative Computing Morristown, New Jersey")
|
|
fmt.Println("\nPlay 'Guess the Animal'")
|
|
fmt.Println("Think of an animal and the computer will try to guess it")
|
|
}
|
|
|
|
func main() {
|
|
yesChild := newNode("Fish", nil, nil)
|
|
noChild := newNode("Bird", nil, nil)
|
|
rootNode := newNode("Does it swim?", yesChild, noChild)
|
|
|
|
printIntro()
|
|
|
|
keepPlaying := (parseInput("Are you thinking of an animal?", true, rootNode) == "y")
|
|
|
|
for keepPlaying {
|
|
keepAsking := true
|
|
|
|
actualNode := rootNode
|
|
|
|
for keepAsking {
|
|
if !actualNode.isLeaf() {
|
|
answer := parseInput(actualNode.text, false, nil)
|
|
|
|
if answer == "y" {
|
|
if actualNode.yesNode == nil {
|
|
log.Fatal("invalid node")
|
|
}
|
|
actualNode = actualNode.yesNode
|
|
} else {
|
|
if actualNode.noNode == nil {
|
|
log.Fatal("invalid node")
|
|
}
|
|
actualNode = actualNode.noNode
|
|
}
|
|
} else {
|
|
answer := parseInput(fmt.Sprintf("Is it a %s?", actualNode.text), false, nil)
|
|
if answer == "n" {
|
|
newAnimal := avoidVoidInput("The animal you were thinking of was a ?")
|
|
newQuestion := avoidVoidInput(fmt.Sprintf("Please type in a question that would distinguish a '%s' from a '%s':", newAnimal, actualNode.text))
|
|
newAnswer := parseInput(fmt.Sprintf("For a '%s' the answer would be", newAnimal), false, nil)
|
|
actualNode.update(newQuestion+"?", newAnswer, newAnimal)
|
|
} else {
|
|
fmt.Println("Why not try another animal?")
|
|
}
|
|
keepAsking = false
|
|
}
|
|
}
|
|
keepPlaying = (parseInput("Are you thinking of an animal?", true, rootNode) == "y")
|
|
}
|
|
}
|