3 For our first project, we’ll implement a classic beginner programming problem:
4 the guessing game. Here’s how it works: Our program will generate a random
5 integer between one and a hundred. It will then prompt us to enter a guess.
6 Upon entering our guess, it will tell us if we’re too low or too high. Once we
7 guess correctly, it will congratulate us. Sounds good?
11 Let’s set up a new project. Go to your projects directory. Remember how we had
12 to create our directory structure and a `Cargo.toml` for `hello_world`? Cargo
13 has a command that does that for us. Let’s give it a shot:
17 $ cargo new guessing_game --bin
21 We pass the name of our project to `cargo new`, and then the `--bin` flag,
22 since we’re making a binary, rather than a library.
24 Check out the generated `Cargo.toml`:
29 name = "guessing_game"
31 authors = ["Your Name <you@example.com>"]
34 Cargo gets this information from your environment. If it’s not correct, go ahead
37 Finally, Cargo generated a ‘Hello, world!’ for us. Check out `src/main.rs`:
41 println!("Hello, world!")
45 Let’s try compiling what Cargo gave us:
49 Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game)
52 Excellent! Open up your `src/main.rs` again. We’ll be writing all of
53 our code in this file.
55 Before we move on, let me show you one more Cargo command: `run`. `cargo run`
56 is kind of like `cargo build`, but it also then runs the produced executable.
61 Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game)
62 Running `target/debug/guessing_game`
66 Great! The `run` command comes in handy when you need to rapidly iterate on a
67 project. Our game is just such a project, we need to quickly test each
68 iteration before moving on to the next one.
72 Let’s get to it! The first thing we need to do for our guessing game is
73 allow our player to input a guess. Put this in your `src/main.rs`:
79 println!("Guess the number!");
81 println!("Please input your guess.");
83 let mut guess = String::new();
85 io::stdin().read_line(&mut guess)
87 .expect("Failed to read line");
89 println!("You guessed: {}", guess);
93 There’s a lot here! Let’s go over it, bit by bit.
99 We’ll need to take user input, and then print the result as output. As such, we
100 need the `io` library from the standard library. Rust only imports a few things
101 into every program, [the ‘prelude’][prelude]. If it’s not in the prelude,
102 you’ll have to `use` it directly.
104 [prelude]: ../std/prelude/index.html
110 As you’ve seen before, the `main()` function is the entry point into your
111 program. The `fn` syntax declares a new function, the `()`s indicate that
112 there are no arguments, and `{` starts the body of the function. Because
113 we didn’t include a return type, it’s assumed to be `()`, an empty
116 [tuples]: primitive-types.html#tuples
119 println!("Guess the number!");
121 println!("Please input your guess.");
124 We previously learned that `println!()` is a [macro][macros] that
125 prints a [string][strings] to the screen.
127 [macros]: macros.html
128 [strings]: strings.html
131 let mut guess = String::new();
134 Now we’re getting interesting! There’s a lot going on in this little line.
135 The first thing to notice is that this is a [let statement][let], which is
136 used to create ‘variable bindings’. They take this form:
142 [let]: variable-bindings.html
144 This will create a new binding named `foo`, and bind it to the value `bar`. In
145 many languages, this is called a ‘variable’, but Rust’s variable bindings have
146 a few tricks up their sleeves.
148 For example, they’re [immutable][immutable] by default. That’s why our example
149 uses `mut`: it makes a binding mutable, rather than immutable. `let` doesn’t
150 take a name on the left hand side, it actually accepts a
151 ‘[pattern][patterns]’. We’ll use patterns more later. It’s easy enough
155 let foo = 5; // immutable.
156 let mut bar = 5; // mutable
159 [immutable]: mutability.html
160 [patterns]: patterns.html
162 Oh, and `//` will start a comment, until the end of the line. Rust ignores
163 everything in [comments][comments].
165 [comments]: comments.html
167 So now we know that `let mut guess` will introduce a mutable binding named
168 `guess`, but we have to look at the other side of the `=` for what it’s
169 bound to: `String::new()`.
171 `String` is a string type, provided by the standard library. A
172 [`String`][string] is a growable, UTF-8 encoded bit of text.
174 [string]: ../std/string/struct.String.html
176 The `::new()` syntax uses `::` because this is an ‘associated function’ of
177 a particular type. That is to say, it’s associated with `String` itself,
178 rather than a particular instance of a `String`. Some languages call this a
181 This function is named `new()`, because it creates a new, empty `String`.
182 You’ll find a `new()` function on many types, as it’s a common name for making
183 a new value of some kind.
188 io::stdin().read_line(&mut guess)
190 .expect("Failed to read line");
193 That’s a lot more! Let’s go bit-by-bit. The first line has two parts. Here’s
200 Remember how we `use`d `std::io` on the first line of the program? We’re now
201 calling an associated function on it. If we didn’t `use std::io`, we could
202 have written this line as `std::io::stdin()`.
204 This particular function returns a handle to the standard input for your
205 terminal. More specifically, a [std::io::Stdin][iostdin].
207 [iostdin]: ../std/io/struct.Stdin.html
209 The next part will use this handle to get input from the user:
212 .read_line(&mut guess)
215 Here, we call the [`read_line()`][read_line] method on our handle.
216 [Methods][method] are like associated functions, but are only available on a
217 particular instance of a type, rather than the type itself. We’re also passing
218 one argument to `read_line()`: `&mut guess`.
220 [read_line]: ../std/io/struct.Stdin.html#method.read_line
221 [method]: method-syntax.html
223 Remember how we bound `guess` above? We said it was mutable. However,
224 `read_line` doesn’t take a `String` as an argument: it takes a `&mut String`.
225 Rust has a feature called ‘[references][references]’, which allows you to have
226 multiple references to one piece of data, which can reduce copying. References
227 are a complex feature, as one of Rust’s major selling points is how safe and
228 easy it is to use references. We don’t need to know a lot of those details to
229 finish our program right now, though. For now, all we need to know is that
230 like `let` bindings, references are immutable by default. Hence, we need to
231 write `&mut guess`, rather than `&guess`.
233 Why does `read_line()` take a mutable reference to a string? Its job is
234 to take what the user types into standard input, and place that into a
235 string. So it takes that string as an argument, and in order to add
236 the input, it needs to be mutable.
238 [references]: references-and-borrowing.html
240 But we’re not quite done with this line of code, though. While it’s
241 a single line of text, it’s only the first part of the single logical line of
246 .expect("Failed to read line");
249 When you call a method with the `.foo()` syntax, you may introduce a newline
250 and other whitespace. This helps you split up long lines. We _could_ have
254 io::stdin().read_line(&mut guess).ok().expect("failed to read line");
257 But that gets hard to read. So we’ve split it up, three lines for three
258 method calls. We already talked about `read_line()`, but what about `ok()`
259 and `expect()`? Well, we already mentioned that `read_line()` puts what
260 the user types into the `&mut String` we pass it. But it also returns
261 a value: in this case, an [`io::Result`][ioresult]. Rust has a number of
262 types named `Result` in its standard library: a generic [`Result`][result],
263 and then specific versions for sub-libraries, like `io::Result`.
265 [ioresult]: ../std/io/type.Result.html
266 [result]: ../std/result/enum.Result.html
268 The purpose of these `Result` types is to encode error handling information.
269 Values of the `Result` type, like any type, have methods defined on them. In
270 this case, `io::Result` has an `ok()` method, which says ‘we want to assume
271 this value is a successful one. If not, just throw away the error
272 information’. Why throw it away? Well, for a basic program, we just want to
273 print a generic error, as basically any issue means we can’t continue. The
274 [`ok()` method][ok] returns a value which has another method defined on it:
275 `expect()`. The [`expect()` method][expect] takes a value it’s called on, and
276 if it isn’t a successful one, [`panic!`][panic]s with a message you
277 passed it. A `panic!` like this will cause our program to crash, displaying
280 [ok]: ../std/result/enum.Result.html#method.ok
281 [expect]: ../std/option/enum.Option.html#method.expect
282 [panic]: error-handling.html
284 If we leave off calling these two methods, our program will compile, but
289 Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game)
290 src/main.rs:10:5: 10:39 warning: unused result which must be used,
291 #[warn(unused_must_use)] on by default
292 src/main.rs:10 io::stdin().read_line(&mut guess);
293 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
296 Rust warns us that we haven’t used the `Result` value. This warning comes from
297 a special annotation that `io::Result` has. Rust is trying to tell you that
298 you haven’t handled a possible error. The right way to suppress the error is
299 to actually write error handling. Luckily, if we just want to crash if there’s
300 a problem, we can use these two little methods. If we can recover from the
301 error somehow, we’d do something else, but we’ll save that for a future
304 There’s just one line of this first example left:
307 println!("You guessed: {}", guess);
311 This prints out the string we saved our input in. The `{}`s are a placeholder,
312 and so we pass it `guess` as an argument. If we had multiple `{}`s, we would
313 pass multiple arguments:
319 println!("x and y: {} and {}", x, y);
324 Anyway, that’s the tour. We can run what we have with `cargo run`:
328 Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game)
329 Running `target/debug/guessing_game`
331 Please input your guess.
336 All right! Our first part is done: we can get input from the keyboard,
337 and then print it back out.
339 # Generating a secret number
341 Next, we need to generate a secret number. Rust does not yet include random
342 number functionality in its standard library. The Rust team does, however,
343 provide a [`rand` crate][randcrate]. A ‘crate’ is a package of Rust code.
344 We’ve been building a ‘binary crate’, which is an executable. `rand` is a
345 ‘library crate’, which contains code that’s intended to be used with other
348 [randcrate]: https://crates.io/crates/rand
350 Using external crates is where Cargo really shines. Before we can write
351 the code using `rand`, we need to modify our `Cargo.toml`. Open it up, and
352 add these few lines at the bottom:
360 The `[dependencies]` section of `Cargo.toml` is like the `[package]` section:
361 everything that follows it is part of it, until the next section starts.
362 Cargo uses the dependencies section to know what dependencies on external
363 crates you have, and what versions you require. In this case, we’ve used version `0.3.0`.
364 Cargo understands [Semantic Versioning][semver], which is a standard for writing version
365 numbers. If we wanted to use the latest version we could use `*` or we could use a range
366 of versions. [Cargo’s documentation][cargodoc] contains more details.
368 [semver]: http://semver.org
369 [cargodoc]: http://doc.crates.io/crates-io.html
371 Now, without changing any of our code, let’s build our project:
375 Updating registry `https://github.com/rust-lang/crates.io-index`
376 Downloading rand v0.3.8
377 Downloading libc v0.1.6
378 Compiling libc v0.1.6
379 Compiling rand v0.3.8
380 Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game)
383 (You may see different versions, of course.)
385 Lots of new output! Now that we have an external dependency, Cargo fetches the
386 latest versions of everything from the registry, which is a copy of data from
387 [Crates.io][cratesio]. Crates.io is where people in the Rust ecosystem
388 post their open source Rust projects for others to use.
390 [cratesio]: https://crates.io
392 After updating the registry, Cargo checks our `[dependencies]` and downloads
393 any we don’t have yet. In this case, while we only said we wanted to depend on
394 `rand`, we’ve also grabbed a copy of `libc`. This is because `rand` depends on
395 `libc` to work. After downloading them, it compiles them, and then compiles
398 If we run `cargo build` again, we’ll get different output:
404 That’s right, no output! Cargo knows that our project has been built, and that
405 all of its dependencies are built, and so there’s no reason to do all that
406 stuff. With nothing to do, it simply exits. If we open up `src/main.rs` again,
407 make a trivial change, and then save it again, we’ll just see one line:
411 Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game)
414 So, we told Cargo we wanted any `0.3.x` version of `rand`, and so it fetched the latest
415 version at the time this was written, `v0.3.8`. But what happens when next
416 week, version `v0.3.9` comes out, with an important bugfix? While getting
417 bugfixes is important, what if `0.3.9` contains a regression that breaks our
420 The answer to this problem is the `Cargo.lock` file you’ll now find in your
421 project directory. When you build your project for the first time, Cargo
422 figures out all of the versions that fit your criteria, and then writes them
423 to the `Cargo.lock` file. When you build your project in the future, Cargo
424 will see that the `Cargo.lock` file exists, and then use that specific version
425 rather than do all the work of figuring out versions again. This lets you
426 have a repeatable build automatically. In other words, we’ll stay at `0.3.8`
427 until we explicitly upgrade, and so will anyone who we share our code with,
428 thanks to the lock file.
430 What about when we _do_ want to use `v0.3.9`? Cargo has another command,
431 `update`, which says ‘ignore the lock, figure out all the latest versions that
432 fit what we’ve specified. If that works, write those versions out to the lock
433 file’. But, by default, Cargo will only look for versions larger than `0.3.0`
434 and smaller than `0.4.0`. If we want to move to `0.4.x`, we’d have to update
435 the `Cargo.toml` directly. When we do, the next time we `cargo build`, Cargo
436 will update the index and re-evaluate our `rand` requirements.
438 There’s a lot more to say about [Cargo][doccargo] and [its
439 ecosystem][doccratesio], but for now, that’s all we need to know. Cargo makes
440 it really easy to re-use libraries, and so Rustaceans tend to write smaller
441 projects which are assembled out of a number of sub-packages.
443 [doccargo]: http://doc.crates.io
444 [doccratesio]: http://doc.crates.io/crates-io.html
446 Let’s get on to actually _using_ `rand`. Here’s our next step:
455 println!("Guess the number!");
457 let secret_number = rand::thread_rng().gen_range(1, 101);
459 println!("The secret number is: {}", secret_number);
461 println!("Please input your guess.");
463 let mut guess = String::new();
465 io::stdin().read_line(&mut guess)
467 .expect("failed to read line");
469 println!("You guessed: {}", guess);
473 The first thing we’ve done is change the first line. It now says
474 `extern crate rand`. Because we declared `rand` in our `[dependencies]`, we
475 can use `extern crate` to let Rust know we’ll be making use of it. This also
476 does the equivalent of a `use rand;` as well, so we can make use of anything
477 in the `rand` crate by prefixing it with `rand::`.
479 Next, we added another `use` line: `use rand::Rng`. We’re going to use a
480 method in a moment, and it requires that `Rng` be in scope to work. The basic
481 idea is this: methods are defined on something called ‘traits’, and for the
482 method to work, it needs the trait to be in scope. For more about the
483 details, read the [traits][traits] section.
485 [traits]: traits.html
487 There are two other lines we added, in the middle:
490 let secret_number = rand::thread_rng().gen_range(1, 101);
492 println!("The secret number is: {}", secret_number);
495 We use the `rand::thread_rng()` function to get a copy of the random number
496 generator, which is local to the particular [thread][concurrency] of execution
497 we’re in. Because we `use rand::Rng`’d above, it has a `gen_range()` method
498 available. This method takes two arguments, and generates a number between
499 them. It’s inclusive on the lower bound, but exclusive on the upper bound,
500 so we need `1` and `101` to get a number between one and a hundred.
502 [concurrency]: concurrency.html
504 The second line just prints out the secret number. This is useful while
505 we’re developing our program, so we can easily test it out. But we’ll be
506 deleting it for the final version. It’s not much of a game if it prints out
507 the answer when you start it up!
509 Try running our new program a few times:
513 Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game)
514 Running `target/debug/guessing_game`
516 The secret number is: 7
517 Please input your guess.
521 Running `target/debug/guessing_game`
523 The secret number is: 83
524 Please input your guess.
529 Great! Next up: let’s compare our guess to the secret guess.
533 Now that we’ve got user input, let’s compare our guess to the random guess.
534 Here’s our next step, though it doesn’t quite work yet:
540 use std::cmp::Ordering;
544 println!("Guess the number!");
546 let secret_number = rand::thread_rng().gen_range(1, 101);
548 println!("The secret number is: {}", secret_number);
550 println!("Please input your guess.");
552 let mut guess = String::new();
554 io::stdin().read_line(&mut guess)
556 .expect("failed to read line");
558 println!("You guessed: {}", guess);
560 match guess.cmp(&secret_number) {
561 Ordering::Less => println!("Too small!"),
562 Ordering::Greater => println!("Too big!"),
563 Ordering::Equal => println!("You win!"),
568 A few new bits here. The first is another `use`. We bring a type called
569 `std::cmp::Ordering` into scope. Then, five new lines at the bottom that use
573 match guess.cmp(&secret_number) {
574 Ordering::Less => println!("Too small!"),
575 Ordering::Greater => println!("Too big!"),
576 Ordering::Equal => println!("You win!"),
580 The `cmp()` method can be called on anything that can be compared, and it
581 takes a reference to the thing you want to compare it to. It returns the
582 `Ordering` type we `use`d earlier. We use a [`match`][match] statement to
583 determine exactly what kind of `Ordering` it is. `Ordering` is an
584 [`enum`][enum], short for ‘enumeration’, which looks like this:
596 With this definition, anything of type `Foo` can be either a
597 `Foo::Bar` or a `Foo::Baz`. We use the `::` to indicate the
598 namespace for a particular `enum` variant.
600 The [`Ordering`][ordering] enum has three possible variants: `Less`, `Equal`,
601 and `Greater`. The `match` statement takes a value of a type, and lets you
602 create an ‘arm’ for each possible value. Since we have three types of
603 `Ordering`, we have three arms:
606 match guess.cmp(&secret_number) {
607 Ordering::Less => println!("Too small!"),
608 Ordering::Greater => println!("Too big!"),
609 Ordering::Equal => println!("You win!"),
613 [ordering]: ../std/cmp/enum.Ordering.html
615 If it’s `Less`, we print `Too small!`, if it’s `Greater`, `Too big!`, and if
616 `Equal`, `You win!`. `match` is really useful, and is used often in Rust.
618 I did mention that this won’t quite work yet, though. Let’s try it:
622 Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game)
623 src/main.rs:28:21: 28:35 error: mismatched types:
624 expected `&collections::string::String`,
626 (expected struct `collections::string::String`,
627 found integral variable) [E0308]
628 src/main.rs:28 match guess.cmp(&secret_number) {
630 error: aborting due to previous error
631 Could not compile `guessing_game`.
634 Whew! This is a big error. The core of it is that we have ‘mismatched types’.
635 Rust has a strong, static type system. However, it also has type inference.
636 When we wrote `let guess = String::new()`, Rust was able to infer that `guess`
637 should be a `String`, and so it doesn’t make us write out the type. And with
638 our `secret_number`, there are a number of types which can have a value
639 between one and a hundred: `i32`, a thirty-two-bit number, or `u32`, an
640 unsigned thirty-two-bit number, or `i64`, a sixty-four-bit number. Or others.
641 So far, that hasn’t mattered, and so Rust defaults to an `i32`. However, here,
642 Rust doesn’t know how to compare the `guess` and the `secret_number`. They
643 need to be the same type. Ultimately, we want to convert the `String` we
644 read as input into a real number type, for comparison. We can do that
645 with three more lines. Here’s our new program:
651 use std::cmp::Ordering;
655 println!("Guess the number!");
657 let secret_number = rand::thread_rng().gen_range(1, 101);
659 println!("The secret number is: {}", secret_number);
661 println!("Please input your guess.");
663 let mut guess = String::new();
665 io::stdin().read_line(&mut guess)
667 .expect("failed to read line");
669 let guess: u32 = guess.trim().parse()
671 .expect("Please type a number!");
673 println!("You guessed: {}", guess);
675 match guess.cmp(&secret_number) {
676 Ordering::Less => println!("Too small!"),
677 Ordering::Greater => println!("Too big!"),
678 Ordering::Equal => println!("You win!"),
686 let guess: u32 = guess.trim().parse()
688 .expect("Please type a number!");
691 Wait a minute, I thought we already had a `guess`? We do, but Rust allows us
692 to ‘shadow’ the previous `guess` with a new one. This is often used in this
693 exact situation, where `guess` starts as a `String`, but we want to convert it
694 to an `u32`. Shadowing lets us re-use the `guess` name, rather than forcing us
695 to come up with two unique names like `guess_str` and `guess`, or something
698 We bind `guess` to an expression that looks like something we wrote earlier:
704 Followed by an `ok().expect()` invocation. Here, `guess` refers to the old
705 `guess`, the one that was a `String` with our input in it. The `trim()`
706 method on `String`s will eliminate any white space at the beginning and end of
707 our string. This is important, as we had to press the ‘return’ key to satisfy
708 `read_line()`. This means that if we type `5` and hit return, `guess` looks
709 like this: `5\n`. The `\n` represents ‘newline’, the enter key. `trim()` gets
710 rid of this, leaving our string with just the `5`. The [`parse()` method on
711 strings][parse] parses a string into some kind of number. Since it can parse a
712 variety of numbers, we need to give Rust a hint as to the exact type of number
713 we want. Hence, `let guess: u32`. The colon (`:`) after `guess` tells Rust
714 we’re going to annotate its type. `u32` is an unsigned, thirty-two bit
715 integer. Rust has [a number of built-in number types][number], but we’ve
716 chosen `u32`. It’s a good default choice for a small positive number.
718 [parse]: ../std/primitive.str.html#method.parse
719 [number]: primitive-types.html#numeric-types
721 Just like `read_line()`, our call to `parse()` could cause an error. What if
722 our string contained `A👍%`? There’d be no way to convert that to a number. As
723 such, we’ll do the same thing we did with `read_line()`: use the `ok()` and
724 `expect()` methods to crash if there’s an error.
726 Let’s try our program out!
730 Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game)
731 Running `target/guessing_game`
733 The secret number is: 58
734 Please input your guess.
740 Nice! You can see I even added spaces before my guess, and it still figured
741 out that I guessed 76. Run the program a few times, and verify that guessing
742 the number works, as well as guessing a number too small.
744 Now we’ve got most of the game working, but we can only make one guess. Let’s
745 change that by adding loops!
749 The `loop` keyword gives us an infinite loop. Let’s add that in:
755 use std::cmp::Ordering;
759 println!("Guess the number!");
761 let secret_number = rand::thread_rng().gen_range(1, 101);
763 println!("The secret number is: {}", secret_number);
766 println!("Please input your guess.");
768 let mut guess = String::new();
770 io::stdin().read_line(&mut guess)
772 .expect("failed to read line");
774 let guess: u32 = guess.trim().parse()
776 .expect("Please type a number!");
778 println!("You guessed: {}", guess);
780 match guess.cmp(&secret_number) {
781 Ordering::Less => println!("Too small!"),
782 Ordering::Greater => println!("Too big!"),
783 Ordering::Equal => println!("You win!"),
789 And try it out. But wait, didn’t we just add an infinite loop? Yup. Remember
790 our discussion about `parse()`? If we give a non-number answer, we’ll `return`
795 Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game)
796 Running `target/guessing_game`
798 The secret number is: 59
799 Please input your guess.
803 Please input your guess.
807 Please input your guess.
811 Please input your guess.
813 thread '<main>' panicked at 'Please type a number!'
816 Ha! `quit` actually quits. As does any other non-number input. Well, this is
817 suboptimal to say the least. First, let’s actually quit when you win the game:
823 use std::cmp::Ordering;
827 println!("Guess the number!");
829 let secret_number = rand::thread_rng().gen_range(1, 101);
831 println!("The secret number is: {}", secret_number);
834 println!("Please input your guess.");
836 let mut guess = String::new();
838 io::stdin().read_line(&mut guess)
840 .expect("failed to read line");
842 let guess: u32 = guess.trim().parse()
844 .expect("Please type a number!");
846 println!("You guessed: {}", guess);
848 match guess.cmp(&secret_number) {
849 Ordering::Less => println!("Too small!"),
850 Ordering::Greater => println!("Too big!"),
852 println!("You win!");
860 By adding the `break` line after the `You win!`, we’ll exit the loop when we
861 win. Exiting the loop also means exiting the program, since it’s the last
862 thing in `main()`. We have just one more tweak to make: when someone inputs a
863 non-number, we don’t want to quit, we just want to ignore it. We can do that
870 use std::cmp::Ordering;
874 println!("Guess the number!");
876 let secret_number = rand::thread_rng().gen_range(1, 101);
878 println!("The secret number is: {}", secret_number);
881 println!("Please input your guess.");
883 let mut guess = String::new();
885 io::stdin().read_line(&mut guess)
887 .expect("failed to read line");
889 let guess: u32 = match guess.trim().parse() {
894 println!("You guessed: {}", guess);
896 match guess.cmp(&secret_number) {
897 Ordering::Less => println!("Too small!"),
898 Ordering::Greater => println!("Too big!"),
900 println!("You win!");
908 These are the lines that changed:
911 let guess: u32 = match guess.trim().parse() {
917 This is how you generally move from ‘crash on error’ to ‘actually handle the
918 error’, by switching from `ok().expect()` to a `match` statement. The `Result`
919 returned by `parse()` is an enum just like `Ordering`, but in this case, each
920 variant has some data associated with it: `Ok` is a success, and `Err` is a
921 failure. Each contains more information: the successful parsed integer, or an
922 error type. In this case, we `match` on `Ok(num)`, which sets the inner value
923 of the `Ok` to the name `num`, and then we just return it on the right-hand
924 side. In the `Err` case, we don’t care what kind of error it is, so we just
925 use `_` instead of a name. This ignores the error, and `continue` causes us
926 to go to the next iteration of the `loop`.
928 Now we should be good! Let’s try:
932 Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game)
933 Running `target/guessing_game`
935 The secret number is: 61
936 Please input your guess.
940 Please input your guess.
944 Please input your guess.
946 Please input your guess.
952 Awesome! With one tiny last tweak, we have finished the guessing game. Can you
953 think of what it is? That’s right, we don’t want to print out the secret
954 number. It was good for testing, but it kind of ruins the game. Here’s our
961 use std::cmp::Ordering;
965 println!("Guess the number!");
967 let secret_number = rand::thread_rng().gen_range(1, 101);
970 println!("Please input your guess.");
972 let mut guess = String::new();
974 io::stdin().read_line(&mut guess)
976 .expect("failed to read line");
978 let guess: u32 = match guess.trim().parse() {
983 println!("You guessed: {}", guess);
985 match guess.cmp(&secret_number) {
986 Ordering::Less => println!("Too small!"),
987 Ordering::Greater => println!("Too big!"),
989 println!("You win!");
999 At this point, you have successfully built the Guessing Game! Congratulations!
1001 This first project showed you a lot: `let`, `match`, methods, associated
1002 functions, using external crates, and more. Our next project will show off