diff --git a/00_Alternate_Languages/31_Depth_Charge/go/main.go b/00_Alternate_Languages/31_Depth_Charge/go/main.go new file mode 100644 index 00000000..0ab3f876 --- /dev/null +++ b/00_Alternate_Languages/31_Depth_Charge/go/main.go @@ -0,0 +1,156 @@ +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) +}