Updated guessing-game.md

Jaeju_Kim authored
revision 895b91269518d97b905b1dd4fac8abb1ef87dd8d
guessing-game
# 3.1. 추리 게임 (Guessing Game) - 40%

첫 프로젝트로 우리는 고전적인 초보자용 프로그래밍 문제인 추리 게임을 구현할 것입니다. 이 프로그램은 다음과 같이 동작합니다. 우리 프로그램은 1부터 100 사이의 정수형 난수를 생성합니다. 그리고 나서 우리에게 예측값을 입력받습니다. 우리에게 입력을 받은 프로그램은 그 값이 너무 작거나 너무 크면 우리에게 알려줍니다. 우리가 정확한 값을 예측하는 데 성공하면, 프로그램은 우리를 칭찬해 줍니다. 괜찮죠?

# 구성

새 프로젝트를 구성해 봅시다. 여러분의 프로젝트 디렉터리에 가 주세요. `hello_world`를 위해서 디렉터리 구조와 `Cargo.toml`을 만들었던 방법을 기억하고 있으신가요? Cargo는 이 작업을 우리 대신 해 주는 명령어를 가지고 있습니다. 한번 보도록 합시다.


```bash
$ cd ~/projects
$ cargo new guessing_game --bin
$ cd guessing_game
```

우리는 `cargo new`에게 프로젝트의 이름과 함께 `--bin` 플래그를 넘겨주었습니다. 라이브러리가 아니라 바이너리를 만들고 있기 때문입니다.

생성된 `Cargo.toml`의 내용을 확인해 봅시다.

```toml
[package]

name = "guessing_game"
version = "0.0.1"
authors = ["Your Name "]
```

Cargo는 여러분의 환경으로부터 이 정보를 얻습니다. 만약 틀린 부분이 있다면 가서 고치세요.

마지막으로, Cargo는 우리를 위해서 'Hello, world' 프로그램을 작성해 두었습니다. `src/main.rs`를 확인해 보세요.

```rust
fn main() {
println!("Hello, world!")
}
```

Cargo가 만들어 준 것을 컴파일해 봅시다.

```{bash}
$ cargo build
Compiling guessing_game v0.0.1 (file:///home/you/projects/guessing_game)
```

훌륭하군요! 여러분의 `src/main.rs`를 다시 열어 봅니다. 우리는 이 파일에 모든 코드를 작성할 것입니다.

나아가기 전에, 또 다른 Cargo 명령어를 보여드리겠습니다. `run`입니다. `cargo run`은 `cargo build`와 비슷한 것이지만, 이것은 그 이후 생성된 실행 파일을 실행합니다. 시도해 봅시다.

```bash
$ cargo run
Compiling guessing_game v0.0.1 (file:///home/you/projects/guessing_game)
Running `target/debug/guessing_game`
Hello, world!
```

좋군요! `run` 명령어는 여러분이 하나의 프로젝트를 빠르게 반복해야 할 때에 편리합니다. 우리 게임이 바로 그런 프로젝트이죠. 다음 것으로 넘어가기 전에 빠르게 각 반복을 테스트할 필요가 있습니다.


# 추측을 처리하기

시작해 봅시다! 추리 게임에서 처음으로 해야 할 것은 우리 플레이어들에게 예측을 입력할 수 있도록 하는 것입니다. 이것을 여러분의 `src/main.rs` 에 넣으세요.

```rust,no_run
use std::io;

fn main() {
println!("Guess the number!");

println!("Please input your guess.");

let mut guess = String::new();

io::stdin().read_line(&mut guess)
.ok()
.expect("Failed to read line");

println!("You guessed: {}", guess);
}
```

상당히 많군요! 조금씩 살펴보도록 합시다.

```rust,ignore
use std::io;
```

우리는 사용자 입력을 받고 결과를 출력해야 합니다. 그러므로 우리는 표준 라이브러리의 `io` 라이브러리가 필요합니다. Rust가 모든 프로그램에 임포트하는 것은 ['서곡'][prelude]이라 불리는 아주 작은 라이브러리 뿐입니다. 만약 서곡에 들어 있지 않은 것을 사용하고 싶다면, 여러분은 그것을 직접적으로 `use`해야 합니다.


[prelude]: ../std/prelude/index.html

```rust,ignore
fn main() {
```

이전에 보셨던 것처럼, `main()` 함수는 여러분의 프로그램으로 들어가는 진입점입니다. `fn` 문법은 새 함수를 선언하며, `()`는 매개 변수가 없다는 것을 나타냅니다. 그리고 `{`는 함수의 몸체를 시작합니다. 우리가 반환 타입을 포함시키지 않았기 때문에, 빈 [튜플][tuples]인 `()`으로 간주됩니다.


[tuples]: primitive-types.html#tuples

```rust,ignore
println!("Guess the number!");

println!("Please input your guess.");
```

우리는 `println!()`이 화면에 [문자열][strings]을 출력하는 [매크로][macros]라는 것을 이전에 배운 적이 있습니다.

[macros]: macros.html
[strings]: strings.html

```rust,ignore
let mut guess = String::new();
```

