[Rust] Guessing 게임 만들기_1

은근 재밌다

Kwoncheol Shin
6 min readMar 10, 2019

Guessing 게임 만들기_1 (현재글)

Guessing 게임 만들기_2

Photo by Kate Roberts on Flickr

간단한 게임을 하나 만들어 보면서 Rust의 대해 좀 더 자세히 알아보자!

이번 글에서는 프로젝트를 생성하고 모듈 가져오기, Rust의 변수, io 라이브러리 사용하기 등과 같은 Rust 프로그래밍에 필요한 기본적인 특징들을 살펴 볼 것이다.

Guessing game 🎮

다음과 같이 간단한 원리로 동작하는 게임이다.

  • 프로그램이 1~100 사이의 랜덤한 정수를 생성한다.
  • 사용자가 숫자를 입력할 때마다 프로그램은 사용자가 입력한 수가 정답보다 큰지, 작은지를 알려준다.
  • 사용자가 정답을 입력하면 게임은 종료된다.

먼저 cargo를 이용해 새로운 프로젝트를 생성한다.

$ cargo new guessing_game
>> Created binary (application) `guessing_game` package
$ cd guessing_game

이제 src 폴더 아래 main.rs 파일을 수정해보자.

우선 메인함수가 사용자에게 정수를 입력받고 어떤 수를 입력했는지 보여주도록 해보자.

1. 모듈 가져오기

우리 프로그램은 유저에게 입력을 받아야 한다. std 라이브러리 내부에 이러한 기능을 하는 io 라이브러리가 있으며 이를 가져오기 위해 use 구문을 사용했다.

use std::io;

Module std::prelude

Rust의 std 라이브러리는 다양한 하위 라이브러리들을 가지고 있다. std 라이브러리 내부에는 prelude 라이브러리가 있는데 이는 모든 Rust 파일에 기본적으로 import되는 패키지이다. 이 안에는 기본적인 Rust프로그램에 필요한 최소한의 라이브러리들이 들어있다. io 라이브러리는 std 내부에 있지만 prelude 에는 포함되지 않았기 때문에 use 를 사용해 명시적으로 패키지를 불러왔다.

2. 변수관리

let mut guess = String::new(); 

첫 번째로 let 은 변수를 선언하는 문법이다. Rust에서 일반 변수는 기본적으로 값을 변경할 수 없다.(immutable)

다음과 같은 구문은 에러를 일으킨다.

let foo = 5;
foo = 3;
>> cannot assign twice to immutable variable

하지만 위에서 우리가 선언했던 것과 같이 let 뒤에 mut 을 붙여준다면 변수의 변경이 가능하게된다.(mutable)

두 번째로 String::new 는 새로운 String 객체를 생성하는 함수이다. newString 과 같은 타입 들이 가지고 있는 함수이며 이에 접근하기 위해 :: 를 사용했다.

let mut guess = String::new() 는 다음과 같은 뜻을 가진 문장이다.

“String의 new함수를 이용해 guess라는 이름을 가진 mutable 변수를 선언해라.”

이제 io 를 사용하는 구문을 살펴보자

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

우리는 use std::io 를 입력해줬기 때문에 io 모듈에 바로 접근할 수 있다. 하지만 use 를 쓰지않고std::io::stdin() 과 같은 방식으로도 접근할 수 있다.

io::stdin()은 터미널에서의 인풋을 관리할 수 있는 standard input handle 인스턴스를 반환한다. read_line 은 해당 인스턴스가 갖고 있는 함수로 입력받은 값을 파라미터로 받은 변수에 String 형식으로 전달해준다.

다음으로 파라미터 이름을 전달할 때 앞에 붙여준 &mut 에 대해서 살펴보자. 우선 & 은 값을 참조하겠다는 표현이다. 즉 값을 직접 전달하는 것이 아니라 값의 주소만 전달하겠다는 것인데, 이러한 기능은 프로그램의 로직이 어디에 위치해있던 하나의 값에 동일하게 접근할 수 있게 해준다. 참조는 복잡하지만 매우 유용한 기능으로 Rust는 이 값을 안전하고 효율적으로 관리할 수 있도록 해준다.

참조는 변수와 마찬가지로 아무 것도 명시해주지 않을시 immutable한 값이다. 우리는 값을 변경해야 하기 때문에 &mut 을 붙여 mutable하도록 만들어주었다.

3. Result 타입으로 에러 관리하기

read_line 함수가 반환하는 결과는 io::Result 라는 타입을 갖고있다. (Rust의 std 에는 다양한 Result 타입들이 존재한다) Result는 미리 정의된 enumeration 값을 가진다.(enum에 대해서는 여기서 다루지 않겠다) Result의 경우 Ok 혹은Err 둘 중 하나의 값을 가질 수 있다. Result가 Ok 일 경우 Result를 반환한 동작이 잘 진행됐다는 것을 뜻하고 Err 는 그렇지 않다는 것을 나타낸다.

expectio::Result 가 갖고있는 메서드로 Result가 Ok 일 경우에는 입력받은 값을 반환하고 Err 일 경우 expect의 인자로 전달된 값을 결과로 반환한다.

expect 를 사용하지 않더라도 컴파일은 가능하지만 이에 대한 경고를 받게된다.

4. println! 으로 값 출력하기

우리 println문에는 {} 라는 녀석이 있었다.

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

{}는 placeholder로 println 내에서 값을 받을 수 있도록 해주는 녀석이다. C언어의 서식문자(%d,%s) 와 같은 역할을 한다.

let x = 5;
let y = 10;
println!("x = {} and y = {}", x, y);
>> x = 5 and y = 10

이제 cargo build 를 이용해 우리 코드가 잘 동착하는지 확인해보자.

$ cargo run
>> Game starts!
>> Please input your guess.
5
>> You guessed: 5

이번 글에서는

  1. 모듈 가져오기
  2. Rust 변수 생성
  3. io 모듈
  4. Result 타입
  5. println의 placeholder

위 다섯 가지에 대해서 알아보았다.

다음 글에서는 랜덤한 정수를 생성하는 코드를 작성해 볼 것이다. 랜덤한 정수를 생성하는 부분은 외부 crate를 사용할 것이기 때문에 이를 다루는 것에 대해서도 함께 알아 볼 것이다.

👋

Guessing 게임 만들기_1 (현재글)

Guessing 게임 만들기_2

--

--