猜谜游戏实践 | 青训营

74 阅读3分钟

使用的包的说明

  1. "bufio":bufio包实现了有缓冲的I/O

  2. "fmt":在本程序中用于输入与输出

  3. "log":使用log.Fatal()在报错之后立即终止整个程序(不执行defer)

  4. "math/rand"生成随机数用

  5. "os":标准输入文件的指针

  6. "strconv":代码中用于基本数据类型和字符串的相互转换

    以及"strings"、"time",用于处理字符串和生成随机数种子

代码实现思路

  1. 首先基于获得time.Now().Unix()与rand.Seed()方法获得随机数种子
  2. 确定最大值100,最小值1,赋值给guessMaxguessMin
  3. 从键盘获得输入guess,并转换为int类型与生成的随机数target进行比较
  4. 如果guess小于随机数target就将guess赋值给guessMin
  5. 如果guess大于随机数target就将guess赋值给guessMax
  6. 输出提示范围[guessMin, guessMax]
  7. 使用for循环,将3~6循环操作,循环10次
  8. 创建函数Max(int, int)Min(int, int),使得每次判断时,范围只会缩小guessMinguessMax
  9. 若猜测的数字过小,输出提示太小了,新的范围是[guessMin,guessMax]
  10. 若猜测的数字过大,输出提示太大了,新的范围是[guessMin,guessMax]
  11. 若猜对数字,则直接结束循环,使用break跳出
  12. 创建bool值变量success,赋值为false
  13. 若猜对数字就将true赋给success
  14. 循环结束后进行判断,若十次都没有猜中,则执行输出语句,将随机数target输出

代码实现

package main  
  
import (  
    "bufio"  
    "fmt"  
    "log"  
    "math/rand"  
    "os"  
    "strconv"  
    "strings"  
    "time"  
)  
  
// main函数在程序启动时调用  
func main() {  
    seconds := time.Now().Unix()
    rand.Seed(seconds)  
    target := rand.Intn(100) + 1 //生成一个介于1和100之间的随机整数  
    fmt.Printf("随机数已经生成")  
    fmt.Println("开始输入你猜的数字")  

    reader := bufio.NewReader(os.Stdin) //创建bufio.Reader读取键盘输入  

    success := false  
    guessMax := 100  
    guessMin := 0  
    for num := 0; num < 10; num++ {  
        fmt.Println("你还有", 10-num, "次机会")  
        fmt.Print("你猜的数字为:")  
        input, err := reader.ReadString('\n') //读取输入内容,直到他们按了<Enter>键  
        if err != nil {  
            log.Fatal(err)  
        }  

        input = strings.TrimSpace(input)     //删除换行符
        guess, err := strconv.Atoi(input)    //子符串转换为整数  
        if err != nil {  
            log.Fatal(err)  
        }  

        if guess < target {  
            guessMin = Min(guessMin, guess)  
            fmt.Printf("太小了,新的范围是[%d,%d]\n", guessMin, guessMax)  
        } else if guess > target {  
            guessMax = Max(guessMax, guess)  
            fmt.Printf("太大了,新的范围是[%d,%d]\n", guessMin, guessMax)  
        } else {  
            success = true  
            fmt.Println("恭喜你猜对了")  
            break  
        }  
    }  
    if !success {  
        fmt.Println("你没有猜到,随机数是:", target)  
    }  
}

func Min(num1 int, num2 int) int {  
    if num1 > num2 {  
        return num1  
    } else {  
        return num2  
    }  
}  

func Max(num1 int, num2 int) int {  
    if num1 > num2 {  
        return num2  
    } else {  
        return num1  
    }  
}

路径记录

  1. 随机数生成错误,伪随机数,数值固定

  2. 键盘输入有误,输入有误无法执行,不再使用fmt.Scanf格式输入

  3. 判断条件错误,使用max、min限制范围

  4. 范围波动,max、min方法替换为guessMaxguessMin,限制范围只能缩小

  5. 结束后缺少提示,不输出随机数结果,无法判断对错

问题解决

  1. 随机数问题,首次使用随机数时没有使用时间作为随机种子,使得随机数为伪随机数
  2. 最大值与最小值范围判断:直接赋值时,每次输入都会改变范围,范围时大时小,使用函数解决,每次范围只能缩小,不允许增加
  3. 循环次数用完不输出结果,创建bool值变量success
  4. 报错检查,借助GoLand软件对代码进行检查,删除冗余部分代码,提高可读性

学习收获

  1. 将多次循环代码拆分,以单独一次循环内容,解决复杂高重复性问题
  2. 通过函数实现对重复代码的复用,减少输入对程序运行的影响,将影响限制在可控范围内
  3. 调用多个包,充分了解各个包之间如何互相配合,降低代码复杂度,提高代码可读性,便于阅读代码
  4. 代码测试阶段,以不同方式进行测试,多方面查找问题