점점 흥미로워지고 있군요! 이 짧은 줄에 많은 것이 일어나고 있습니다. 첫 번째로 눈치챌 수 있는 것은, 이것은 '변수 결합'을 만드는 데 사용되는 [let 구문][let]이라는 것입니다. 이것들은 다음과 같은 형태를 취합니다.

```rust,ignore
let foo = bar;
```

[let]: variable-bindings.html

이것은 `foo`라는 이름의 새 결합을 만들고, 그것을 값 `bar`에 결합합니다. 많은 언어들에서 이것은 '변수'라고 불립니다만, Rust의 변수 결합은 몇 가지 특이한 점들을 가지고 있습니다.

예를 들어서, Rust의 변수들은 기본적으로 [변경 불가능][immutable]합니다. 그래서 우리는 이 예제에서 `mut`를 사용한 것입니다. 이것은 이 결합을 변경할 수 있도록 만듭니다. `let`은 좌변에 이름을 취하는 대신, 사실은 '[패턴][patterns]'을 받습니다. 우리는 나중에 패턴을 사용할 것입니다. 지금으로서는 충분히 사용할 수 있을 정도로 간단합니다.


```
let foo = 5; // immutable.
let mut bar = 5; // mutable
```

[immutable]: mutability.html
[patterns]: patterns.html

오, 그리고 `//` 은 그것이 있는 줄의 마지막까지를 주석으로 만듭니다. Rust는 [주석][comments] 속의 모든 내용을 무시합니다.

[comments]: comments.html

그러므로 지금 우리는 `let mut guess`가 이름이 `guess`인, 새 변경 가능한 결합을 도입한다는 것을 알고 있습니다. 그러나 거기에 결합될, 그 반대편에 있는 `String::new()`에 대해서도 보아야겠죠.


`String`은 표준 라이브러리에서 제공하는 문자열 타입입니다. [`String`][string]은 자라날 수 있는 UTF-8 텍스트입니다.


[string]: ../std/string/struct.String.html

`::new()` 문법에서 `::`를 사용하는 이유는 이것이 어떤 특정한 타입과 '연결된 함수'이기 때문입니다. 이것은 다시 말해서 new() 함수가 `String`의 인스턴스 하나하나에 연결되는 것이 아니라, `String` 그 자체에 연결되어 있다는 것을 말합니다. 일부 언어들은 이것을 '정적 메서드'라고 부릅니다.

이 함수는 빈 `String`을 새로 만들기 때문에 `new()`라는 이름을 가지고 있습니다. 어떤 종류의 새로운 값을 만드는 데 흔하게 사용되는 이름이기 때문에, 여러분은 많은 타입들에서 `new()` 함수를 보게 될 것입니다.


다시 진행해 봅시다.

```rust,ignore
io::stdin().read_line(&mut guess)
.ok()
.expect("Failed to read line");
```

아주 많은 것이 있군요! 하나하나씩 봅시다. 첫 번째 줄은 두 부분으로 이루어져 있습니다. 다음이 첫 번째 부분입니다.

```rust,ignore
io::stdin()
```

프로그램의 첫 줄에서 `std::io`를 `use` 했던 것을 기억하고 있습니까? 이제 우리는 거기에 연결된 함수들을 호출합니다. 만약 우리가 `use std::io`를 하지 않았다면, 우리는 이 줄을 `std::io::stdin()`으로 쓸 수도 있었습니다.

이 특별한 함수는 여러분의 터미널의 표준 입력에 대한 핸들을 반환합니다. 더 자세히 알고 싶으면 [std::io::Stdin][iostdin]을 참고하세요.

[iostdin]: ../std/io/struct.Stdin.html

다음 부분은 이 핸들을 사용자로부터 입력을 받는 데 사용할 것입니다.

```rust,ignore
.read_line(&mut guess)
```

여기에서 핸들에게 [`read_line()`][read_line] 메서드를 호출합니다. [메서드][method]는 연결된 함수와 비슷하지만, 그 타입 자체가 아니라 그 타입의 각 인스턴스들에서만 사용할 수 있습니다. 우리는 또한 `read_line`에 매개변수 하나(`&mut guess`)를 넘기고 있습니다.

[read_line]: ../std/io/struct.Stdin.html#method.read_line
[method]: methods.html

위에서 `guess`를 어떻게 결합하는지 기억하고 계신가요? 우리는 이게 변경 가능하다고 말했었습니다. 그러나, `read_line`은 `String`을 매개변수로 취하지 않고, 대신 `&mut String`을 취합니다. Rust는 '[참조][references]'라고 부르는 기능을 가지고 있습니다. 이 기능은 하나의 데이터 조각에 대해 여러 개의 참조를 가질 수 있도록 해서, 복사 회수를 줄일 수 있습니다. Rust의 주요 특장점 중 하나가 레퍼런스를 쉽고 안전하게 사용할 수 있다는 점인 것처럼, 참조는 복잡한 기능입니다. 그러나 우리 프로그램을 마치기 위해서 자세한 내용들을 알아야 할 필요는 없습니다. 지금으로서는, 우리가 알아야 할 것은 `let` 결합처럼, 참조는 기본적으로 변경 불가능하다는 것입니다. 따라서, 우리는 `&guess` 대신 `&mut guess`를 써야 합니다.

