Files
basic-computer-games/00_Alternate_Languages/31_Depth_Charge/go/main.go
2022-10-27 09:03:10 +10:00

157 lines
3.4 KiB
Go

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)
}