讲动人的故事,写懂人的代码
2.6 故事4: 一直让玩家不断猜
我们全班要一起用三种语言来写第4个故事啦。这可能是我们所有故事中最复杂的一个了。不过别担心,贾克强已经把这个故事的需求都用投影仪展示出来了。
- 程序会提示玩家猜两个骰子的点数之和。
- 如果玩家第一次输入点数之和就答错了,程序就会提示‘第一次猜就错了哦’(You guessed it wrong on the first try.),并让玩家继续猜。
- 如果玩家第二次或之后输入点数之和也答错了,但这次猜测比上次更接近正确答案,程序就会提示‘更热了’(Hotter.),并让玩家继续猜。
- 如果离正确答案更远了,程序就会提示‘更冷了’(Colder.),并让玩家继续猜。
- 如果距离正确答案的距离和上次一样,程序就会提示‘不冷不热’(Neither cold nor hot.),并让玩家继续猜。
- 如果玩家猜对了,程序就会提示‘恭喜你答对了!’(You win!),并让玩家继续猜。
贾克强:“故事4对于Rust新手来说,可能有些挑战性。但别担心,这个故事,我来帮你们写Rust代码哦。”
2.6.1 Rust版故事4
2.6.1.1 初始化 previous_guess
贾克强:“故事4是让玩家不断地猜测,所以我们把原来只猜一次的代码,放入了一个循环中。这样一来,就不需要原来猜一次的代码了。“
”然后,我们新增了一行代码。为了能判断玩家的猜测是否接近答案,我们增加了一个previous_guess
变量来存储玩家的上一次猜测。在玩家第一次猜测之前,previous_guess
变量的值应该为空。但是,一旦玩家猜了第一次,这个变量就不会再是空的。因此,我们为这个变量使用了Option<u32>
类型。这意味着previous_guess
既可以是一个u32
的32位无符号整数(表示玩家猜测的点数),也可以是None
(表示玩家还没有猜测过)。在Rust中,None
是一个枚举值(也就是枚举类型Option<u32>
的变体),用来表示‘无效’或‘未设置’。“
- println!("Please input your guess (between 2 and 12).");
-
- let mut guess = String::new();
-
- io::stdin()
- .read_line(&mut guess)
- .expect("Failed to read line");
-
- let guess: u32 = guess.trim().parse().expect("Please type a number!");
-
- println!("You guessed: {guess}");
-
- match guess.cmp(&sum_of_two_dice) {
- Ordering::Less | Ordering::Greater => println!("You guessed it wrong on the first try"),
- Ordering::Equal => println!("You win!"),
- }
+ let mut previous_guess: Option<u32> = None;
2.6.1.2 增加循环结构
贾克强:“我们在这里添加了一个loop
循环,让代码能够反复进行玩家的输入和猜测。loop
在Rust中是一个无尽的循环,但别担心,我们在后面的故事中,可以使用break
语句来结束它哦!”
+ loop {
2.6.1.3 获取玩家输入
贾克强:“这部分代码和原代码有些相似,它们都是把玩家的输入读取出来,然后解析成u32
类型的整数哦。”
+ println!("Please input your guess (between 2 and 12).");
+
+ let mut guess = String::new();
+
+ io::stdin()
+ .read_line(&mut guess)
+ .expect("Failed to read line");
+
+ let guess: u32 = guess.trim().parse().expect("Please type a number!");
+
+ println!("You guessed: {guess}");
2.6.1.4 新的比较逻辑
贾克强兴奋地解释道:“这里,我们新增了对previous_guess
的检查哦。如果previous_guess
是None
(也就是说这是我们的第一次猜测),我们就直接将当前的猜测和骰子的和进行比较。若玩家第一次猜得不对,那我们就会把当前的猜测存入previous_guess
中。”
他继续说:“Some(guess)
的意思是,我们把guess
封装在一个Some
枚举中,并赋值给previous_guess
,这样previous_guess
保存的值就从None
变成了Some(guess)
。这就意味着,previous_guess
不再是空的了,而是包含了玩家上一次的猜测值哦。”
+ match previous_guess {
+ None => match guess.cmp(&sum_of_two_dice) {
+ Ordering::Less | Ordering::Greater => {
+ println!("You guessed it wrong on the first try.");
+ previous_guess = Some(guess);
+