`read_line()`이 문자열에 대한 변경할 수 있는 참조를 취하는 이유는 무엇일까요? 이 함수의 역할은 사용자가 표준 입력에 넣은 것을 가져다가 문자열 안쪽에 놓는 것입니다. 따라서 이 함수는 문자열을 매개변수로 받아서 거기에 입력을 더해야 하므로 참조는 변경 가능해야 합니다.


[references]: references-and-borrowing.html

그러나 아직도 이 코드에서 보아야 할 것이 남아 있습니다. 단 한 줄으로 이뤄져 있지만, 이 코드에 담긴 논리의 첫 부분에 지나지 않습니다.

```rust,ignore
.ok()
.expect("Failed to read line");
```

`.foo()` 문법으로 메서드를 호출하려고 할 때, 여러분은 새 줄을 만들거나 다른 공백 문자를 사용하게 될지도 모릅니다. 이렇게 함으로써 길이가 아주 긴 코드를 여러 개로 나눌 수 있습니다. 우리는 다음과 같이 _할 수도_ 있었습니다.

```rust,ignore
io::stdin().read_line(&mut guess).ok().expect("failed to read line");
```

하지만 이러면 읽기가 어렵습니다. 그래서 우리는 세 개의 메서드 호출을 세 줄에 나누어 쓴 것입니다. 지금까지 앞에서 `read_line()`에 대해서 말했습니다. 그러나 대체 `ok()`와 `expect()`는 뭘까요? 뭐, 우리는 `read_line()`이 사용자의 입력을 우리가 넘긴 `&mut String`에 넣는다고 했었습니다. 그러나 이 함수도 값을 하나 반환합니다. 이 경우에 반환값은 [`io::Result`][ioresult]가 됩니다. Rust의 표준 라이브러리에는 `Result`라는 이름의 타입이 여럿 있는데, 일반적인 버전의 [`Result`][result]와 `io::Result` 같은 종속 라이브러리들에 대한 특화된 버전들이 있습니다.

[ioresult]: ../std/io/type.Result.html
[result]: ../std/result/enum.Result.html

이러한 `Result` 타입들의 목적은 오류 처리 정보를 기록하는 것입니다. 여느 타입들과 마찬가지로 `Result` 타입의 값들은 그 타입에 대해 정의된 메서드를 가지고 있습니다. 예컨대 `io::Result`에는 `ok()` 메서드가 있습니다. 이 메서드가 말하고자 하는 바는 '나는 이 값이 성공적인 것이라고 가정하려 한다'는 뜻입니다. 만약 그렇지 않다면, 이 메서드는 오류 정보를 그냥 던져버립니다. 어째서 던져버리냐고요? 뭐, 기초적인 프로그램이기 때문에 그냥 일반적인 오류를 출력하고 싶거든요. 어떠한 문제든 기본적으로는 더 진행할 수가 없다는 것을 의미하기 때문입니다. 이 [`ok()` 메서드][ok]는 또 다른 메서드 `expect()`가 정의된 다른 값을 반환합니다. 이 [`expect()` 메서드][expect]는 자신이 호출된 값이 성공적인 것이 아니라면, 여러분이 넘긴 메시지를 가지고 [`panic!`][panic]을 호출합니다. 이런 `panic!`은 우리가 만든 프로그램이 메시지를 출력하고 나서 기능을 멈추도록 만듭니다.


[ok]: ../std/result/enum.Result.html#method.ok
[expect]: ../std/option/enum.Option.html#method.expect
[panic]: error-handling.html

만약 이 두 개의 메서드를 떼어낸다면, 우리 프로그램은 컴파일이 되겠지만 다음과 같은 경고가 나오게 됩니다.

```bash
$ cargo build
Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game)
src/main.rs:10:5: 10:39 warning: unused result which must be used,
#[warn(unused_must_use)] on by default
src/main.rs:10 io::stdin().read_line(&mut guess);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
```

Rust가 우리에게 사용되지 않은 `Result` 값이 있다고 경고합니다. 이 경고는 `io::Result`가 가지고 있는 특별한 참고용 주석_annotation_으로부터 왔습니다. Rust는 발생할 수 있지만 여러분이 처리하지 않은 에러에 대해 말하려고 시도합니다. 이러한 오류를 숨기기 위한 올바른 방법은 실제로 에러 처리 코드를 작성하는 것입니다. 다행히도 문제가 있을 때 그냥 동작을 멈추고 싶다면 위의 두 메서드를 사용하면 됩니다. 만약 어떤 방식으로든 오류로부터 복구하고 싶다면 다른 무언가를 하게 될 테지만, 그것은 나중의 프로젝트로 미루도록 하겠습니다.

이제 첫 예제의 마지막 줄이 남았습니다.

```rust,ignore
println!("You guessed: {}", guess);
}
```

우리가 입력을 저장했던 문자열을 출력합니다. `{}`는 자리 표시자입니다. 그리고 우리는 거기에 `guess`를 매개 변수로 넘깁니다. 혹시 여러 개의 `{}`가 있다면, 다음처럼 여러 개의 매개 변수를 넘기게 될 것입니다.

