Go 实践项目01——猜谜游戏 | 青训营笔记

127 阅读3分钟

实践项目

1 猜谜游戏

随机生成一个100以内的正整数,进行猜测

1.1 生成随机数

time.Now().UnixNano() 作为随机数种子

rand.Intn(maxNum) 生成小于maxNum的正整数

  
  maxNum := 100
  rand.Seed(time.Now().UnixNano())
  secretNumber := rand.Intn(maxNum)
  fmt.Println("谜底是:",secretNumber)

1.2 读取用户输入

  1. fmt包

    1. Scanfunc Scan(a ...interface{}) (n int, err error)

      从标准输入扫描文本,将成功读取的空白分隔的值保存进成功传递给本函数的参数。

      换行视为空白。

      返回成功扫描的条目个数和遇到的任何错误。

      参数间以空格或回车键进行分割。

      如果输入的参数不够接收的,按回车后仍然会等待其他参数的输入。

      如果输入的参数大于接收的参数,只有给定数量的参数被接收,其他参数自动忽略。

        
        var a1 int
        var a2 string
        ​
        n, err := fmt.Scan(&a1, &a2)
      
    2. Scanffunc Scanf(format string, a ...interface{}) (n int, err error)

      Scanf也可以接收多个参数

      Scanf接收字符串时,只能在最后接收

      否则按照"%s%d"的格式进行接收时,无论输入多少字符(包含数字),都会被认定是第一个字符串的内容

        
        var a,c string
        var b,d int
        ​
        fmt.Scanf("%d%s", &b,&a)
        fmt.Println(a,b)
        fmt.Scanf("%s%d", &c,&d)
        fmt.Println(c,d)
      
    3. Scanlnfunc Scanln(a ...interface{}) (n int, err error)

      Scanln与Scan类似,但在换行时停止扫描,并且在最后一项之后必须有换行或EOF

      Scan在输入一个参数后进行回车,会继续等待第二个参数的键入

      Scanln在认定输入了一个参数就截止了,只会接收一个参数并产生error

  2. bufio包

    bufio包是对IO的封装,可以操作文件等内容,同样可以用来接收键盘的输入,此时对象不是文件等,而是os.Stdin,也就是标准输入设备

    对键盘输入来说,使用Reader对象(或Scanner对象)

    1. 创建Reader对象

        
        reader := bufio.NewReader(os.Stdin)
      
    2. ReadByte

      func (b *Reader) ReadByte() (c byte, err error)

      用来接收一个byte类型,会阻塞等待键盘输入

        
        package main
        ​
        import (
            "bufio"
            "fmt"
            "os"
        )
        ​
        func main() {
        ​
            reader := bufio.NewReader(os.Stdin)
        ​
            n, err := reader.ReadByte() // a
        ​
            fmt.Println("n = ", n)             // n =  97
            fmt.Println("string =", string(n)) // string = a
            fmt.Println("err = ", err)         // err =  <nil>
        ​
        }
      
    3. ReadBytes

      func (b *Reader) ReadBytes(delim byte) (line []byte, err error)

      输入参数为一个byte字符,当输入遇到该字符,会停止接收并返回

      接收的内容包括该停止字符以及前面的内容

        
        package main
        ​
        import (
            "bufio"
            "fmt"
            "os"
        )
        ​
        func main() {
        ​
            reader := bufio.NewReader(os.Stdin)
        ​
            n, err := reader.ReadBytes('\n')
        ​
            fmt.Println("n = ", n)
            fmt.Println("string =", string(n))
            fmt.Println("err = ", err)
        ​
        }
      

      Reader可以接收包含空格内容的字符串,而不进行分割

      这是bufio.Reader与fmt的一大不同

5.1.3 代码

  
  package main
  ​
  import (
      "fmt"
      "math/rand"
      "strconv"
      "strings"
      "time"
  )
  ​
  func main(){
      maxNum := 100
      rand.Seed(time.Now().UnixNano())
      secretNumber := rand.Intn(maxNum)
      fmt.Println("谜底是:",secretNumber)
  ​
      var input string
      small := 0
      big := 100
  ​
      fmt.Print("请输入你的猜测:")
      for{
          _, err := fmt.Scanf("%v\n", &input)
          if err != nil{
              fmt.Println("读取输入出现错误,请重试!",err)
              continue
          }
          input = strings.Trim(strings.TrimSuffix(input, "\n"), "\r")
  ​
          guess, err := strconv.Atoi(input)
          if err != nil{
              fmt.Println("输入错误,请输入正整数!")
              continue
          }
          fmt.Printf("你的输入是:%v,",guess)
  ​
          if guess > secretNumber{
              if big > guess{
                  big = guess
              }
              fmt.Printf("数字在 %2d —— %2d 之间,请重新输入\n",small,big)
          }else if guess < secretNumber{
              if small < guess{
                  small = guess
              }
              fmt.Printf("数字在 %2d —— %2d 之间,请重新输入\n",small,big)
          }else{
              fmt.Println("恭喜你猜对了,游戏结束!")
              break
          }
      }
  }
  ​

演示:

1684595830510.png