这是我参与「第五届青训营 」伴学笔记创作活动的第 3 天
ps:由于最近春节事务较多,走亲访友的,还有实验室布置的任务,所以一直是咕咕鸟,本来打算日更的。本文是对于伴学笔记第一天的案例1的代码实现和介绍。
1. 简介
在很多与朋友的聚会中,自然少不了玩一些助兴的小游戏,在这其中数字炸弹最为常见,那么什么是数字炸弹呢?
数字炸弹就是在一个数字范围内,有一个数字作为炸弹,谁猜中这个炸弹就被惩罚.比如范围是1 ~ 99,炸弹是60,然后猜了一个数字是30,30不是炸弹,那么现在猜数字的范围就缩小到30 ~ 100, 又猜了一个数字80,80也不是炸弹,那么现在又缩小范围到30~80,每次猜不能猜边界上的值,直到有人猜中这个炸弹,然后就受到惩罚。
而本文所实现的猜谜游戏可以说和数字炸弹十分相近,就让我来带着你用实现这个有意思的小游戏。
2. 猜谜游戏的迭代以及代码实现
2.1 使用rand类生成随机数
对于一个猜谜游戏的实现,那随机数的生成必不可少。而在GO语言中,要实现随机数的生成我们应当用到math/rand包中的函数,使用rand.Intn()函数生成随机数。具体代码如下:
package main
import (
"fmt"
"math/rand"
)
func main() {
maxNum := 100
secretNumber := rand.Intn(maxNum)
fmt.Println("The secret number is ", secretNumber)
}
2.2 随机数种子的生成
如果读者将上方代码进行了运行,那将会发现随机数正确生成了,但是却存在一个问题:生成的随机数它一直是同一个值,并不会因为执行而发生变化,这是为什么呢?
这是因为rand.Intn方法将返回一个非负伪随机数,其值范围在半开区间 [0, n)。而rand.Intn函数生成随机数会受随机数种子的影响,如果为输入随机数种子,将会使用默认的种子作为随机数种子。故而想要实现随机数的生成,我们还需要生成随机数种子。
我们可以将当前的时间作为随机数种子进行传入,以实现不同时间生成不同随机数的功能。在获取当前时间时,我们可以使用官方提供的time包,利用该包,高效的实现对时间的获取。具体代码优化如下:
package main
import (
"fmt"
"math/rand"
"time"
)
func main() {
maxNum := 100
rand.Seed(time.Now().UnixNano())
secretNumber := rand.Intn(maxNum)
fmt.Println("The secret number is ", secretNumber)
}
2.3 实现对用户输入的读取
在以上的代码,我们已经成功实现了对于随机数的生成。但作为一个猜谜游戏,用户的输入自然必不可少。想要实现对用户输入的读取,我们可以使用bufio中的NewReader方法将os.stdin标准输入流中的数据读取到reader变量中来,最后再使用strings包中的方法将"\n"进行去除。具体代码实现如下:
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)
input, err := reader.ReadString('\n')
if err != nil {
fmt.Println("An error occured while reading input. Please try again", err)
return
}
input = strings.Trim(input, "\r\n")
guess, err := strconv.Atoi(input)
if err != nil {
fmt.Println("Invalid input. Please enter an integer value")
return
}
fmt.Println("You guess is", guess)
}
2.4 实现对用户输入的判断逻辑
现在的代码已经能很好的实现数据的读取和随机数的生成了,接下来就是猜谜游戏的判断逻辑相关代码的编写。
对于猜谜游戏而言,判断逻辑应该是:假设生成的随机数值为X,如果用户输入的值与生成值相比,输入值小于生成值,则应当返回“输入值小了”;如果输入值大于生成值,则返回“输入值大了”;如果输入值等于生成值,则返回“恭喜你获胜”。具体相关代码如下:
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)
input, err := reader.ReadString('\n')
if err != nil {
fmt.Println("An error occured while reading input. Please try again", err)
return
}
input = strings.Trim(input, "\r\n")
guess, err := strconv.Atoi(input)
if err != nil {
fmt.Println("Invalid input. Please enter an integer value")
return
}
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!")
}
}
2.5 实现游戏循环,简易版猜谜游戏完成
在上方代码的基础上,我们可以发现已经完成了猜谜游戏的基本功能。但是在广泛的情况下,应当是没有猜中继续给玩家猜谜的机会,所以,我们可以将之前的代码放到一个循环之中,以期实现更加完善的代码功能,具体代码如下:
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
}
}
}
3. 课后作业——使用fmt.Scanf简化代码的实现
具体代码如下:
package main
import (
"fmt"
"math/rand"
"strconv"
"time"
)
func main() {
maxNum := 100
rand.Seed(time.Now().UnixNano())
secretNumber := rand.Intn(maxNum)
var input string
for {
fmt.Printf("Please input your guess: ")
fmt.Scanf("%v",&input)
fmt.Scanln()//使用scanln吸取换行符
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
}
}
}