```rust
let x = 5;
let y = 10;

println!("x and y: {} and {}", x, y);
```

쉽군요.

어쨌든 그렇습니다. `cargo run`을 통해 지금까지 한 것을 실행할 수 있습니다.

```bash
$ cargo run
Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game)
Running `target/debug/guessing_game`
Guess the number!
Please input your guess.
6
You guessed: 6
```

좋습니다! 이제 첫 번째 부분은 끝났습니다. 이제 우리는 키보드로부터 입력을 받고, 그걸 다시 출력할 수 있습니다.


# 숨김수 생성하기

이제 우리는 숨김수를 만들어야 합니다. Rust는 아직 표준 라이브러리에 난수 기능을 포함하고 있지 않습니다. 그러나 Rust 팀은 [`rand` 크레이트][randcrate]를 제공합니다. '크레이트'는 Rust 코드의 패키지입니다. 우리는 지금까지 실행 가능한 '바이너리 크레이트'를 만들고 있었습니다. 반면에 `rand`는 '라이브러리 크레이트'입니다. 라이브러리 크레이트는 다른 프로그램들이 사용하도록 의도된 코드들을 담고 있습니다.

[randcrate]: https://crates.io/crates/rand

외부 크레이트를 사용할 때야말로 Cargo가 빛을 보는 때입니다. 우리가 `rand`를 쓰는 코드를 작성하기 전에, `Cargo.toml`을 수정해야 합니다. 다음 몇 줄을 파일의 뒤에 추가하세요.

```toml
[dependencies]

rand="0.3.0"
```

`Cargo.toml` 파일의 `[dependencies]` 절은 `[package]` 절과 비슷합니다. 다음 절이 시작하기 전까지 등장하는 것들이 그 일부분입니다. Cargo는 외부 크레이트에 대한 의존성 여부와 필요한 버전을 알기 위해 dependencies 절을 사용합니다. 이 경우 우리는 `0.3.0`을 사용했습니다. Cargo는 버전 번호를 쓰는 표준적인 방법인 [의미적 버전 매기기][semver]를 이해합니다. 만약 최신 버전을 사용하고 싶다면 `*`를 이용할 수 있고, 사용할 버전의 범위를 적을 수도 있습니다. 더 자세한 정보를 위해서는 [Cargo 문서][cargodoc]을 보시기 바랍니다.

[semver]: http://semver.org
[cargodoc]: http://doc.crates.io/crates-io.html

이제 우리 프로젝트를 빌드해 봅시다.

```bash
$ cargo build
Updating registry `https://github.com/rust-lang/crates.io-index`
Downloading rand v0.3.8
Downloading libc v0.1.6
Compiling libc v0.1.6
Compiling rand v0.3.8
Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game)
```

(물론 다른 버전을 보실 수도 있습니다.)

새로운 출력이 많군요! 이제 우리는 외부 의존성을 가지고 있고, Cargo는 [Crates.io][cratesio] 데이터의 사본인 레지스트리로부터 최신 버전들을 가져옵니다. Crates.io는 Rust 생태계에 속한 사람들이 자신들의 오픈 소스 프로젝트를 다른 이들이 사용할 수 있도록 올리는 곳입니다.

[cratesio]: https://crates.io

레지스트리를 업데이트한 다음, Cargo는 우리 `[dependencies]`를 확인하고, 아직 가지고 있지 않은 것들을 내려받습니다. 지금 우리는 `rand`에만 의존하고 싶다고 말했지만 `libc`의 사본 또한 가져왔습니다. 그 이유는 `rand`의 동작이 `libc`에 의존하기 때문입니다. Cargo는 이들을 내려받아 컴파일하고, 다음으로 우리 프로젝트를 컴파일합니다.

`cargo build`를 다시 실행하면, 이번에는 다른 출력을 얻습니다.

```bash
$ cargo build
```

맞습니다. 출력이 없군요! Cargo는 우리 프로젝트가 이미 빌드되었고, 프로젝트가 의존하고 있는 모든 것이 빌드되어 있음을 알고 있습니다. 따라서 그것들을 다시 수행할 이유가 없고, 이제 할 것이 없으므로 그냥 종료합니다. 만약 `src/main.rs`를 다시 열어서 약간 수정하고 다시 저장한다면 다음 한 줄을 보게 될 것입니다.

```bash
$ cargo build
Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game)
```

우리는 Cargo에게 `rand`의 `0.3.x`버전이라면 뭐든지 좋다고 말했으므로, Cargo는 이 글이 쓰이는 시점에서 최신 버전인 `v0.3.8`을 가져옵니다. 그러나 만약 중요한 버그 수정을 위해 다음 주에 `v0.3.9`가 나온다면 어떻게 될까요? 버그 수정은 중요하지만, 만약 `0.3.9`가 우리 코드를 깨지게 만드는 수정 내용을 가지고 있다면 어떨까요?

이 문제의 답은 `Cargo.lock` 파일입니다. 이 파일은 여러분의 프로젝트 디렉터리에서 찾을 수 있습니다. 프로젝트를 처음 빌드할 때 Cargo는 여러분의 조건에 맞는 모든 버전을 계산하고, 그것을 `Cargo.lock` 파일에 적습니다. 나중에 여러분의 프로젝트를 다시 빌드하면, Cargo는 `Cargo.lock` 파일이 존재하는 것을 보고, 새로 버전을 확인하기보다는 거기에 적혀 있는 버전을 사용합니다. 이로 인해 여러분은 자동적으로 빌드를 반복할 수 있습니다. 무슨 말이냐면, lock 파일 덕분에 우리는 명시적으로 업그레이드하기 전까지는 `0.3.8` 버전에 머무른다는 말이죠. 그리고 우리 코드를 공유하는 다른 모든 사람들 또한 그렇습니다.

`v0.3.9`를 사용하고 싶다면 어떻게 _해야_ 할까요? Cargo는 `update`라는 또 다른 명령어를 갖고 있습니다. 이것은 'lock을 무시하고, 우리가 명세한 것에 들어맞는 최신 버전을 찾아내어, 있다면 lock 파일에 그 버전을 기록하라'는 의미입니다. 그렇지만 Cargo는 기본적으로 `0.3.0`보다 크고 `0.4.0`보다 작은 버전만을 찾습니다. 만약 `0.4.x`로 옮기고 싶다면, 우리는 `Cargo.toml`을 직접 수정해야 할 것입니다. 그렇게 한 후에 `Cargo build`를 실행하면, Cargo는 우리의 `rand` 요구사항을 다시 평가하여 색인을 갱신할 것입니다.

[Cargo][doccargo]와 [그 생태계][doccratesio]에 대해서는 할 말이 많지만, 지금 필요한 것은 모두 설명했습니다. Cargo는 라이브러리 재사용을 매우 쉽게 만들기 때문에, Rust인들은 많은 부패키지를 조립한 작은 프로젝트를 작성하는 경향이 있습니다.

[doccargo]: http://doc.crates.io
[doccratesio]: http://doc.crates.io/crates-io.html

이제 실제로 `rand`를 _사용해_ 봅시다.

```rust,ignore
extern crate rand;

