이 시리즈는 Rust 공식문서를 통해 공부한 흔적임을 밝힙니다.
Hello, world!
를 출력하는 것만으로는 Rust 프로그래밍을 해봤다고 하기 애매하다.
따라서 우리는 유의미하게 동작하는 프로그램을 직접 작성해보며
Rust 프로그래밍을 간단히 맛보는 시간을 갖도록 하겠다.
단순히 맛보기일 뿐이며, 아직 배우지 않은 내용을 다루고 있으므로
모든 것을 이해하고 넘어가려고 하기 보다는
Rust 프로젝트의 전체적인 구성을 훑어본다는 느낌으로 나아가자.프로젝트-관리
코드에 대한 설명이 주를 이루어 매우 길어 보이겠지만 겁먹지 말자.
이건 단지 호기심을 불러일으키고 동기부여를 하는 내용이다.
우리는 이 시간에 숫자 맛히기 게임을 구현할 것이다.
숫자 맛히기 게임 Guessing Game
- 1과 100 사이의 임의의 정수, 난수값을 생성한다.
- 플레이어가 어떤 값을 예상했는지 묻고 플레이어는 예측값을 입력한다.
- 플레이어의 예측값과 생성된 난수값을 비교하여 비교 결과를 알려준다.
- 플레이어의 예측값이 생성된 난수값과 일치하면 축하 메시지를 출력 후 종료한다.
⚠️ 본 게시물의 예제는 오래된 버전의 코드를 포함합니다!
게시물 작성 시점의rand
크레이트의 최신 버전은 0.7.3 으로,
다음과 같이 난수를 생성했던 반면,
let secret_number = rand::thread_rng().gen_range(1, 101);
2021년 7월 12일 기준rand
크레이트의 최신 버전은 0.8.4 으로,
다음과 같이 난수를 생성하도록 변경되었습니다.
let secret_number = rand::thread_rng().gen_range(1..101);
이를 제보해주신 fregataa 님께 감사드리며,
본 게시물을 보고 실습을 따라하고자 하시는 분은 최신 버전의rand
크레이트 사용 시
rand::thread_rng().gen_range
함수의 인자를 변경하여 진행해주시기 바랍니다.
― 2021.07.15 Edited
먼저, Cargo를 통해 새 프로젝트를 생성해야 한다.
숫자 맛히기 게임이니까 guessing_game
이라는 이름을 사용하겠다.
peter@hp-laptop:~/rust-practice$ mkdir chapter02
peter@hp-laptop:~/rust-practice$ cd chapter02
peter@hp-laptop:~/rust-practice/chapter02$ cargo new guessing_game
Created binary (application) `guessing_game` package
peter@hp-laptop:~/rust-practice/chapter02$ cd guessing_game
peter@hp-laptop:~/rust-practice/chapter02/guessing_game$
지난 시간에도 살펴봤듯이, Cargo.toml
과 src/main.rs
가 자동 생성되었다.
peter@hp-laptop:~/rust-practice/chapter02/guessing_game$ tree
.
├── Cargo.toml
└── src
└── main.rs
1 directory, 2 files
peter@hp-laptop:~/rust-practice/chapter02/guessing-game$
우리의 코드는 이 자동 생성된 src/main.rs
에 작성될 것이다.
한 번에 모든 것을 작성하기 보다는 조금씩 확장적으로 구현하도록 하겠다.
먼저, 플레이어가 어떤 값을 예상했는지 묻고
플레이어는 예측값을 입력한다. 에 해당하는 부분을 작성해보자.
src/main.rs
에 자동 생성된 코드를 지우고 다음과 같이 작성하면 된다.
// 당장은 이해를 못하더라도 따라 적어보는 것을 추천한다.
~/rust-practice/chapter02/guessing_game$ vi src/main.rs
src/main.rs
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) .expect("Fail to read line"); println!("You guessed: {}", guess); }
이 코드를 차근차근 해석해보자.
사용자의 입력을 받기 위해서는 표준 입력 함수가 필요한데
이것은 표준 라이브러리 std
의 입출력 라이브러리 io
에서 가져올 수 있다.
맨 첫번째 줄의 use std::io;
는 이를 위한 코드다.
Prelude에 포함되어 있는 자료형은 그냥 사용할 수 있지만
그렇지 않은 것들은 use
를 통해 가져와야 한다.
Prelude
모든 Rust 프로그램이 자동으로 가져오는 것들의 목록.
Rust는 모든 crate의 root에extern crate std;
을 추가하고
모든 module에use std::prelude::v1::*;
을 추가한다.
// crate과 module에 대한 건 일단 그런 게 있구나 하고 넘어가자.
std::prelude::v1
에 무엇이 들어있는지 궁금하다면 문서를 참고하자.
다음으로 보게 되는 것은 main
함수인데,
fn
키워드를 통해 함수를 선언할 수 있다는 것과 {}
에 본문이 들어간다는 것은 지난 시간에 이야기했다.
소괄호 ()
의 경우 매개변수가 존재한다면 그 안에 들어가지만
우리의 main
함수는 매개변수를 가지지 않아 비워두었다.
println!
이 문자열 출력을 위한 매크로라는 것도 지난 시간에 다루었으니 자세한 설명은 생략한다.
다음으로 우리는 let mut guess = String::new();
를 통해
변수를 저장하기 위한 공간을 마련한다.
Rust에서 변수는 let
키워드를 통해 선언한다.
Rust의 변수는 기본적으로 불변성을 가지고 있으며
mut
키워드로 가변성을 명시해주어야 그 값을 변경할 수 있는데
이에 대한 설명은 추후에 진행하겠다.
단지 우리 예제에서는 값의 변경이 필요해 mut
키워드를 사용했다는 것 정도만 알고 넘어가자.
=
는 우측값을 좌측값에 bind하겠다는 의미인데
guess
변수에 String::new
함수의 반환값을 bind한다는 것이다.
String
은 Prelude에 포함되어 있는, 표준 라이브러리가 제공하는 문자열 자료형이다.
이것은 길이 조절이 가능하며 UTF-8 형식으로 인코딩된 텍스트를 표현한다.
new
는 String
자료형에 구현되어 있는 함수로, 이런 함수를 연관 함수라고 부른다.
연관 함수에 대한 것도 나중에 다룰테니 일단 빈 문자열을 생성해서 guess
에 bind했다는 것만 이해하자.
이제 io
로 시작하는 조금 길어보이는 코드를 마주했다.
io
는 Prelude에 포함되어 있지 않아 우리가 use
를 통해 가져왔던 녀석이다.
그리고 stdin
은 방금 본 String::new
와 마찬가지로 io
의 연관 함수다.
사실 use
를 사용하지 않고 std::io::stdin
으로 사용할 수도 있지만
그럴 경우 코드가 복잡해질 수 있다는 건 여담.
io::stdin
는 터미널로부터 표준 입력을 받는 핸들의 인스턴스를 반환한다.
그리고 표준 입력 핸들의 메서드 read_line
을 통해 사용자가 입력한 값을 얻어올 수 있다.
얻어온 값은 read_line
의 인자로 전달된 변수에 저장된다.
read_line
에 의해 변경되기 때문에 그것의 인자는 가변성을 가지고 있어야 한다.
이것이 우리가 guess
변수에 가변성을 부여한 이유다.
&
는 값을 복사하지 않고 접근하기 위한 참조에 이용되며
참조는 기본적으로 불변성을 띄기 때문에 가변성을 갖고 참조하겠다는 의미에서
&mut guess
와 같이 인자를 전달한다.
나중에 더 자세히 배우겠지만 불변성을 띈 변수는 가변 참조가 안된다는 것은 여담.
io::std::Stdin
의 메서드 read_line
은 io::Result
자료형의 값을 반환한다.
io::Result
는 열거형으로, Ok
와 Err
두 가지 값을 가지고 있다.
작업이 성공적으로 완료되면 Ok
가 반환되며, 이것은 성공적으로 생성된 값을 가진다.
그렇지 않을 경우 Err
가 반환되며, 이것은 실패 원인에 대한 정보를 가진다.
이 녀석은 보통 예외처리를 하기 위해 사용된다.
io::Result
의 메서드 expect
는 그 인자값이 Ok
인지 Err
인지에 따라
Ok
라면 그것이 가진 성공적으로 생성된 값을 반환하고
Err
라면 프로그램을 종료하고 인자로 전달된 메시지를 출력한다.
우리 예제에서는 성공 시 표준 입력으로 입력된 문자열의 바이트 수를 반환하지만 사용하지 않는다.
Result
를 반환할 때 이것에 대한 예외처리를 해주지 않으면
컴파일은 되지만 이에 대한 경고가 출력될 것이다.
마지막으로, println!
매크로를 다시 만났는데 이 녀석은 지금까지 봤던 녀석들과 조금 다르다.
문자열에 {}
가 존재하며 문자열 외에 우리가 선언한 변수 guess
도 인자로 전달되었다.
{}
는 자리지정자placeholder로, 어떤 값이 들어갈 자리를 의미하며,
그곳에 들어갈 값은 문자열 뒤에 ,
를 사이에 두고 전달하면 된다.
자리지정자를 여러 개 사용할 경우 그 순서에 맞게 ,
를 사이에 두고 열거하면 된다.
우리가 작성한 코드를 전체적으로 이해했으니 이제 한 번 실행해보자.
peter@hp-laptop:~/rust-practice/chapter02/guessing_game$ cargo run
Compiling guessing_game v0.1.0 (/home/peter/rust-practice/chapter02/guessing_game)
Finished dev [unoptimized + debuginfo] target(s) in 0.20s
Running `target/debug/guessing_game`
Guess the number!
Please input your guess.
78
You guessed: 78
peter@hp-laptop:~/rust-practice/chapter02/guessing_game$
Please input your guess.
가 출력되면 우리가 어떤 값을 입력할 때까지 대기할 것이고
우리가 어떤 값을 입력하면 마저 실행된다.
이번에는 1과 100 사이의 임의의 정수,
난수값을 생성한다. 에 해당하는 부분을 작성해보자.
난수 생성은 Rust의 표준 라이브러리에서는 지원하지 않지만
Rust 팀이 제공하는 rand
크레이트를 사용하면 이러한 기능을 사용할 수 있다.
크레이트crate는 라이브러리 또는 바이너리 소스 파일의 집합이라고만 알아두자.
안에 들어 있는 소스 코드를 가져다 쓸 수 있는 라이브러리 크레이트와
main
함수가 있어 실행 가능한 바이너리 크레이트가 존재하는데
rand
크레이트는 라이브러리 크레이트에 해당한다.
우리가 작성하고 있는 guessing_game
도 크레이트다, 바이너리 크레이트.
rand
크레이트와 같은 외부 크레이트를 사용하려면
Cargo.toml
에 그것을 의존 패키지로 등록해주어야 한다.
Cargo.toml
의 [dependencies]
아래에 의존 패키지를 추가할 수 있다.
의존 패키지 이름과 그것의 시멘틱 버전을 입력한다.
~/rust-practice/chapter02/guessing_game$ vi Cargo.toml
Cargo.toml
[package] name = "guessing_game" version = "0.1.0" authors = ["Peter J <peter.j@kakao.com>"] edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] rand = "0.7.3"
이제 이 프로젝트에서는 rand
크레이트 0.7.3 버전을 사용할 수 있다.
이 상태로 cargo build
를 수행하면 rand
크레이트에 필요한 것들이
0.7.3 버전과 호환되는 버전으로 다운로드된다.
Cargo는 현재 프로젝트에 아직 다운로드 되지 않은 것만 다운로드하므로
최초에 한 번만 다운로드 할 것이다.
peter@hp-laptop:~/rust-practice/chapter02/guessing_game$ cargo build
Compiling autocfg v0.1.7
Compiling rand_core v0.4.2
Compiling libc v0.2.74
Compiling rand_core v0.3.1
Compiling rand_jitter v0.1.4
Compiling rand_hc v0.1.0
Compiling rand_xorshift v0.1.1
Compiling rand_isaac v0.1.1
Compiling rand_chacha v0.1.1
Compiling rand_pcg v0.1.2
Compiling rand v0.6.5
Compiling rand_os v0.1.3
Compiling guessing_game v0.1.0 (/home/peter/rust-practice/chapter02/guessing_game)
Finished dev [unoptimized + debuginfo] target(s) in 2.76s
peter@hp-laptop:~/rust-practice/chapter02/guessing_game$
cargo build
가 처음 실행되었을 때 이 연관된 패키지들의 버전이 Cargo.lock
에 기록되는데
우리는 Cargo.lock
으로 인해 의존 패키지가 업데이트되었을 때
업데이트 버전이 우리 프로젝트와 호환되지 않더라도 기존 버전을 유지하며 사용할 수 있다.
Cargo.toml
에 지정된 조건에 맞는 가장 최신 버전을 사용하고 싶다면
다음 명령어를 통해 업데이트하여 Cargo.lock
을 갱신할 수 있다.
~/rust-practice/chapter02/guessing_game$ cargo update
Cargo에 대한 더 자세한 이야기는 나중으로 미루고 난수 생성으로 돌아오자.
~/rust-practice/chapter02/guessing_game$ vi src/main.rs
src/main.rs
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) .expect("Fail to read line"); println!("You guessed: {}", guess); }
난수 생성을 위해 use rand::Rng;
가 추가되었다.
이것은 난수 생성기에 구현된 메서드를 정의하는 트레이트trait인데
이 녀석을 가져와야 해당 메서드를 사용할 수 있다는 것만 알고 넘어가자.
트레이트에 대한 건 추후에 제대로 다룰 예정이다.
let secret_number = rand::thread_rng().gen_range(1, 101);
에서 난수를 생성한다.
rand::thread_rng()
은 난수 생성기를 반환하며
난수 생성기의 메서드 gen_range
에 전달한 인자 범위의 정수값이 secret_number
에 bind된다.
범위는 첫번째 인자 이상 두번째 인자 미만으로 정해진다.
앞에서 use rand::Rng;
을 해주지 않으면 이 gen_range
를 사용할 수 없게 된다.
난수를 생성할 땐 시드 값이 필요한데 Rust의 난수 생성기는 운영체제로부터 시드 값을 받는다.
그리고 나중에 삭제하겠지만 난수가 잘 생성되었는지 확인하기 위한
println!("The secret number is: {}", secret_number);
가 작성되었다.
이제 실행해보면 난수가 생성되는 것을 확인할 수 있다.
peter@hp-laptop:~/rust-practice/chapter02/guessing_game$ cargo run
Compiling guessing_game v0.1.0 (/home/peter/rust-practice/chapter02/guessing_game)
Finished dev [unoptimized + debuginfo] target(s) in 0.24s
Running `target/debug/guessing_game`
Guess the number!
The secret number is: 72
Please input your guess.
78
You guessed: 78
peter@hp-laptop:~/rust-practice/chapter02/guessing_game$
그리고 당연하게도 다시 실행해보면 다른 값이 생성된다.
peter@hp-laptop:~/rust-practice/chapter02/guessing_game$ cargo run
Finished dev [unoptimized + debuginfo] target(s) in 0.01s
Running `target/debug/guessing_game`
Guess the number!
The secret number is: 82
Please input your guess.
28
You guessed: 28
peter@hp-laptop:~/rust-practice/chapter02/guessing_game$
이제 플레이어의 예측값과 생성된 난수값을 비교하여
비교 결과를 알려준다. 에 해당하는 부분을 작성해보자.
비교할 때 유의해야 할 점은, 표준 입력은 문자열의 형태로 읽어온다는 것이다.
즉, 난수 정수값과 직접 비교하려고 하면 자료형이 다르기 때문에 불가능하다.
// 물론 이게 가능한 언어도 존재하지만, Rust는 자료형에 민감하다, 매우!
그런 의미에서 먼저 값을 비교하기 전에 예측값을 정수로 변환하자.
peter@hp-laptop:~/rust-practice/chapter02/guessing_game$ vi src/main.rs
src/main.rs
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) .expect("Fail to read line"); let guess: u32 = guess.trim().parse() .expect("Please type a number!"); println!("You guessed: {}", guess); }
우리는 u32
자료형의 guess
변수를 만들었다.
u32
는 Rust의 정수 자료형 중 하나로, 부호가 없는 32bit 정수를 의미한다.
변수 선언은 let <변수 이름>: <자료형>;
으로 이루어지며,
컴파일 시점에 자료형이 명확한 경우에만 자료형을 생략할 수 있다.
앞서 선언한 다른 변수들은 그것이 명확해서 생략된 것이다.
그런데 guess
라는 이름의 변수는 기존에 선언된 바가 있다.
하지만 Rust는 shadowing이라는 기능으로 기존의 값을 가리고 같은 이름의 변수를 선언할 수 있다.
shadowing을 사용하면 기존의 값은 그 변수의 이름으로 접근할 수 없다.
이 기능은 guess_str
과 같이 개별 변수를 따로 만들지 않고
변환한 변수를 같은 이름으로 저장할 수 있다는 편의성을 제공한다.
우리는 기존의 guess
가 가진 문자열에서 trim
메서드를 통해 개행문자와 같은 공백을 제거하고
parse
메서드를 통해 구문분석을 하여 숫자를 반환한다.
숫자로 변환할 수 없는 문자열이었을 경우 expect
가 프로그램을 종료하고
숫자로 변환되면 그 값을 새로 선언한 guess
에 bind한다.
자, 이제 예측값과 난수값을 비교할 수 있게 되었으니 이에 해당하는 코드를 작성해보자.
peter@hp-laptop:~/rust-practice/chapter02/guessing_game$ vi src/main.rs
src/main.rs
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) .expect("Fail to read line"); let guess: u32 = guess.trim().parse() .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!"), } }
이번에는 use std::cmp::Ordering;
이 추가되었다.
Ordering
은 Result
와 마찬가지로 열거형이다.
이것은 Less
, Greater
, Equal
세 개의 값을 가지고 있다.
cmp
메서드는 비교가 가능한 어떤 값에도 사용할 수 있는데
그 값과 인자로 전달된 값을 비교하여 그 결과를 Ordering
열거값으로 반환한다.
그 값이 인자로 전달된 값에 비해 어떠한가를 반환하는 것이다.
cmp
매서드의 반환값이 각각의 열거값에 해당할 때의 코드는
match
라는 비교 구문을 사용하여 작성할 수 있다.
match
표현식에 대해서는 이후에 다시 이야기하겠지만
<패턴> => <실행문>
형태의 arm으로 구성되어 있으며
match
와 중괄호 사이의 값이 어떤 패턴과 일치하면 그 arm의 실행문이 실행되는 형태다.
우리는 guess.cmp(&secret_number)
의 반환값을 그 기준값으로 사용한다.
실행해보면 값의 대소관계에 따라 문자열이 출력되는 것을 확인할 수 있다.
peter@hp-laptop:~/rust-practice/chapter02/guessing_game$ cargo run
Compiling guessing_game v0.1.0 (/home/peter/rust-practice/chapter02/guessing_game)
Finished dev [unoptimized + debuginfo] target(s) in 0.35s
Running `target/debug/guessing_game`
Guess the number!
The secret number is: 44
Please input your guess.
28
You guessed: 28
Too small!
peter@hp-laptop:~/rust-practice/chapter02/guessing_game$
그런데 이렇게 한 번 시도하고 끝나면 제대로 된 숫자 맞히기 게임이 되지 않는다.
따라서 반복문을 통해 계속 입력 받고, 정답을 맞췄을 때 종료할 필요가 있다.
유의미한 게임이 되도록 하기 위해서 반복문을 사용하여
플레이어의 예측값이 생성된 난수값과 일치하면
축하 메시지를 출력 후 종료한다. 에 해당하는 부분을 작성하자.
반복을 사용하는 방법은 다양하지만 무한 반복을 하는데 사용되는 loop
를 사용해보겠다.
이것은 말 그대로 무한 반복이므로 반복 조건에 따라 반복을 종료하는 코드를 포함시키는 게 중요하다.
물론 종료 조건이 없어도 ctrl + c
를 통해 강제 종료할 수는 있긴 하다.
하지만 적절한 종료 조건을 통해 로직 상의 종료를 구현하는 것이 좋다.
peter@hp-laptop:~/rust-practice/chapter02/guessing_game$ vi src/main.rs
src/main.rs
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) .expect("Fail to read line"); let guess: u32 = guess.trim().parse() .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; }, } } }
loop
를 사용하여 무한 반복을 하게 수정하였으며
match
구문의 Ordring::Equal
에 해당하는 arm의 실행문을 코드블록으로 바꾸어
반복에서 벗어나기 위한 break;
를 추가하였다.
이제 실행해보면 반복적으로 수행되는 것을 알 수 있다.
peter@hp-laptop:~/rust-practice/chapter02/guessing_game$ cargo run
Compiling guessing_game v0.1.0 (/home/peter/rust-practice/chapter02/guessing_game)
Finished dev [unoptimized + debuginfo] target(s) in 0.26s
Running `target/debug/guessing_game`
Guess the number!
The secret number is: 42
Please input your guess.
28
You guessed: 28
Too small!
Please input your guess.
78
You guessed: 78
Too big!
Please input your guess.
42
You guessed: 42
You win!
peter@hp-laptop:~/rust-practice/chapter02/guessing_game$
지금 우리 프로그램은 사용자가 숫자가 아닌 값을 입력하면 그대로 종료된다.
하지만 그것보다는 사용자로 하여금 다시 입력하도록 하는 것이 좋을 것이다.
우리는 열거형과 match
를 이용하여 비교문을 작성하는 것을 해봤으니
Result
의 열거값을 통해 이를 처리하는 것도 금방 할 수 있을 것이다.
그리고 하는 김에 더이상 필요하지 않은, 난수값 출력 코드도 제거하겠다.
peter@hp-laptop:~/rust-practice/chapter02/guessing_game$ vi src/main.rs
src/main.rs
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) .expect("Fail 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; }, } } }
이제 guess.trim().parse()
가 성공했을 경우에만 그 결과가 guess
에 bind되고
그렇지 않을 경우 continue
를 만나 반복문의 시작 부분으로 돌아간다.
이제 다시 실행해보자.
peter@hp-laptop:~/rust-practice/chapter02/guessing_game$ cargo run
Compiling guessing_game v0.1.0 (/home/peter/rust-practice/chapter02/guessing_game)
Finished dev [unoptimized + debuginfo] target(s) in 0.70s
Running `target/debug/guessing_game`
Guess the number!
Please input your guess.
78
You guessed: 78
Too small!
Please input your guess.
guess
Please input your guess.
it is not a number!
Please input your guess.
93
You guessed: 93
You win!
peter@hp-laptop:~/rust-practice/chapter02/guessing_game$
실시간 피터 "왜 맞았지? 그냥 적당히 큰 값이었는ㄷ..."
자, 이걸로 우리는 작동하는 하나의 Rust 프로그램, 숫자 맞추기 게임을 구현했다.
무언가 구현해냈다는 뿌듯함과 함께 그래서 이게 어떻게 작동되는가 하는 궁금증이 생긴다.
그 궁금증을 가지고 호기심을 유지한 채! 다음 내용으로 넘어가보자.
이 포스트의 내용은 공식문서의 2장 Programming a Guessing Game에 해당합니다.
잘 읽었습니다!👍👍👍
짤막한 업데이트 글귀..!
현재 (2021.07.12)
rand crate
의 최신 버전은0.8.4
이고,get_range 메소드는 아래처럼 인자를 하나만 받게 되었습니다.