package main import ( "bufio" "fmt" "math" "math/rand" "os" "strconv" "strings" "time" ) type Position []int func NewPosition() Position { p := make([]int, 3) return Position(p) } func showWelcome() { fmt.Print("\033[H\033[2J") fmt.Println(" DEPTH CHARGE") fmt.Println(" Creative Computing Morristown, New Jersey") fmt.Println() } func getNumCharges() (int, int) { scanner := bufio.NewScanner(os.Stdin) for { fmt.Println("Dimensions of search area?") scanner.Scan() dim, err := strconv.Atoi(scanner.Text()) if err != nil { fmt.Println("Must enter an integer number. Please try again...") continue } return dim, int(math.Log2(float64(dim))) + 1 } } func askForNewGame() { scanner := bufio.NewScanner(os.Stdin) fmt.Println("Another game (Y or N): ") scanner.Scan() if strings.ToUpper(scanner.Text()) == "Y" { main() } fmt.Println("OK. Hope you enjoyed yourself") os.Exit(1) } func showShotResult(shot, location Position) { result := "Sonar reports shot was " if shot[1] > location[1] { // y-direction result += "north" } else if shot[1] < location[1] { // y-direction result += "south" } if shot[0] > location[0] { // x-direction result += "east" } else if shot[0] < location[0] { // x-direction result += "west" } if shot[1] != location[1] || shot[0] != location[0] { result += " and " } if shot[2] > location[2] { result += "too low." } else if shot[2] < location[2] { result += "too high." } else { result += "depth OK." } fmt.Println(result) } func getShot() Position { scanner := bufio.NewScanner(os.Stdin) for { shotPos := NewPosition() fmt.Println("Enter coordinates: ") scanner.Scan() rawGuess := strings.Split(scanner.Text(), " ") if len(rawGuess) != 3 { goto there } for i := 0; i < 3; i++ { val, err := strconv.Atoi(rawGuess[i]) if err != nil { goto there } shotPos[i] = val } return shotPos there: fmt.Println("Please enter coordinates separated by spaces") fmt.Println("Example: 3 2 1") } } func getRandomPosition(searchArea int) Position { pos := NewPosition() for i := 0; i < 3; i++ { pos[i] = rand.Intn(searchArea) } return pos } func playGame(searchArea, numCharges int) { rand.Seed(time.Now().UTC().UnixNano()) fmt.Println("\nYou are the captain of the destroyer USS Computer.") fmt.Println("An enemy sub has been causing you trouble. Your") fmt.Printf("mission is to destroy it. You have %d shots.\n", numCharges) fmt.Println("Specify depth charge explosion point with a") fmt.Println("trio of numbers -- the first two are the") fmt.Println("surface coordinates; the third is the depth.") fmt.Println("\nGood luck!") fmt.Println() subPos := getRandomPosition(searchArea) for c := 0; c < numCharges; c++ { fmt.Printf("\nTrial #%d\n", c+1) shot := getShot() if shot[0] == subPos[0] && shot[1] == subPos[1] && shot[2] == subPos[2] { fmt.Printf("\nB O O M ! ! You found it in %d tries!\n", c+1) askForNewGame() } else { showShotResult(shot, subPos) } } // out of depth charges fmt.Println("\nYou have been torpedoed! Abandon ship!") fmt.Printf("The submarine was at %d %d %d\n", subPos[0], subPos[1], subPos[2]) askForNewGame() } func main() { showWelcome() searchArea, numCharges := getNumCharges() playGame(searchArea, numCharges) }