use std::io;
use rand::Rng;

fn main() {
println!("Guess the number!");

let secret_number = rand::thread_rng().gen_range(1, 101);

println!("The secret number is: {}", secret_number);

println!("Please input your guess.");

let mut guess = String::new();

io::stdin().read_line(&mut guess)
.ok()
.expect("failed to read line");

println!("You guessed: {}", guess);
}
```

가장 먼저 첫 번째 줄을 바꿨습니다. 이제 `extern crate rand` 라고 되어 있군요. 우리의 `[dependencies]`에 `rand`를 선언했기 때문에, Rust에게 우리가 이것을 사용하겠다고 알리기 위해 `extern crate`를 사용할 수 있습니다. 이 명령은 동시에 `use rand`와 같은 역할을 수행하기 때문에, 우리는 `rand` 크레이트 내부의 어떤 것이든 `rand::`라는 접두어를 붙여 사용할 수 있습니다.

다음으로, 우리는 또 다른 `use` 라인을 추가했습니다. 그 내용은 `use rand::Rng`입니다. 어떤 메서드 하나를 잠시 사용할 건데, 이 메서드는 `Rng`가 스코프 내에 있어야 사용할 수 있습니다. 기본적인 아이디어는 이것입니다. 메서드들은 '특성'이라고 불리는 무언가 위에 정의됩니다. 그리고 이 메서드가 동작하기 위해서는, 그 특성이 스코프 내에 있어야 합니다. 더 자세한 내용이 필요하면 [특성][traits] 절을 읽어 주세요.


[traits]: traits.html

중간쯤에 우리가 추가한 또 다른 두 줄이 있습니다.

```rust,ignore
let secret_number = rand::thread_rng().gen_range(1, 101);

println!("The secret number is: {}", secret_number);
```

난수 발생기의 사본을 하나 얻기 위해 `rand::thread_rng()` 함수를 사용했습니다. 이 난수 발생기는 우리가 현재 실행하고 있는 특정한 [스레드][concurrency]에 대해 하나씩 존재합니다. 위에서 `use rand::Rng`를 적었기 때문에, `gen_range()` 메서드를 사용할 수 있습니다. 이 메서드는 두 개의 인자를 받아서, 그 사이의 수를 생성합니다. 이 메서드는 하한값은 포함하지만, 상한값은 포함하지 않습니다. 따라서 우리는 1부터 100 사이의 수를 생성하기 위해 `1`과 `101`을 사용해야 합니다.

[concurrency]: concurrency.html

The second line just prints out the secret number. This is useful while
we’re developing our program, so we can easily test it out. But we’ll be
deleting it for the final version. It’s not much of a game if it prints out
the answer when you start it up!

Try running our new program a few times:
두 번째 줄은 단지 비밀수를 출력합니다. 이 부분은 프로그램을 개발하는 동안 테스트하기가 쉬워지기 때문에 쓸모가 있습니다. 그러나, 최종본에서는 이 부분을 삭제할 것입니다. 시작할 때 답을 출력해 버리면 게임이 되지 않으니까요!

새 프로그램을 몇 번 시험해 봅시다.


```bash
$ cargo run
Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game)
Running `target/debug/guessing_game`
Guess the number!
The secret number is: 7
Please input your guess.
4
You guessed: 4
$ cargo run
Running `target/debug/guessing_game`
Guess the number!
The secret number is: 83
Please input your guess.
5
You guessed: 5
```

Great! Next up: let’s compare our guess to the secret guess.

# Comparing guesses

Now that we’ve got user input, let’s compare our guess to the random guess.
Here’s our next step, though it doesn’t quite work yet:
잘 되는군요! 다음으로는 우리의 추측과 비밀수를 비교해 봅시다.

# 추측 비교하기

이제 사용자의 입력을 받았으니, 우리의 추측을 난수와 비교해 봅시다. 다음이 그 단계이지만, 아직 잘 작동하지는 않습니다.


```rust,ignore
extern crate rand;

