去台湾玩儿了一个礼拜,赶紧回来继续翻译吧!
3.1.5 循环
Page 38
loop关键字可以实现一个无限循环.让我们来加入一个循环:
extern crate rand;
use std::io;
use std::cmp::Ordering;
use rand::Rng;
fn main() {
println!("Guess the number!");
let secret_number = rand::thread_rng().gen_range(1, 101);
println!("The secret number is: {}", secret_number);
loop {
println!("Please input your guess.");
let mut guess = String::new();
io::stdin().read_line(&mut guess)
.ok()
.expect("failed to read line");
let guess: u32 = guess.trim().parse()
.ok()
.expect("Please type a number!");
println!("You guessed: {}", guess);
match guess.cmp(&secret_number) {
Ordering::Less => println!("Too small!"),
Ordering::Greater => println!("Too big!"),
Ordering::Equal => println!("You win!"),
}
}
}
试一下.但是请稍等一下,我们刚才不是加了一个无限循环了么?是的.还记得我们之前讨论过parse()么?如果我们传入了一个非数字,我们会退出循环.看一下:
Page 39
哈哈!quit确实退出了.就像其他非数字的输入一样.这是我们次最优的方法.
现在让我们来真正退出游戏:
extern crate rand;
use std::io;
use std::cmp::Ordering;
use rand::Rng;
fn main() {
println!("Guess the number!");
let secret_number = rand::thread_rng().gen_range(1, 101);
println!("The secret number is: {}", secret_number);
loop {
println!("Please input your guess.");
let mut guess = String::new();
io::stdin().read_line(&mut guess)
.ok()
.expect("failed to read line");
let guess: u32 = guess.trim().parse()
.ok()
.expect("Please type a number!");
println!("You guessed: {}", guess);
match guess.cmp(&secret_number) {
Ordering::Less => println!("Too small!"),
Ordering::Greater => println!("Too big!"),
Ordering::Equal => {
println!("You win!");
break;
}
}
}
}
Page 40
在You win这一行结束的时候添加一个break,我们可以在赢得游戏的时候退出.退出循环也就意味着退出程序,因为那是我们main()函数的最后一行.我们还剩下最后一件事情纠结:当某人输入了非数字的时候,我们不想退出,而是想要忽略它.我们可以这样做:
extern crate rand;
use std::io;
use std::cmp::Ordering;
use rand::Rng;
fn main() {
println!("Guess the number!");
let secret_number = rand::thread_rng().gen_range(1, 101);
println!("The secret number is: {}", secret_number);
loop {
println!("Please input your guess.");
let mut guess = String::new();
io::stdin().read_line(&mut guess)
.ok()
.expect("failed to read line");
let guess: u32 = match guess.trim().parse() {
Ok(num) => num,
Err(_) => continue,
};
println!("You guessed: {}", guess);
match guess.cmp(&secret_number) {
Ordering::Less => println!("Too small!"),
Ordering::Greater => println!("Too big!"),
Ordering::Equal => {
println!("You win!");
break;
}
}
}
}
Page 41
修改的行是这里:
let guess: u32 = match guess.trim().parse() {
Ok(num) => num,
Err(_) => continue,
};
通过把ok().expect()语句转为match陈述式,我们可以实现将"错误时崩溃"转换成"错误时处理",这是我们的通用性做法.parse()方法的返回值是一个枚举类型,就像Ordering一样,但是在这里,每一个结果都有一些和他关联的数据:Ok是成功,Ree是失败.两者都有更多的信息:也就是一个成功整型转换,或者一个错误的类型.在此例中,当我们命中了Ok(num)分支,它会把Ok的值赋值给num变量,然后我们会在操作符右侧返回这个值.在Err分支里,我们不关心错误是什么,我们就只用了一个_来代替错误的名字.这将忽略这个错误,然后continue会让我们开始loop的下一次迭代.
现在,我们应该可以成功运行了!让我们试试吧:
Page 42
漂亮!还有最后一个小问题,我们就完成了猜数字游戏.你可以想想是什么问题么?对了,就是我们不要打印出那个秘密数字.它在测试时很好用,但是会毁了游戏.这里是最终版本:
extern crate rand;
use std::io;
use std::cmp::Ordering;
use rand::Rng;
fn main() {
println!("Guess the number!");
let secret_number = rand::thread_rng().gen_range(1, 101);
loop {
println!("Please input your guess.");
let mut guess = String::new();
io::stdin().read_line(&mut guess)
.ok()
.expect("failed to read line");
let guess: u32 = match guess.trim().parse() {
Ok(num) => num,
Err(_) => continue,
};
println!("You guessed: {}", guess);
match guess.cmp(&secret_number) {
Ordering::Less => println!("Too small!"),
Ordering::Greater => println!("Too big!"),
Ordering::Equal => {
println!("You win!");
break;
}
}
}
}
Page 43
3.1.6 完成了!
终于,在这里我们成功完成了猜数字游戏!恭喜你!
我们的第一个工程像你展示了很多:let,match,方法,关联方法,使用外部crates等等.我们的下一个工程会展示更多东西.