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 by default into every program, [the ‘prelude’][prelude]. If it’s not in the
102 prelude, 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 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 specified version `0.3.0`,
364 which Cargo understands to be any release that’s compatible with this specific version.
365 Cargo understands [Semantic Versioning][semver], which is a standard for writing version
366 numbers. If we wanted to use only `0.3.0` exactly, we could use `=0.3.0`. If we
367 wanted to use the latest version we could use `*`; We could use a range of
368 versions. [Cargo’s documentation][cargodoc] contains more details.
370 [semver]: http://semver.org
371 [cargodoc]: http://doc.crates.io/crates-io.html
373 Now, without changing any of our code, let’s build our project:
377 Updating registry `https://github.com/rust-lang/crates.io-index`
378 Downloading rand v0.3.8
379 Downloading libc v0.1.6
380 Compiling libc v0.1.6
381 Compiling rand v0.3.8
382 Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game)
385 (You may see different versions, of course.)
387 Lots of new output! Now that we have an external dependency, Cargo fetches the
388 latest versions of everything from the registry, which is a copy of data from
389 [Crates.io][cratesio]. Crates.io is where people in the Rust ecosystem
390 post their open source Rust projects for others to use.
392 [cratesio]: https://crates.io
394 After updating the registry, Cargo checks our `[dependencies]` and downloads
395 any we don’t have yet. In this case, while we only said we wanted to depend on
396 `rand`, we’ve also grabbed a copy of `libc`. This is because `rand` depends on
397 `libc` to work. After downloading them, it compiles them, and then compiles
400 If we run `cargo build` again, we’ll get different output:
406 That’s right, no output! Cargo knows that our project has been built, and that
407 all of its dependencies are built, and so there’s no reason to do all that
408 stuff. With nothing to do, it simply exits. If we open up `src/main.rs` again,
409 make a trivial change, and then save it again, we’ll just see one line:
413 Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game)
416 So, we told Cargo we wanted any `0.3.x` version of `rand`, and so it fetched the latest
417 version at the time this was written, `v0.3.8`. But what happens when next
418 week, version `v0.3.9` comes out, with an important bugfix? While getting
419 bugfixes is important, what if `0.3.9` contains a regression that breaks our
422 The answer to this problem is the `Cargo.lock` file you’ll now find in your
423 project directory. When you build your project for the first time, Cargo
424 figures out all of the versions that fit your criteria, and then writes them
425 to the `Cargo.lock` file. When you build your project in the future, Cargo
426 will see that the `Cargo.lock` file exists, and then use that specific version
427 rather than do all the work of figuring out versions again. This lets you
428 have a repeatable build automatically. In other words, we’ll stay at `0.3.8`
429 until we explicitly upgrade, and so will anyone who we share our code with,
430 thanks to the lock file.
432 What about when we _do_ want to use `v0.3.9`? Cargo has another command,
433 `update`, which says ‘ignore the lock, figure out all the latest versions that
434 fit what we’ve specified. If that works, write those versions out to the lock
435 file’. But, by default, Cargo will only look for versions larger than `0.3.0`
436 and smaller than `0.4.0`. If we want to move to `0.4.x`, we’d have to update
437 the `Cargo.toml` directly. When we do, the next time we `cargo build`, Cargo
438 will update the index and re-evaluate our `rand` requirements.
440 There’s a lot more to say about [Cargo][doccargo] and [its
441 ecosystem][doccratesio], but for now, that’s all we need to know. Cargo makes
442 it really easy to re-use libraries, and so Rustaceans tend to write smaller
443 projects which are assembled out of a number of sub-packages.
445 [doccargo]: http://doc.crates.io
446 [doccratesio]: http://doc.crates.io/crates-io.html
448 Let’s get on to actually _using_ `rand`. Here’s our next step:
457 println!("Guess the number!");
459 let secret_number = rand::thread_rng().gen_range(1, 101);
461 println!("The secret number is: {}", secret_number);
463 println!("Please input your guess.");
465 let mut guess = String::new();
467 io::stdin().read_line(&mut guess)
469 .expect("failed to read line");
471 println!("You guessed: {}", guess);
475 The first thing we’ve done is change the first line. It now says
476 `extern crate rand`. Because we declared `rand` in our `[dependencies]`, we
477 can use `extern crate` to let Rust know we’ll be making use of it. This also
478 does the equivalent of a `use rand;` as well, so we can make use of anything
479 in the `rand` crate by prefixing it with `rand::`.
481 Next, we added another `use` line: `use rand::Rng`. We’re going to use a
482 method in a moment, and it requires that `Rng` be in scope to work. The basic
483 idea is this: methods are defined on something called ‘traits’, and for the
484 method to work, it needs the trait to be in scope. For more about the
485 details, read the [traits][traits] section.
487 [traits]: traits.html
489 There are two other lines we added, in the middle:
492 let secret_number = rand::thread_rng().gen_range(1, 101);
494 println!("The secret number is: {}", secret_number);
497 We use the `rand::thread_rng()` function to get a copy of the random number
498 generator, which is local to the particular [thread][concurrency] of execution
499 we’re in. Because we `use rand::Rng`’d above, it has a `gen_range()` method
500 available. This method takes two arguments, and generates a number between
501 them. It’s inclusive on the lower bound, but exclusive on the upper bound,
502 so we need `1` and `101` to get a number ranging from one to a hundred.
504 [concurrency]: concurrency.html
506 The second line just prints out the secret number. This is useful while
507 we’re developing our program, so we can easily test it out. But we’ll be
508 deleting it for the final version. It’s not much of a game if it prints out
509 the answer when you start it up!
511 Try running our new program a few times:
515 Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game)
516 Running `target/debug/guessing_game`
518 The secret number is: 7
519 Please input your guess.
523 Running `target/debug/guessing_game`
525 The secret number is: 83
526 Please input your guess.
531 Great! Next up: let’s compare our guess to the secret guess.
535 Now that we’ve got user input, let’s compare our guess to the random guess.
536 Here’s our next step, though it doesn’t quite work yet:
542 use std::cmp::Ordering;
546 println!("Guess the number!");
548 let secret_number = rand::thread_rng().gen_range(1, 101);
550 println!("The secret number is: {}", secret_number);
552 println!("Please input your guess.");
554 let mut guess = String::new();
556 io::stdin().read_line(&mut guess)
558 .expect("failed to read line");
560 println!("You guessed: {}", guess);
562 match guess.cmp(&secret_number) {
563 Ordering::Less => println!("Too small!"),
564 Ordering::Greater => println!("Too big!"),
565 Ordering::Equal => println!("You win!"),
570 A few new bits here. The first is another `use`. We bring a type called
571 `std::cmp::Ordering` into scope. Then, five new lines at the bottom that use
575 match guess.cmp(&secret_number) {
576 Ordering::Less => println!("Too small!"),
577 Ordering::Greater => println!("Too big!"),
578 Ordering::Equal => println!("You win!"),
582 The `cmp()` method can be called on anything that can be compared, and it
583 takes a reference to the thing you want to compare it to. It returns the
584 `Ordering` type we `use`d earlier. We use a [`match`][match] statement to
585 determine exactly what kind of `Ordering` it is. `Ordering` is an
586 [`enum`][enum], short for ‘enumeration’, which looks like this:
598 With this definition, anything of type `Foo` can be either a
599 `Foo::Bar` or a `Foo::Baz`. We use the `::` to indicate the
600 namespace for a particular `enum` variant.
602 The [`Ordering`][ordering] enum has three possible variants: `Less`, `Equal`,
603 and `Greater`. The `match` statement takes a value of a type, and lets you
604 create an ‘arm’ for each possible value. Since we have three types of
605 `Ordering`, we have three arms:
608 match guess.cmp(&secret_number) {
609 Ordering::Less => println!("Too small!"),
610 Ordering::Greater => println!("Too big!"),
611 Ordering::Equal => println!("You win!"),
615 [ordering]: ../std/cmp/enum.Ordering.html
617 If it’s `Less`, we print `Too small!`, if it’s `Greater`, `Too big!`, and if
618 `Equal`, `You win!`. `match` is really useful, and is used often in Rust.
620 I did mention that this won’t quite work yet, though. Let’s try it:
624 Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game)
625 src/main.rs:28:21: 28:35 error: mismatched types:
626 expected `&collections::string::String`,
628 (expected struct `collections::string::String`,
629 found integral variable) [E0308]
630 src/main.rs:28 match guess.cmp(&secret_number) {
632 error: aborting due to previous error
633 Could not compile `guessing_game`.
636 Whew! This is a big error. The core of it is that we have ‘mismatched types’.
637 Rust has a strong, static type system. However, it also has type inference.
638 When we wrote `let guess = String::new()`, Rust was able to infer that `guess`
639 should be a `String`, and so it doesn’t make us write out the type. And with
640 our `secret_number`, there are a number of types which can have a value
641 between one and a hundred: `i32`, a thirty-two-bit number, or `u32`, an
642 unsigned thirty-two-bit number, or `i64`, a sixty-four-bit number or others.
643 So far, that hasn’t mattered, and so Rust defaults to an `i32`. However, here,
644 Rust doesn’t know how to compare the `guess` and the `secret_number`. They
645 need to be the same type. Ultimately, we want to convert the `String` we
646 read as input into a real number type, for comparison. We can do that
647 with three more lines. Here’s our new program:
653 use std::cmp::Ordering;
657 println!("Guess the number!");
659 let secret_number = rand::thread_rng().gen_range(1, 101);
661 println!("The secret number is: {}", secret_number);
663 println!("Please input your guess.");
665 let mut guess = String::new();
667 io::stdin().read_line(&mut guess)
669 .expect("failed to read line");
671 let guess: u32 = guess.trim().parse()
673 .expect("Please type a number!");
675 println!("You guessed: {}", guess);
677 match guess.cmp(&secret_number) {
678 Ordering::Less => println!("Too small!"),
679 Ordering::Greater => println!("Too big!"),
680 Ordering::Equal => println!("You win!"),
688 let guess: u32 = guess.trim().parse()
690 .expect("Please type a number!");
693 Wait a minute, I thought we already had a `guess`? We do, but Rust allows us
694 to ‘shadow’ the previous `guess` with a new one. This is often used in this
695 exact situation, where `guess` starts as a `String`, but we want to convert it
696 to an `u32`. Shadowing lets us re-use the `guess` name, rather than forcing us
697 to come up with two unique names like `guess_str` and `guess`, or something
700 We bind `guess` to an expression that looks like something we wrote earlier:
706 Followed by an `ok().expect()` invocation. Here, `guess` refers to the old
707 `guess`, the one that was a `String` with our input in it. The `trim()`
708 method on `String`s will eliminate any white space at the beginning and end of
709 our string. This is important, as we had to press the ‘return’ key to satisfy
710 `read_line()`. This means that if we type `5` and hit return, `guess` looks
711 like this: `5\n`. The `\n` represents ‘newline’, the enter key. `trim()` gets
712 rid of this, leaving our string with just the `5`. The [`parse()` method on
713 strings][parse] parses a string into some kind of number. Since it can parse a
714 variety of numbers, we need to give Rust a hint as to the exact type of number
715 we want. Hence, `let guess: u32`. The colon (`:`) after `guess` tells Rust
716 we’re going to annotate its type. `u32` is an unsigned, thirty-two bit
717 integer. Rust has [a number of built-in number types][number], but we’ve
718 chosen `u32`. It’s a good default choice for a small positive number.
720 [parse]: ../std/primitive.str.html#method.parse
721 [number]: primitive-types.html#numeric-types
723 Just like `read_line()`, our call to `parse()` could cause an error. What if
724 our string contained `A👍%`? There’d be no way to convert that to a number. As
725 such, we’ll do the same thing we did with `read_line()`: use the `ok()` and
726 `expect()` methods to crash if there’s an error.
728 Let’s try our program out!
732 Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game)
733 Running `target/guessing_game`
735 The secret number is: 58
736 Please input your guess.
742 Nice! You can see I even added spaces before my guess, and it still figured
743 out that I guessed 76. Run the program a few times, and verify that guessing
744 the number works, as well as guessing a number too small.
746 Now we’ve got most of the game working, but we can only make one guess. Let’s
747 change that by adding loops!
751 The `loop` keyword gives us an infinite loop. Let’s add that in:
757 use std::cmp::Ordering;
761 println!("Guess the number!");
763 let secret_number = rand::thread_rng().gen_range(1, 101);
765 println!("The secret number is: {}", secret_number);
768 println!("Please input your guess.");
770 let mut guess = String::new();
772 io::stdin().read_line(&mut guess)
774 .expect("failed to read line");
776 let guess: u32 = guess.trim().parse()
778 .expect("Please type a number!");
780 println!("You guessed: {}", guess);
782 match guess.cmp(&secret_number) {
783 Ordering::Less => println!("Too small!"),
784 Ordering::Greater => println!("Too big!"),
785 Ordering::Equal => println!("You win!"),
791 And try it out. But wait, didn’t we just add an infinite loop? Yup. Remember
792 our discussion about `parse()`? If we give a non-number answer, we’ll `return`
797 Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game)
798 Running `target/guessing_game`
800 The secret number is: 59
801 Please input your guess.
805 Please input your guess.
809 Please input your guess.
813 Please input your guess.
815 thread '<main>' panicked at 'Please type a number!'
818 Ha! `quit` actually quits. As does any other non-number input. Well, this is
819 suboptimal to say the least. First, let’s actually quit when you win the game:
825 use std::cmp::Ordering;
829 println!("Guess the number!");
831 let secret_number = rand::thread_rng().gen_range(1, 101);
833 println!("The secret number is: {}", secret_number);
836 println!("Please input your guess.");
838 let mut guess = String::new();
840 io::stdin().read_line(&mut guess)
842 .expect("failed to read line");
844 let guess: u32 = guess.trim().parse()
846 .expect("Please type a number!");
848 println!("You guessed: {}", guess);
850 match guess.cmp(&secret_number) {
851 Ordering::Less => println!("Too small!"),
852 Ordering::Greater => println!("Too big!"),
854 println!("You win!");
862 By adding the `break` line after the `You win!`, we’ll exit the loop when we
863 win. Exiting the loop also means exiting the program, since it’s the last
864 thing in `main()`. We have just one more tweak to make: when someone inputs a
865 non-number, we don’t want to quit, we just want to ignore it. We can do that
872 use std::cmp::Ordering;
876 println!("Guess the number!");
878 let secret_number = rand::thread_rng().gen_range(1, 101);
880 println!("The secret number is: {}", secret_number);
883 println!("Please input your guess.");
885 let mut guess = String::new();
887 io::stdin().read_line(&mut guess)
889 .expect("failed to read line");
891 let guess: u32 = match guess.trim().parse() {
896 println!("You guessed: {}", guess);
898 match guess.cmp(&secret_number) {
899 Ordering::Less => println!("Too small!"),
900 Ordering::Greater => println!("Too big!"),
902 println!("You win!");
910 These are the lines that changed:
913 let guess: u32 = match guess.trim().parse() {
919 This is how you generally move from ‘crash on error’ to ‘actually handle the
920 error’, by switching from `ok().expect()` to a `match` statement. The `Result`
921 returned by `parse()` is an enum just like `Ordering`, but in this case, each
922 variant has some data associated with it: `Ok` is a success, and `Err` is a
923 failure. Each contains more information: the successful parsed integer, or an
924 error type. In this case, we `match` on `Ok(num)`, which sets the inner value
925 of the `Ok` to the name `num`, and then we just return it on the right-hand
926 side. In the `Err` case, we don’t care what kind of error it is, so we just
927 use `_` instead of a name. This ignores the error, and `continue` causes us
928 to go to the next iteration of the `loop`.
930 Now we should be good! Let’s try:
934 Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game)
935 Running `target/guessing_game`
937 The secret number is: 61
938 Please input your guess.
942 Please input your guess.
946 Please input your guess.
948 Please input your guess.
954 Awesome! With one tiny last tweak, we have finished the guessing game. Can you
955 think of what it is? That’s right, we don’t want to print out the secret
956 number. It was good for testing, but it kind of ruins the game. Here’s our
963 use std::cmp::Ordering;
967 println!("Guess the number!");
969 let secret_number = rand::thread_rng().gen_range(1, 101);
972 println!("Please input your guess.");
974 let mut guess = String::new();
976 io::stdin().read_line(&mut guess)
978 .expect("failed to read line");
980 let guess: u32 = match guess.trim().parse() {
985 println!("You guessed: {}", guess);
987 match guess.cmp(&secret_number) {
988 Ordering::Less => println!("Too small!"),
989 Ordering::Greater => println!("Too big!"),
991 println!("You win!");
1001 At this point, you have successfully built the Guessing Game! Congratulations!
1003 This first project showed you a lot: `let`, `match`, methods, associated
1004 functions, using external crates, and more. Our next project will show off