use std::io;
use std::cmp::Ordering;
use rand::Rng;

fn main() {
println!("Guess the number!");

let secret_number = rand::thread_rng().gen_range(1, 101);

println!("The secret number is: {}", secret_number);

println!("Please input your guess.");

let mut guess = String::new();

io::stdin().read_line(&mut guess)
.ok()
.expect("failed to read line");

println!("You guessed: {}", guess);

match guess.cmp(&secret_number) {
Ordering::Less => println!("Too small!"),
Ordering::Greater => println!("Too big!"),
Ordering::Equal => println!("You win!"),
}
}
```

A few new bits here. The first is another `use`. We bring a type called
`std::cmp::Ordering` into scope. Then, five new lines at the bottom that use
it:
새로운 것들이 약간 들어가 있군요. 그 첫번째는 또 다른 `use`입니다. `std::cmp::Ordering`이라는 타입 하나를 스코프 안으로 가져왔습니다. 그 다음은 아래쪽에서 그걸 사용하고 있는 다섯 줄의 새 라인입니다.

```rust,ignore
match guess.cmp(&secret_number) {
Ordering::Less => println!("Too small!"),
Ordering::Greater => println!("Too big!"),
Ordering::Equal => println!("You win!"),
}
```

The `cmp()` method can be called on anything that can be compared, and it
takes a reference to the thing you want to compare it to. It returns the
`Ordering` type we `use`d earlier. We use a [`match`][match] statement to
determine exactly what kind of `Ordering` it is. `Ordering` is an
[`enum`][enum], short for ‘enumeration’, which looks like this:

```rust
enum Foo {
Bar,
Baz,
}
```

[match]: match.html
[enum]: enums.html

With this definition, anything of type `Foo` can be either a
`Foo::Bar` or a `Foo::Baz`. We use the `::` to indicate the
namespace for a particular `enum` variant.

The [`Ordering`][ordering] enum has three possible variants: `Less`, `Equal`,
and `Greater`. The `match` statement takes a value of a type, and lets you
create an ‘arm’ for each possible value. Since we have three types of
`Ordering`, we have three arms:
`cmp()` 메서드는 비교될 수 있는 모든 것에서 호출이 가능합니다. 그리고 이 메서드는 여러분이 비교하고자 하는 어떤 것의 레퍼런스를 취합니다. 또 이 메서드는 우리가 앞에서 `use`한 `Ordering` 타입을 반환합니다. 우리는 `Ordering` 중에서 정확히 어떤 것인지를 확실히 알아내기 위해서 [`match`][match] 구문을 사용합니다. `Ordering`은 [`enum`][enum]입니다. 그리고 enum은 열거형(enumeration)의 준말이고, 다음과 같이 생겼습니다.

```rust
enum Foo {
Bar,
Baz,
}
```

[match]: match.html
[enum]: enums.html

이 정의에서, `Foo` 타임의 어떤 것은 `Foo::Bar` 또는 `Foo::Baz`가 될 수 있습니다. `::`는 특정한 `enum` 변형을 위한 네임스페이스를 나타내는 용도입니다.

[`Ordering`][ordering] enum은 `Less`와 `Equal`, `Greater`의 세 가지 변형을 가지고 있습니다. `match` 구문은 어떤 타입의 어떤 값을 취해서, 가능한 값들 각각에 대해서 '가지'를 만들도록 합니다. 세 가지 종류의 `Ordering`이 있기 때문에, 가지도 세 갈래입니다.


```rust,ignore
match guess.cmp(&secret_number) {
Ordering::Less => println!("Too small!"),
Ordering::Greater => println!("Too big!"),
Ordering::Equal => println!("You win!"),
}
```

[ordering]: ../std/cmp/enum.Ordering.html

If it’s `Less`, we print `Too small!`, if it’s `Greater`, `Too big!`, and if
`Equal`, `You win!`. `match` is really useful, and is used often in Rust.

I did mention that this won’t quite work yet, though. Let’s try it:
만약 `Less`라면 우리는 `Too small!`을 출력합니다. 만약 `Greater`라면 `Too big`을 출력합니다. 그리고 `Equal`일 때는 `You win`을 출력합니다. `match`는 정말로 유용하며 Rust에서 자주 사용합니다.

그렇지만 아직 잘 동작하지 않는다고 언급했었죠. 시험해 봅시다.


```bash
$ cargo build
Compiling guessing_game v0.1.0 (file:///home/you/projects/guessing_game)
src/main.rs:28:21: 28:35 error: mismatched types:
expected `&collections::string::String`,
found `&_`
(expected struct `collections::string::String`,
found integral variable) [E0308]
src/main.rs:28 match guess.cmp(&secret_number) {
^~~~~~~~~~~~~~
error: aborting due to previous error
Could not compile `guessing_game`.
```

Whew! This is a big error. The core of it is that we have ‘mismatched types’.
Rust has a strong, static type system. However, it also has type inference.
When we wrote `let guess = String::new()`, Rust was able to infer that `guess`
should be a `String`, and so it doesn’t make us write out the type. And with
our `secret_number`, there are a number of types which can have a value
between one and a hundred: `i32`, a thirty-two-bit number, or `u32`, an
unsigned thirty-two-bit number, or `i64`, a sixty-four-bit number. Or others.
So far, that hasn’t mattered, and so Rust defaults to an `i32`. However, here,
Rust doesn’t know how to compare the `guess` and the `secret_number`. They
need to be the same type. Ultimately, we want to convert the `String` we
read as input into a real number type, for comparison. We can do that
with three more lines. Here’s our new program:

```rust,ignore
extern crate rand;

use std::io;
use std::cmp::Ordering;
use rand::Rng;

fn main() {
println!("Guess the number!");

let secret_number = rand::thread_rng().gen_range(1, 101);

println!("The secret number is: {}", secret_number);

println!("Please input your guess.");

let mut guess = String::new();

io::stdin().read_line(&mut guess)
.ok()
.expect("failed to read line");

let guess: u32 = guess.trim().parse()
.ok()
.expect("Please type a number!");

println!("You guessed: {}", guess);

match guess.cmp(&secret_number) {
Ordering::Less => println!("Too small!"),
Ordering::Greater => println!("Too big!"),
Ordering::Equal => println!("You win!"),
}
}
```

The new three lines:

```rust,ignore
let guess: u32 = guess.trim().parse()
.ok()
.expect("Please type a number!");
```

Wait a minute, I thought we already had a `guess`? We do, but Rust allows us
to ‘shadow’ the previous `guess` with a new one. This is often used in this
exact situation, where `guess` starts as a `String`, but we want to convert it
to an `u32`. Shadowing lets us re-use the `guess` name, rather than forcing us
to come up with two unique names like `guess_str` and `guess`, or something
else.

We bind `guess` to an expression that looks like something we wrote earlier:

```rust,ignore
guess.trim().parse()
```

Followed by an `ok().expect()` invocation. Here, `guess` refers to the old
`guess`, the one that was a `String` with our input in it. The `trim()`
method on `String`s will eliminate any white space at the beginning and end of
our string. This is important, as we had to press the ‘return’ key to satisfy
`read_line()`. This means that if we type `5` and hit return, `guess` looks
like this: `5¶
`. The `¶
` represents ‘newline’, the enter key. `trim()` gets
rid of this, leaving our string with just the `5`. The [`parse()` method on
strings][parse] parses a string into some kind of number. Since it can parse a
variety of numbers, we need to give Rust a hint as to the exact type of number
we want. Hence, `let guess: u32`. The colon (`:`) after `guess` tells Rust
we’re going to annotate its type. `u32` is an unsigned, thirty-two bit
integer. Rust has [a number of built-in number types][number], but we’ve
chosen `u32`. It’s a good default choice for a small positive number.

[parse]: ../std/primitive.str.html#method.parse
[number]: primitive-types.html#numeric-types

Just like `read_line()`, our call to `parse()` could cause an error. What if
our string contained `A👍%`? There’d be no way to convert that to a number. As
such, we’ll do the same thing we did with `read_line()`: use the `ok()` and
`expect()` methods to crash if there’s an error.

Let’s try our program out!

```bash
$ cargo run
Compiling guessing_game v0.0.1 (file:///home/you/projects/guessing_game)
Running `target/guessing_game`
Guess the number!
The secret number is: 58
Please input your guess.
76
You guessed: 76
Too big!
```

Nice! You can see I even added spaces before my guess, and it still figured
out that I guessed 76. Run the program a few times, and verify that guessing
the number works, as well as guessing a number too small.

Now we’ve got most of the game working, but we can only make one guess. Let’s
change that by adding loops!

# Looping

The `loop` keyword gives us an infinite loop. Let’s add that in:

```rust,ignore
extern crate rand;

use std::io;
use std::cmp::Ordering;
use rand::Rng;

fn main() {
println!("Guess the number!");

let secret_number = rand::thread_rng().gen_range(1, 101);

println!("The secret number is: {}", secret_number);

loop {
println!("Please input your guess.");

let mut guess = String::new();

io::stdin().read_line(&mut guess)
.ok()
.expect("failed to read line");

let guess: u32 = guess.trim().parse()
.ok()
.expect("Please type a number!");

println!("You guessed: {}", guess);

match guess.cmp(&secret_number) {
Ordering::Less => println!("Too small!"),
Ordering::Greater => println!("Too big!"),
Ordering::Equal => println!("You win!"),
}
}
}
```

And try it out. But wait, didn’t we just add an infinite loop? Yup. Remember
our discussion about `parse()`? If we give a non-number answer, we’ll `return`
and quit. Observe:

```bash
$ cargo run
Compiling guessing_game v0.0.1 (file:///home/you/projects/guessing_game)
Running `target/guessing_game`
Guess the number!
The secret number is: 59
Please input your guess.
45
You guessed: 45
Too small!
Please input your guess.
60
You guessed: 60
Too big!
Please input your guess.
59
You guessed: 59
You win!
Please input your guess.
quit
thread '
' panicked at 'Please type a number!'
```

Ha! `quit` actually quits. As does any other non-number input. Well, this is
suboptimal to say the least. First, let’s actually quit when you win the game:

```rust,ignore
extern crate rand;

use std::io;
use std::cmp::Ordering;
use rand::Rng;

fn main() {
println!("Guess the number!");

let secret_number = rand::thread_rng().gen_range(1, 101);

println!("The secret number is: {}", secret_number);

loop {
println!("Please input your guess.");

let mut guess = String::new();

io::stdin().read_line(&mut guess)
.ok()
.expect("failed to read line");

let guess: u32 = guess.trim().parse()
.ok()
.expect("Please type a number!");

println!("You guessed: {}", guess);

match guess.cmp(&secret_number) {
Ordering::Less => println!("Too small!"),
Ordering::Greater => println!("Too big!"),
Ordering::Equal => {
println!("You win!");
break;
}
}
}
}
```

By adding the `break` line after the `You win!`, we’ll exit the loop when we
win. Exiting the loop also means exiting the program, since it’s the last
thing in `main()`. We have just one more tweak to make: when someone inputs a
non-number, we don’t want to quit, we just want to ignore it. We can do that
like this:

```rust,ignore
extern crate rand;

use std::io;
use std::cmp::Ordering;
use rand::Rng;

fn main() {
println!("Guess the number!");

let secret_number = rand::thread_rng().gen_range(1, 101);

println!("The secret number is: {}", secret_number);

loop {
println!("Please input your guess.");

let mut guess = String::new();

io::stdin().read_line(&mut guess)
.ok()
.expect("failed to read line");

let guess: u32 = match guess.trim().parse() {
Ok(num) => num,
Err(_) => continue,
};

println!("You guessed: {}", guess);

match guess.cmp(&secret_number) {
Ordering::Less => println!("Too small!"),
Ordering::Greater => println!("Too big!"),
Ordering::Equal => {
println!("You win!");
break;
}
}
}
}
```

These are the lines that changed:

```rust,ignore
let guess: u32 = match guess.trim().parse() {
Ok(num) => num,
Err(_) => continue,
};
```

This is how you generally move from ‘crash on error’ to ‘actually handle the
error’, by switching from `ok().expect()` to a `match` statement. The `Result`
returned by `parse()` is an enum just like `Ordering`, but in this case, each
variant has some data associated with it: `Ok` is a success, and `Err` is a
failure. Each contains more information: the successful parsed integer, or an
error type. In this case, we `match` on `Ok(num)`, which sets the inner value
of the `Ok` to the name `num`, and then we just return it on the right-hand
side. In the `Err` case, we don’t care what kind of error it is, so we just
use `_` instead of a name. This ignores the error, and `continue` causes us
to go to the next iteration of the `loop`.

Now we should be good! Let’s try:

```bash
$ cargo run
Compiling guessing_game v0.0.1 (file:///home/you/projects/guessing_game)
Running `target/guessing_game`
Guess the number!
The secret number is: 61
Please input your guess.
10
You guessed: 10
Too small!
Please input your guess.
99
You guessed: 99
Too big!
Please input your guess.
foo
Please input your guess.
61
You guessed: 61
You win!
```

Awesome! With one tiny last tweak, we have finished the guessing game. Can you
think of what it is? That’s right, we don’t want to print out the secret
number. It was good for testing, but it kind of ruins the game. Here’s our
final source:

```rust,ignore
extern crate rand;

use std::io;
use std::cmp::Ordering;
use rand::Rng;

fn main() {
println!("Guess the number!");

let secret_number = rand::thread_rng().gen_range(1, 101);

loop {
println!("Please input your guess.");

let mut guess = String::new();

io::stdin().read_line(&mut guess)
.ok()
.expect("failed to read line");

let guess: u32 = match guess.trim().parse() {
Ok(num) => num,
Err(_) => continue,
};

println!("You guessed: {}", guess);

match guess.cmp(&secret_number) {
Ordering::Less => println!("Too small!"),
Ordering::Greater => println!("Too big!"),
Ordering::Equal => {
println!("You win!");
break;
}
}
}
}
```

# Complete!

At this point, you have successfully built the Guessing Game! Congratulations!

This first project showed you a lot: `let`, `match`, methods, associated
functions, using external crates, and more. Our next project will show off
even more.