]> git.proxmox.com Git - rustc.git/blame - src/doc/book/src/ch02-00-guessing-game-tutorial.md
New upstream version 1.55.0+dfsg1
[rustc.git] / src / doc / book / src / ch02-00-guessing-game-tutorial.md
CommitLineData
13cf67c4
XL
1# Programming a Guessing Game
2
3Let’s jump into Rust by working through a hands-on project together! This
4chapter introduces you to a few common Rust concepts by showing you how to use
5them in a real program. You’ll learn about `let`, `match`, methods, associated
6functions, using external crates, and more! The following chapters will explore
7these ideas in more detail. In this chapter, you’ll practice the fundamentals.
8
9We’ll implement a classic beginner programming problem: a guessing game. Here’s
10how it works: the program will generate a random integer between 1 and 100. It
11will then prompt the player to enter a guess. After a guess is entered, the
12program will indicate whether the guess is too low or too high. If the guess is
13correct, the game will print a congratulatory message and exit.
14
15## Setting Up a New Project
16
17To set up a new project, go to the *projects* directory that you created in
18Chapter 1 and make a new project using Cargo, like so:
19
f035d41b 20```console
13cf67c4
XL
21$ cargo new guessing_game
22$ cd guessing_game
23```
24
25The first command, `cargo new`, takes the name of the project (`guessing_game`)
26as the first argument. The second command changes to the new project’s
27directory.
28
29Look at the generated *Cargo.toml* file:
30
31<span class="filename">Filename: Cargo.toml</span>
32
33```toml
74b04a01 34{{#include ../listings/ch02-guessing-game-tutorial/no-listing-01-cargo-new/Cargo.toml}}
13cf67c4
XL
35```
36
13cf67c4
XL
37As you saw in Chapter 1, `cargo new` generates a “Hello, world!” program for
38you. Check out the *src/main.rs* file:
39
40<span class="filename">Filename: src/main.rs</span>
41
42```rust
74b04a01 43{{#rustdoc_include ../listings/ch02-guessing-game-tutorial/no-listing-01-cargo-new/src/main.rs}}
13cf67c4
XL
44```
45
46Now let’s compile this “Hello, world!” program and run it in the same step
47using the `cargo run` command:
48
f035d41b 49```console
74b04a01 50{{#include ../listings/ch02-guessing-game-tutorial/no-listing-01-cargo-new/output.txt}}
13cf67c4
XL
51```
52
53The `run` command comes in handy when you need to rapidly iterate on a project,
54as we’ll do in this game, quickly testing each iteration before moving on to
55the next one.
56
57Reopen the *src/main.rs* file. You’ll be writing all the code in this file.
58
59## Processing a Guess
60
61The first part of the guessing game program will ask for user input, process
62that input, and check that the input is in the expected form. To start, we’ll
63allow the player to input a guess. Enter the code in Listing 2-1 into
64*src/main.rs*.
65
66<span class="filename">Filename: src/main.rs</span>
67
68```rust,ignore
74b04a01 69{{#rustdoc_include ../listings/ch02-guessing-game-tutorial/listing-02-01/src/main.rs:all}}
13cf67c4
XL
70```
71
72<span class="caption">Listing 2-1: Code that gets a guess from the user and
73prints it</span>
74
75This code contains a lot of information, so let’s go over it line by line. To
76obtain user input and then print the result as output, we need to bring the
77`io` (input/output) library into scope. The `io` library comes from the
78standard library (which is known as `std`):
79
80```rust,ignore
74b04a01 81{{#rustdoc_include ../listings/ch02-guessing-game-tutorial/listing-02-01/src/main.rs:io}}
13cf67c4
XL
82```
83
84By default, Rust brings only a few types into the scope of every program in
85[the *prelude*][prelude]<!-- ignore -->. If a type you want to use isn’t in the
86prelude, you have to bring that type into scope explicitly with a `use`
87statement. Using the `std::io` library provides you with a number of useful
88features, including the ability to accept user input.
89
90[prelude]: ../std/prelude/index.html
91
92As you saw in Chapter 1, the `main` function is the entry point into the
93program:
94
95```rust,ignore
74b04a01 96{{#rustdoc_include ../listings/ch02-guessing-game-tutorial/listing-02-01/src/main.rs:main}}
13cf67c4
XL
97```
98
99The `fn` syntax declares a new function, the parentheses, `()`, indicate there
100are no parameters, and the curly bracket, `{`, starts the body of the function.
101
102As you also learned in Chapter 1, `println!` is a macro that prints a string to
103the screen:
104
105```rust,ignore
74b04a01 106{{#rustdoc_include ../listings/ch02-guessing-game-tutorial/listing-02-01/src/main.rs:print}}
13cf67c4
XL
107```
108
109This code is printing a prompt stating what the game is and requesting input
110from the user.
111
112### Storing Values with Variables
113
114Next, we’ll create a place to store the user input, like this:
115
116```rust,ignore
74b04a01 117{{#rustdoc_include ../listings/ch02-guessing-game-tutorial/listing-02-01/src/main.rs:string}}
13cf67c4
XL
118```
119
120Now the program is getting interesting! There’s a lot going on in this little
121line. Notice that this is a `let` statement, which is used to create a
122*variable*. Here’s another example:
123
124```rust,ignore
136023e0 125let apples = 5;
13cf67c4
XL
126```
127
136023e0
XL
128This line creates a new variable named `apples` and binds it to the value 5. In
129Rust, variables are immutable by default. We’ll be discussing this concept in
130detail in the [“Variables and Mutability”][variables-and-mutability]<!-- ignore
131--> section in Chapter 3. The following example shows how to use `mut` before
132the variable name to make a variable mutable:
13cf67c4
XL
133
134```rust,ignore
136023e0
XL
135let apples = 5; // immutable
136let mut bananas = 5; // mutable
13cf67c4
XL
137```
138
139> Note: The `//` syntax starts a comment that continues until the end of the
140> line. Rust ignores everything in comments, which are discussed in more detail
141> in Chapter 3.
142
532ac7d7 143Let’s return to the guessing game program. You now know that `let mut guess`
69743fb6
XL
144will introduce a mutable variable named `guess`. On the other side of the equal
145sign (`=`) is the value that `guess` is bound to, which is the result of
146calling `String::new`, a function that returns a new instance of a `String`.
147[`String`][string]<!-- ignore --> is a string type provided by the standard
148library that is a growable, UTF-8 encoded bit of text.
13cf67c4
XL
149
150[string]: ../std/string/struct.String.html
151
152The `::` syntax in the `::new` line indicates that `new` is an *associated
136023e0
XL
153function* of the `String` type. An associated function is implemented on a
154type, in this case `String`.
13cf67c4
XL
155
156This `new` function creates a new, empty string. You’ll find a `new` function
157on many types, because it’s a common name for a function that makes a new value
158of some kind.
159
160To summarize, the `let mut guess = String::new();` line has created a mutable
161variable that is currently bound to a new, empty instance of a `String`. Whew!
162
163Recall that we included the input/output functionality from the standard
532ac7d7
XL
164library with `use std::io;` on the first line of the program. Now we’ll call
165the `stdin` function from the `io` module:
13cf67c4
XL
166
167```rust,ignore
74b04a01 168{{#rustdoc_include ../listings/ch02-guessing-game-tutorial/listing-02-01/src/main.rs:read}}
13cf67c4
XL
169```
170
e74abb32 171If we hadn’t put the `use std::io` line at the beginning of the program, we
13cf67c4
XL
172could have written this function call as `std::io::stdin`. The `stdin` function
173returns an instance of [`std::io::Stdin`][iostdin]<!-- ignore -->, which is a
174type that represents a handle to the standard input for your terminal.
175
176[iostdin]: ../std/io/struct.Stdin.html
177
178The next part of the code, `.read_line(&mut guess)`, calls the
179[`read_line`][read_line]<!-- ignore --> method on the standard input handle to
180get input from the user. We’re also passing one argument to `read_line`: `&mut
181guess`.
182
183[read_line]: ../std/io/struct.Stdin.html#method.read_line
184
185The job of `read_line` is to take whatever the user types into standard input
6a06907d
XL
186and append that into a string (without overwriting its contents), so it takes
187that string as an argument. The string argument needs to be mutable so the
188method can change the string’s content by adding the user input.
13cf67c4
XL
189
190The `&` indicates that this argument is a *reference*, which gives you a way to
191let multiple parts of your code access one piece of data without needing to
192copy that data into memory multiple times. References are a complex feature,
193and one of Rust’s major advantages is how safe and easy it is to use
194references. You don’t need to know a lot of those details to finish this
195program. For now, all you need to know is that like variables, references are
196immutable by default. Hence, you need to write `&mut guess` rather than
197`&guess` to make it mutable. (Chapter 4 will explain references more
198thoroughly.)
199
200### Handling Potential Failure with the `Result` Type
201
74b04a01
XL
202We’re still working on this line of code. Although we’re now discussing a third
203line of text, it’s still part of a single logical line of code. The next part
204is this method:
13cf67c4
XL
205
206```rust,ignore
74b04a01 207{{#rustdoc_include ../listings/ch02-guessing-game-tutorial/listing-02-01/src/main.rs:expect}}
13cf67c4
XL
208```
209
136023e0
XL
210When you call a method with the `.method_name()` syntax, it’s often wise to
211introduce a newline and other whitespace to help break up long lines. We could
212have written this code as:
13cf67c4
XL
213
214```rust,ignore
215io::stdin().read_line(&mut guess).expect("Failed to read line");
216```
217
74b04a01
XL
218However, one long line is difficult to read, so it’s best to divide it. Now
219let’s discuss what this line does.
13cf67c4
XL
220
221As mentioned earlier, `read_line` puts what the user types into the string
222we’re passing it, but it also returns a value—in this case, an
223[`io::Result`][ioresult]<!-- ignore -->. Rust has a number of types named
224`Result` in its standard library: a generic [`Result`][result]<!-- ignore -->
225as well as specific versions for submodules, such as `io::Result`.
226
227[ioresult]: ../std/io/type.Result.html
228[result]: ../std/result/enum.Result.html
229
230The `Result` types are [*enumerations*][enums]<!-- ignore -->, often referred
231to as *enums*. An enumeration is a type that can have a fixed set of values,
232and those values are called the enum’s *variants*. Chapter 6 will cover enums
233in more detail.
234
235[enums]: ch06-00-enums.html
236
237For `Result`, the variants are `Ok` or `Err`. The `Ok` variant indicates the
238operation was successful, and inside `Ok` is the successfully generated value.
239The `Err` variant means the operation failed, and `Err` contains information
240about how or why the operation failed.
241
242The purpose of these `Result` types is to encode error-handling information.
69743fb6
XL
243Values of the `Result` type, like values of any type, have methods defined on
244them. An instance of `io::Result` has an [`expect` method][expect]<!-- ignore
245--> that you can call. If this instance of `io::Result` is an `Err` value,
246`expect` will cause the program to crash and display the message that you
247passed as an argument to `expect`. If the `read_line` method returns an `Err`,
248it would likely be the result of an error coming from the underlying operating
249system. If this instance of `io::Result` is an `Ok` value, `expect` will take
250the return value that `Ok` is holding and return just that value to you so you
13cf67c4
XL
251can use it. In this case, that value is the number of bytes in what the user
252entered into standard input.
253
254[expect]: ../std/result/enum.Result.html#method.expect
255
256If you don’t call `expect`, the program will compile, but you’ll get a warning:
257
f035d41b 258```console
74b04a01 259{{#include ../listings/ch02-guessing-game-tutorial/no-listing-02-without-expect/output.txt}}
13cf67c4
XL
260```
261
262Rust warns that you haven’t used the `Result` value returned from `read_line`,
263indicating that the program hasn’t handled a possible error.
264
265The right way to suppress the warning is to actually write error handling, but
69743fb6 266because you just want to crash this program when a problem occurs, you can use
13cf67c4
XL
267`expect`. You’ll learn about recovering from errors in Chapter 9.
268
269### Printing Values with `println!` Placeholders
270
74b04a01 271Aside from the closing curly bracket, there’s only one more line to discuss in
13cf67c4
XL
272the code added so far, which is the following:
273
274```rust,ignore
74b04a01 275{{#rustdoc_include ../listings/ch02-guessing-game-tutorial/listing-02-01/src/main.rs:print_guess}}
13cf67c4
XL
276```
277
278This line prints the string we saved the user’s input in. The set of curly
279brackets, `{}`, is a placeholder: think of `{}` as little crab pincers that
280hold a value in place. You can print more than one value using curly brackets:
281the first set of curly brackets holds the first value listed after the format
282string, the second set holds the second value, and so on. Printing multiple
283values in one call to `println!` would look like this:
284
285```rust
286let x = 5;
287let y = 10;
288
289println!("x = {} and y = {}", x, y);
290```
291
292This code would print `x = 5 and y = 10`.
293
294### Testing the First Part
295
296Let’s test the first part of the guessing game. Run it using `cargo run`:
297
74b04a01
XL
298<!-- manual-regeneration
299cd listings/ch02-guessing-game-tutorial/listing-02-01/
300cargo clean
301cargo run
302input 6 -->
303
f035d41b 304```console
13cf67c4
XL
305$ cargo run
306 Compiling guessing_game v0.1.0 (file:///projects/guessing_game)
74b04a01 307 Finished dev [unoptimized + debuginfo] target(s) in 6.44s
13cf67c4
XL
308 Running `target/debug/guessing_game`
309Guess the number!
310Please input your guess.
3116
312You guessed: 6
313```
314
315At this point, the first part of the game is done: we’re getting input from the
316keyboard and then printing it.
317
318## Generating a Secret Number
319
320Next, we need to generate a secret number that the user will try to guess. The
321secret number should be different every time so the game is fun to play more
322than once. Let’s use a random number between 1 and 100 so the game isn’t too
323difficult. Rust doesn’t yet include random number functionality in its standard
324library. However, the Rust team does provide a [`rand` crate][randcrate].
325
326[randcrate]: https://crates.io/crates/rand
327
328### Using a Crate to Get More Functionality
329
136023e0
XL
330Remember that a crate is a collection of Rust source code files. The project
331we’ve been building is a *binary crate*, which is an executable. The `rand`
332crate is a *library crate*, which contains code intended to be used in other
333programs.
13cf67c4 334
136023e0
XL
335Cargo’s coordination of external crates is where Cargo really shines. Before we
336can write code that uses `rand`, we need to modify the *Cargo.toml* file to
337include the `rand` crate as a dependency. Open that file now and add the
338following line to the bottom beneath the `[dependencies]` section header that
339Cargo created for you. Be sure to specify `rand` exactly as we have here, or
340the code examples in this tutorial may not work.
13cf67c4 341
e74abb32
XL
342<!-- When updating the version of `rand` used, also update the version of
343`rand` used in these files so they all match:
344* ch07-04-bringing-paths-into-scope-with-the-use-keyword.md
345* ch14-03-cargo-workspaces.md
346-->
347
13cf67c4
XL
348<span class="filename">Filename: Cargo.toml</span>
349
350```toml
74b04a01 351{{#include ../listings/ch02-guessing-game-tutorial/listing-02-02/Cargo.toml:9:}}
13cf67c4
XL
352```
353
354In the *Cargo.toml* file, everything that follows a header is part of a section
355that continues until another section starts. The `[dependencies]` section is
356where you tell Cargo which external crates your project depends on and which
357versions of those crates you require. In this case, we’ll specify the `rand`
6a06907d 358crate with the semantic version specifier `0.8.3`. Cargo understands [Semantic
13cf67c4 359Versioning][semver]<!-- ignore --> (sometimes called *SemVer*), which is a
6a06907d
XL
360standard for writing version numbers. The number `0.8.3` is actually shorthand
361for `^0.8.3`, which means any version that is at least `0.8.3` but below
362`0.9.0`. Cargo considers these versions to have public APIs compatible with
363version `0.8.3`, and this specification ensures you'll get the latest patch
364release that will still compile with the code in this chapter. Any version
365`0.9.0` or greater is not guaranteed to have the same API as what the following
366examples use.
13cf67c4
XL
367
368[semver]: http://semver.org
369
370Now, without changing any of the code, let’s build the project, as shown in
69743fb6 371Listing 2-2.
13cf67c4 372
74b04a01
XL
373<!-- manual-regeneration
374cd listings/ch02-guessing-game-tutorial/listing-02-02/
375cargo clean
376cargo build -->
377
f035d41b 378```console
13cf67c4 379$ cargo build
e74abb32 380 Updating crates.io index
6a06907d
XL
381 Downloaded rand v0.8.3
382 Downloaded libc v0.2.86
383 Downloaded getrandom v0.2.2
384 Downloaded cfg-if v1.0.0
385 Downloaded ppv-lite86 v0.2.10
386 Downloaded rand_chacha v0.3.0
387 Downloaded rand_core v0.6.2
388 Compiling rand_core v0.6.2
389 Compiling libc v0.2.86
390 Compiling getrandom v0.2.2
391 Compiling cfg-if v1.0.0
392 Compiling ppv-lite86 v0.2.10
393 Compiling rand_chacha v0.3.0
394 Compiling rand v0.8.3
13cf67c4 395 Compiling guessing_game v0.1.0 (file:///projects/guessing_game)
74b04a01 396 Finished dev [unoptimized + debuginfo] target(s) in 2.53s
13cf67c4
XL
397```
398
399<span class="caption">Listing 2-2: The output from running `cargo build` after
400adding the rand crate as a dependency</span>
401
402You may see different version numbers (but they will all be compatible with
6a06907d
XL
403the code, thanks to SemVer!), different lines (depending on the operating
404system), and the lines may be in a different order.
13cf67c4
XL
405
406Now that we have an external dependency, Cargo fetches the latest versions of
407everything from the *registry*, which is a copy of data from
408[Crates.io][cratesio]. Crates.io is where people in the Rust ecosystem post
409their open source Rust projects for others to use.
410
dc9dc135 411[cratesio]: https://crates.io/
13cf67c4
XL
412
413After updating the registry, Cargo checks the `[dependencies]` section and
414downloads any crates you don’t have yet. In this case, although we only listed
6a06907d
XL
415`rand` as a dependency, Cargo also grabbed other crates that `rand` depends on
416to work. After downloading the crates, Rust compiles them and then compiles the
417project with the dependencies available.
13cf67c4
XL
418
419If you immediately run `cargo build` again without making any changes, you
420won’t get any output aside from the `Finished` line. Cargo knows it has already
421downloaded and compiled the dependencies, and you haven’t changed anything
422about them in your *Cargo.toml* file. Cargo also knows that you haven’t changed
423anything about your code, so it doesn’t recompile that either. With nothing to
424do, it simply exits.
425
426If you open up the *src/main.rs* file, make a trivial change, and then save it
427and build again, you’ll only see two lines of output:
428
74b04a01
XL
429<!-- manual-regeneration
430cd listings/ch02-guessing-game-tutorial/listing-02-02/
431touch src/main.rs
432cargo build -->
433
f035d41b 434```console
13cf67c4
XL
435$ cargo build
436 Compiling guessing_game v0.1.0 (file:///projects/guessing_game)
74b04a01 437 Finished dev [unoptimized + debuginfo] target(s) in 2.53 secs
13cf67c4
XL
438```
439
440These lines show Cargo only updates the build with your tiny change to the
441*src/main.rs* file. Your dependencies haven’t changed, so Cargo knows it can
442reuse what it has already downloaded and compiled for those. It just rebuilds
443your part of the code.
444
445#### Ensuring Reproducible Builds with the *Cargo.lock* File
446
447Cargo has a mechanism that ensures you can rebuild the same artifact every time
448you or anyone else builds your code: Cargo will use only the versions of the
449dependencies you specified until you indicate otherwise. For example, what
136023e0
XL
450happens if next week version 0.8.4 of the `rand` crate comes out, and that
451version contains an important bug fix, but it also contains a regression that
452will break your code?
13cf67c4
XL
453
454The answer to this problem is the *Cargo.lock* file, which was created the
455first time you ran `cargo build` and is now in your *guessing_game* directory.
456When you build a project for the first time, Cargo figures out all the
457versions of the dependencies that fit the criteria and then writes them to
458the *Cargo.lock* file. When you build your project in the future, Cargo will
459see that the *Cargo.lock* file exists and use the versions specified there
460rather than doing all the work of figuring out versions again. This lets you
461have a reproducible build automatically. In other words, your project will
6a06907d 462remain at `0.8.3` until you explicitly upgrade, thanks to the *Cargo.lock*
13cf67c4
XL
463file.
464
465#### Updating a Crate to Get a New Version
466
467When you *do* want to update a crate, Cargo provides another command, `update`,
468which will ignore the *Cargo.lock* file and figure out all the latest versions
469that fit your specifications in *Cargo.toml*. If that works, Cargo will write
470those versions to the *Cargo.lock* file.
471
6a06907d
XL
472But by default, Cargo will only look for versions greater than `0.8.3` and less
473than `0.9.0`. If the `rand` crate has released two new versions, `0.8.4` and
474`0.9.0`, you would see the following if you ran `cargo update`:
13cf67c4 475
74b04a01
XL
476<!-- manual-regeneration
477cd listings/ch02-guessing-game-tutorial/listing-02-02/
478cargo update
6a06907d 479assuming there is a new 0.8.x version of rand; otherwise use another update
74b04a01
XL
480as a guide to creating the hypothetical output shown here -->
481
f035d41b 482```console
13cf67c4 483$ cargo update
e74abb32 484 Updating crates.io index
6a06907d 485 Updating rand v0.8.3 -> v0.8.4
13cf67c4
XL
486```
487
488At this point, you would also notice a change in your *Cargo.lock* file noting
6a06907d 489that the version of the `rand` crate you are now using is `0.8.4`.
13cf67c4 490
6a06907d 491If you wanted to use `rand` version `0.9.0` or any version in the `0.9.x`
13cf67c4
XL
492series, you’d have to update the *Cargo.toml* file to look like this instead:
493
494```toml
495[dependencies]
6a06907d 496rand = "0.9.0"
13cf67c4
XL
497```
498
499The next time you run `cargo build`, Cargo will update the registry of crates
500available and reevaluate your `rand` requirements according to the new version
501you have specified.
502
503There’s a lot more to say about [Cargo][doccargo]<!-- ignore --> and [its
504ecosystem][doccratesio]<!-- ignore --> which we’ll discuss in Chapter 14, but
505for now, that’s all you need to know. Cargo makes it very easy to reuse
506libraries, so Rustaceans are able to write smaller projects that are assembled
507from a number of packages.
508
509[doccargo]: http://doc.crates.io
510[doccratesio]: http://doc.crates.io/crates-io.html
511
512### Generating a Random Number
513
514Now that you’ve added the `rand` crate to *Cargo.toml*, let’s start using
69743fb6 515`rand`. The next step is to update *src/main.rs*, as shown in Listing 2-3.
13cf67c4
XL
516
517<span class="filename">Filename: src/main.rs</span>
518
519```rust,ignore
74b04a01 520{{#rustdoc_include ../listings/ch02-guessing-game-tutorial/listing-02-03/src/main.rs:all}}
13cf67c4
XL
521```
522
523<span class="caption">Listing 2-3: Adding code to generate a random
524number</span>
525
9fa01778 526First, we add a `use` line: `use rand::Rng`. The `Rng` trait defines
13cf67c4
XL
527methods that random number generators implement, and this trait must be in
528scope for us to use those methods. Chapter 10 will cover traits in detail.
529
9fa01778 530Next, we’re adding two lines in the middle. The `rand::thread_rng` function
13cf67c4
XL
531will give us the particular random number generator that we’re going to use:
532one that is local to the current thread of execution and seeded by the
9fa01778 533operating system. Then we call the `gen_range` method on the random number
6a06907d
XL
534generator. This method is defined by the `Rng` trait that we brought into scope
535with the `use rand::Rng` statement. The `gen_range` method takes a range
536expression as an argument and generates a random number in the range. The kind
537of range expression we’re using here takes the form `start..end`. It’s
538inclusive on the lower bound but exclusive on the upper bound, so we need to
539specify `1..101` to request a number between 1 and 100. Alternatively, we could
540pass the range `1..=100`, which is equivalent.
13cf67c4
XL
541
542> Note: You won’t just know which traits to use and which methods and functions
543> to call from a crate. Instructions for using a crate are in each crate’s
544> documentation. Another neat feature of Cargo is that you can run the `cargo
545> doc --open` command, which will build documentation provided by all of your
546> dependencies locally and open it in your browser. If you’re interested in
547> other functionality in the `rand` crate, for example, run `cargo doc --open`
548> and click `rand` in the sidebar on the left.
549
9fa01778
XL
550The second line that we added to the middle of the code prints the secret
551number. This is useful while we’re developing the program to be able to test
552it, but we’ll delete it from the final version. It’s not much of a game if the
553program prints the answer as soon as it starts!
13cf67c4
XL
554
555Try running the program a few times:
556
74b04a01
XL
557<!-- manual-regeneration
558cd listings/ch02-guessing-game-tutorial/listing-02-03/
559cargo run
5604
561cargo run
5625
563-->
564
f035d41b 565```console
13cf67c4
XL
566$ cargo run
567 Compiling guessing_game v0.1.0 (file:///projects/guessing_game)
74b04a01 568 Finished dev [unoptimized + debuginfo] target(s) in 2.53s
13cf67c4
XL
569 Running `target/debug/guessing_game`
570Guess the number!
571The secret number is: 7
572Please input your guess.
5734
574You guessed: 4
74b04a01 575
13cf67c4 576$ cargo run
74b04a01 577 Finished dev [unoptimized + debuginfo] target(s) in 0.02s
13cf67c4
XL
578 Running `target/debug/guessing_game`
579Guess the number!
580The secret number is: 83
581Please input your guess.
5825
583You guessed: 5
584```
585
586You should get different random numbers, and they should all be numbers between
5871 and 100. Great job!
588
589## Comparing the Guess to the Secret Number
590
591Now that we have user input and a random number, we can compare them. That step
592is shown in Listing 2-4. Note that this code won’t compile quite yet, as we
593will explain.
594
595<span class="filename">Filename: src/main.rs</span>
596
597```rust,ignore,does_not_compile
74b04a01 598{{#rustdoc_include ../listings/ch02-guessing-game-tutorial/listing-02-04/src/main.rs:here}}
13cf67c4
XL
599```
600
601<span class="caption">Listing 2-4: Handling the possible return values of
602comparing two numbers</span>
603
604The first new bit here is another `use` statement, bringing a type called
605`std::cmp::Ordering` into scope from the standard library. Like `Result`,
606`Ordering` is another enum, but the variants for `Ordering` are `Less`,
607`Greater`, and `Equal`. These are the three outcomes that are possible when you
608compare two values.
609
69743fb6
XL
610Then we add five new lines at the bottom that use the `Ordering` type. The
611`cmp` method compares two values and can be called on anything that can be
13cf67c4
XL
612compared. It takes a reference to whatever you want to compare with: here it’s
613comparing the `guess` to the `secret_number`. Then it returns a variant of the
614`Ordering` enum we brought into scope with the `use` statement. We use a
615[`match`][match]<!-- ignore --> expression to decide what to do next based on
616which variant of `Ordering` was returned from the call to `cmp` with the values
617in `guess` and `secret_number`.
618
619[match]: ch06-02-match.html
620
621A `match` expression is made up of *arms*. An arm consists of a *pattern* and
622the code that should be run if the value given to the beginning of the `match`
623expression fits that arm’s pattern. Rust takes the value given to `match` and
624looks through each arm’s pattern in turn. The `match` construct and patterns
625are powerful features in Rust that let you express a variety of situations your
626code might encounter and make sure that you handle them all. These features
627will be covered in detail in Chapter 6 and Chapter 18, respectively.
628
629Let’s walk through an example of what would happen with the `match` expression
630used here. Say that the user has guessed 50 and the randomly generated secret
631number this time is 38. When the code compares 50 to 38, the `cmp` method will
632return `Ordering::Greater`, because 50 is greater than 38. The `match`
633expression gets the `Ordering::Greater` value and starts checking each arm’s
634pattern. It looks at the first arm’s pattern, `Ordering::Less`, and sees that
635the value `Ordering::Greater` does not match `Ordering::Less`, so it ignores
636the code in that arm and moves to the next arm. The next arm’s pattern,
637`Ordering::Greater`, *does* match `Ordering::Greater`! The associated code in
638that arm will execute and print `Too big!` to the screen. The `match`
639expression ends because it has no need to look at the last arm in this scenario.
640
641However, the code in Listing 2-4 won’t compile yet. Let’s try it:
642
f035d41b 643```console
74b04a01 644{{#include ../listings/ch02-guessing-game-tutorial/listing-02-04/output.txt}}
13cf67c4
XL
645```
646
647The core of the error states that there are *mismatched types*. Rust has a
648strong, static type system. However, it also has type inference. When we wrote
9fa01778 649`let mut guess = String::new()`, Rust was able to infer that `guess` should be
13cf67c4
XL
650a `String` and didn’t make us write the type. The `secret_number`, on the other
651hand, is a number type. A few number types can have a value between 1 and 100:
652`i32`, a 32-bit number; `u32`, an unsigned 32-bit number; `i64`, a 64-bit
653number; as well as others. Rust defaults to an `i32`, which is the type of
654`secret_number` unless you add type information elsewhere that would cause Rust
655to infer a different numerical type. The reason for the error is that Rust
656cannot compare a string and a number type.
657
658Ultimately, we want to convert the `String` the program reads as input into a
9fa01778 659real number type so we can compare it numerically to the secret number. We can
f9f354fc 660do that by adding another line to the `main` function body:
13cf67c4
XL
661
662<span class="filename">Filename: src/main.rs</span>
663
664```rust,ignore
74b04a01 665{{#rustdoc_include ../listings/ch02-guessing-game-tutorial/no-listing-03-convert-string-to-number/src/main.rs:here}}
13cf67c4
XL
666```
667
f9f354fc 668The line is:
13cf67c4
XL
669
670```rust,ignore
f9f354fc 671let guess: u32 = guess.trim().parse().expect("Please type a number!");
13cf67c4
XL
672```
673
674We create a variable named `guess`. But wait, doesn’t the program already have
675a variable named `guess`? It does, but Rust allows us to *shadow* the previous
676value of `guess` with a new one. This feature is often used in situations in
677which you want to convert a value from one type to another type. Shadowing lets
678us reuse the `guess` variable name rather than forcing us to create two unique
69743fb6 679variables, such as `guess_str` and `guess` for example. (Chapter 3 covers
13cf67c4
XL
680shadowing in more detail.)
681
682We bind `guess` to the expression `guess.trim().parse()`. The `guess` in the
683expression refers to the original `guess` that was a `String` with the input in
684it. The `trim` method on a `String` instance will eliminate any whitespace at
685the beginning and end. Although `u32` can contain only numerical characters,
686the user must press <span class="keystroke">enter</span> to satisfy
687`read_line`. When the user presses <span class="keystroke">enter</span>, a
688newline character is added to the string. For example, if the user types <span
689class="keystroke">5</span> and presses <span class="keystroke">enter</span>,
690`guess` looks like this: `5\n`. The `\n` represents “newline,” the result of
cdc7bbd5
XL
691pressing <span class="keystroke">enter</span> (On Windows, pressing <span
692class="keystroke">enter</span> results in a carriage return and a newline,
693`\r\n`). The `trim` method eliminates `\n` or `\r\n`, resulting in just `5`.
13cf67c4
XL
694
695The [`parse` method on strings][parse]<!-- ignore --> parses a string into some
696kind of number. Because this method can parse a variety of number types, we
697need to tell Rust the exact number type we want by using `let guess: u32`. The
698colon (`:`) after `guess` tells Rust we’ll annotate the variable’s type. Rust
699has a few built-in number types; the `u32` seen here is an unsigned, 32-bit
700integer. It’s a good default choice for a small positive number. You’ll learn
701about other number types in Chapter 3. Additionally, the `u32` annotation in
702this example program and the comparison with `secret_number` means that Rust
703will infer that `secret_number` should be a `u32` as well. So now the
704comparison will be between two values of the same type!
705
706[parse]: ../std/primitive.str.html#method.parse
707
708The call to `parse` could easily cause an error. If, for example, the string
709contained `A👍%`, there would be no way to convert that to a number. Because it
710might fail, the `parse` method returns a `Result` type, much as the `read_line`
9fa01778
XL
711method does (discussed earlier in [“Handling Potential Failure with the
712`Result` Type”](#handling-potential-failure-with-the-result-type)<!-- ignore
713-->). We’ll treat this `Result` the same way by using the `expect` method
13cf67c4
XL
714again. If `parse` returns an `Err` `Result` variant because it couldn’t create
715a number from the string, the `expect` call will crash the game and print the
716message we give it. If `parse` can successfully convert the string to a number,
717it will return the `Ok` variant of `Result`, and `expect` will return the
718number that we want from the `Ok` value.
719
720Let’s run the program now!
721
74b04a01
XL
722<!-- manual-regeneration
723cd listings/ch02-guessing-game-tutorial/no-listing-03-convert-string-to-number/
724cargo run
725 76
726-->
727
f035d41b 728```console
13cf67c4
XL
729$ cargo run
730 Compiling guessing_game v0.1.0 (file:///projects/guessing_game)
74b04a01 731 Finished dev [unoptimized + debuginfo] target(s) in 0.43s
69743fb6 732 Running `target/debug/guessing_game`
13cf67c4
XL
733Guess the number!
734The secret number is: 58
735Please input your guess.
736 76
737You guessed: 76
738Too big!
739```
740
741Nice! Even though spaces were added before the guess, the program still figured
742out that the user guessed 76. Run the program a few times to verify the
743different behavior with different kinds of input: guess the number correctly,
744guess a number that is too high, and guess a number that is too low.
745
746We have most of the game working now, but the user can make only one guess.
747Let’s change that by adding a loop!
748
749## Allowing Multiple Guesses with Looping
750
751The `loop` keyword creates an infinite loop. We’ll add that now to give users
752more chances at guessing the number:
753
754<span class="filename">Filename: src/main.rs</span>
755
756```rust,ignore
74b04a01 757{{#rustdoc_include ../listings/ch02-guessing-game-tutorial/no-listing-04-looping/src/main.rs:here}}
13cf67c4
XL
758```
759
760As you can see, we’ve moved everything into a loop from the guess input prompt
761onward. Be sure to indent the lines inside the loop another four spaces each
762and run the program again. Notice that there is a new problem because the
763program is doing exactly what we told it to do: ask for another guess forever!
764It doesn’t seem like the user can quit!
765
532ac7d7 766The user could always interrupt the program by using the keyboard shortcut <span
13cf67c4 767class="keystroke">ctrl-c</span>. But there’s another way to escape this
9fa01778
XL
768insatiable monster, as mentioned in the `parse` discussion in [“Comparing the
769Guess to the Secret Number”](#comparing-the-guess-to-the-secret-number)<!--
770ignore -->: if the user enters a non-number answer, the program will crash. The
771user can take advantage of that in order to quit, as shown here:
13cf67c4 772
74b04a01
XL
773<!-- manual-regeneration
774cd listings/ch02-guessing-game-tutorial/no-listing-04-looping/
775cargo run
776(too small guess)
777(too big guess)
778(correct guess)
779quit
780-->
781
f035d41b 782```console
13cf67c4
XL
783$ cargo run
784 Compiling guessing_game v0.1.0 (file:///projects/guessing_game)
74b04a01 785 Finished dev [unoptimized + debuginfo] target(s) in 1.50s
69743fb6 786 Running `target/debug/guessing_game`
13cf67c4
XL
787Guess the number!
788The secret number is: 59
789Please input your guess.
79045
791You guessed: 45
792Too small!
793Please input your guess.
79460
795You guessed: 60
796Too big!
797Please input your guess.
79859
799You guessed: 59
800You win!
801Please input your guess.
802quit
fc512014
XL
803thread 'main' panicked at 'Please type a number!: ParseIntError { kind: InvalidDigit }', src/main.rs:28:47
804note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
13cf67c4
XL
805```
806
807Typing `quit` actually quits the game, but so will any other non-number input.
808However, this is suboptimal to say the least. We want the game to automatically
809stop when the correct number is guessed.
810
811### Quitting After a Correct Guess
812
813Let’s program the game to quit when the user wins by adding a `break` statement:
814
815<span class="filename">Filename: src/main.rs</span>
816
817```rust,ignore
74b04a01 818{{#rustdoc_include ../listings/ch02-guessing-game-tutorial/no-listing-05-quitting/src/main.rs:here}}
13cf67c4
XL
819```
820
821Adding the `break` line after `You win!` makes the program exit the loop when
822the user guesses the secret number correctly. Exiting the loop also means
823exiting the program, because the loop is the last part of `main`.
824
825### Handling Invalid Input
826
827To further refine the game’s behavior, rather than crashing the program when
828the user inputs a non-number, let’s make the game ignore a non-number so the
829user can continue guessing. We can do that by altering the line where `guess`
69743fb6
XL
830is converted from a `String` to a `u32`, as shown in Listing 2-5.
831
832<span class="filename">Filename: src/main.rs</span>
13cf67c4
XL
833
834```rust,ignore
74b04a01 835{{#rustdoc_include ../listings/ch02-guessing-game-tutorial/listing-02-05/src/main.rs:here}}
13cf67c4
XL
836```
837
69743fb6
XL
838<span class="caption">Listing 2-5: Ignoring a non-number guess and asking for
839another guess instead of crashing the program</span>
840
136023e0
XL
841Switching from an `expect` call to a `match` expression is one way of moving
842from crashing on an error to handling the error. Remember that `parse` returns
843a `Result` type and `Result` is an enum that has the variants `Ok` or `Err`.
844We’re using a `match` expression here, as we did with the `Ordering` result of
845the `cmp` method.
13cf67c4
XL
846
847If `parse` is able to successfully turn the string into a number, it will
848return an `Ok` value that contains the resulting number. That `Ok` value will
849match the first arm’s pattern, and the `match` expression will just return the
850`num` value that `parse` produced and put inside the `Ok` value. That number
851will end up right where we want it in the new `guess` variable we’re creating.
852
853If `parse` is *not* able to turn the string into a number, it will return an
854`Err` value that contains more information about the error. The `Err` value
855does not match the `Ok(num)` pattern in the first `match` arm, but it does
856match the `Err(_)` pattern in the second arm. The underscore, `_`, is a
857catchall value; in this example, we’re saying we want to match all `Err`
858values, no matter what information they have inside them. So the program will
69743fb6 859execute the second arm’s code, `continue`, which tells the program to go to the
9fa01778 860next iteration of the `loop` and ask for another guess. So, effectively, the
69743fb6 861program ignores all errors that `parse` might encounter!
13cf67c4
XL
862
863Now everything in the program should work as expected. Let’s try it:
864
74b04a01
XL
865<!-- manual-regeneration
866cd listings/ch02-guessing-game-tutorial/listing-02-05/
867cargo run
868(too small guess)
869(too big guess)
870foo
871(correct guess)
872-->
873
f035d41b 874```console
13cf67c4
XL
875$ cargo run
876 Compiling guessing_game v0.1.0 (file:///projects/guessing_game)
fc512014 877 Finished dev [unoptimized + debuginfo] target(s) in 4.45s
69743fb6 878 Running `target/debug/guessing_game`
13cf67c4
XL
879Guess the number!
880The secret number is: 61
881Please input your guess.
88210
883You guessed: 10
884Too small!
885Please input your guess.
88699
887You guessed: 99
888Too big!
889Please input your guess.
890foo
891Please input your guess.
89261
893You guessed: 61
894You win!
895```
896
897Awesome! With one tiny final tweak, we will finish the guessing game. Recall
898that the program is still printing the secret number. That worked well for
899testing, but it ruins the game. Let’s delete the `println!` that outputs the
69743fb6 900secret number. Listing 2-6 shows the final code.
13cf67c4
XL
901
902<span class="filename">Filename: src/main.rs</span>
903
904```rust,ignore
74b04a01 905{{#rustdoc_include ../listings/ch02-guessing-game-tutorial/listing-02-06/src/main.rs}}
13cf67c4
XL
906```
907
69743fb6 908<span class="caption">Listing 2-6: Complete guessing game code</span>
13cf67c4
XL
909
910## Summary
911
69743fb6 912At this point, you’ve successfully built the guessing game. Congratulations!
13cf67c4
XL
913
914This project was a hands-on way to introduce you to many new Rust concepts:
136023e0
XL
915`let`, `match`, functions, the use of external crates, and more. In the next
916few chapters, you’ll learn about these concepts in more detail. Chapter 3
917covers concepts that most programming languages have, such as variables, data
918types, and functions, and shows how to use them in Rust. Chapter 4 explores
919ownership, a feature that makes Rust different from other languages. Chapter 5
920discusses structs and method syntax, and Chapter 6 explains how enums work.
9fa01778
XL
921
922[variables-and-mutability]:
923ch03-01-variables-and-mutability.html#variables-and-mutability