Go语言实战:猜谜游戏| 青训营

78 阅读3分钟

这是一个很经典的案例,我们将使用Golang来构建一个猜数字的游戏。

内容介绍

在这个游戏里面,程序首先会生成一个介于1~100之间的随机整数,然后提示玩家进行猜测。玩家每次输入一个数字,程序会告诉玩家这个猜测的值是高于还是低于那个秘密的随机数,并且让玩家再次猜测。如果猜对了就告诉玩家胜利并且退出程序。

设计

想要完成一件事,就要在大脑中提前构思一下完成这件事的框架。当然,做猜字谜游戏也不例外。我们想要的效果:

  • 生成一个随机数
  • 从用户那里接收数据
  • 程序比较数据与生成的随机数
  • 返回比较结果

一、生成一个随机数

我们先从第一步开始,在Java中我们可以使用math/rand包 生成随机数。在Golang中也不例外,甚至名字都一样,我们使用math/rand包生成随机数。导入了math/rand包,我们就可以完成第一步:

import (
    "fmt"
    "math/rand"
)

然后我们这样写主方法

func main() {
    maxNum := 100
    rand.Seed(time.Now().UnixNano())
    secretNumber := rand.Intn(maxNum)
    fmt.Println("The secret number is ", secretNumber)
}

需要注意的是:

  • 第一行我们定义了一个变量maxNum,这是用来界定随机数的最大值100。
  • 第二行很关键,因为使用这个包之前需要设置随机数种子,否则的话每一次生成相同的随机序列,一般的惯例用法是在程序启动的时候,用启动的时间戳来初始化随机种子。我们用time.now.unix来初始化随机种子。
  • 第三行,我们调用Intn函数,生成了一个随机数并存入变量secretNumber

二、接收数据

我们先从底层逻辑开始。

每个程序执行的时候都会打开几个文件,stdin stdout stderr等,stdin 文件(in也就是输入流)可以用 os.Stdin 来得到。

但是,直接操作这个文件很不方便,我们会用 bufio.NewReader 把一个文件转换成一个 reader 变量。

reader变量上会有很多用来操作一个流的操作,我们可以用它的 ReadString 方法来读取一行。

如果读取失败,我们能打印错误并退出。

注意!

ReadString返回的结果包含结尾的换行符,我们应当先把它去掉,再转换成数字。如果转换失败,我们同样打印错误,退出。

代码如下:

reader := bufio.NewReader(os.Stdin)

input, err := reader.ReadString('\n')

input = strings.Trim(input, "\r\n")//去掉换行符

guess, err := strconv.Atoi(input)//将输入转化为数字

三、比较数据并返回结果

我们直接用if判断并返回就好

if err != nil {
    fmt.Println("An error occured while reading input. Please try again", err)
    return
}
if err != nil {
    fmt.Println("Invalid input. Please enter an integer value")
    return
}

这样一个猜谜游戏就做好了

package main

import (
    "bufio"
    "fmt"
    "math/rand"
    "os"
    "strconv"
    "strings"
    "time"
)

func main() {
    maxNum := 100
    rand.Seed(time.Now().UnixNano())
    secretNumber := rand.Intn(maxNum)
    // fmt.Println("The secret number is ", secretNumber)

    fmt.Println("Please input your guess")
    reader := bufio.NewReader(os.Stdin)
    for {
       input, err := reader.ReadString('\n')
       if err != nil {
          fmt.Println("An error occured while reading input. Please try again", err)
          continue
       }
       input = strings.Trim(input, "\r\n")

       guess, err := strconv.Atoi(input)
       if err != nil {
          fmt.Println("Invalid input. Please enter an integer value")
          continue
       }
       fmt.Println("You guess is", guess)
       if guess > secretNumber {
          fmt.Println("Your guess is bigger than the secret number. Please try again")
       } else if guess < secretNumber {
          fmt.Println("Your guess is smaller than the secret number. Please try again")
       } else {
          fmt.Println("Correct, you Legend!")
          break
       }
    }
}

但是玩家只能输入一次猜测,无论猜测是否正确,程序都会退出。

为了改变这种行为,让游戏可以正常玩下去,我们需要加一个循环,我们把刚刚的代码挪到一个for循环里面,然后再把return改成continue,以便于在出错的时候能够继续循环,在用户输入正确的时候break,这样才能在用户胜利的时候退出游戏。

怎么样是不是很简单呢?