Rust

The Rust Programming Language 日本語版 を 自分で学習したときのメモ

2. Programming Guess Game.


  1. 新しいプロジェクトを生成する ... v00
  2. 実行する
    $ cargo new guessing_game
        Creating binary (application) `guessing_game` package
    note: see more `Cargo.toml` keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
    $ cd guessing_game
    $ tree .
    .
    ├── Cargo.toml
    └── src
        └── main.rs
    
    2 directories, 2 files
    
    guessing_game/main.rsを変更する
    fn main() {
        println!("Hello, world!");
    }
    
  3. 推測を処理する ... v01
  4. read_line 関数は、 「ユーザが標準入力に入力したデータを、文字列に追加する」 という動作を行う。 引数の文字列変数 guess の参照を渡すために & をつけ、 さらに可変にするために mutをつけて、 &mut guessguess と表記している。

    read_line 関数は io::Result を返す。 これは enum (列挙)型であり、その列挙子は okErr である。 したがって、.expect("...") の部分は返り値の io:Result クラスの expect メソッドが実行される。 Errexpect() メソッドは、実行を中断し、引数として渡されたメッセージを表示する。 okexpect() メソッドは、正しい返り値を取り出して返す。 今回の read_line() 関数の返り値は、ユーザ入力のバイト数である。

    guessing_game/main.rsの変更
    *** v00/guessing_game/src/main.rs	Sat Jan 24 16:43:55 2026
    --- v01/guessing_game/src/main.rs	Sun Jan 25 04:56:38 2026
    ***************
    *** 1,3 ****
      fn main() {
    !     println!("Hello, world!");
      }
    --- 1,13 ----
    + use std::io;
    + 
      fn main() {
    !     println!("Guess the number!");
    !     println!("Please input your guess.");
    ! 
    !     let mut guess = String::new();  // ユーザの入力を格納する変数 (可変 mutable)
    !     io::stdin()
    !         .read_line(&mut guess)
    !         .expect("Failed to read line");
    ! 
    !     println!("You guessed: {}", guess);
      }
    
    guessing_game の実行
    $ cargo build
       Compiling guessing_game v0.1.0 (/home/nitta/doc/rust/project/guessing_game)
        Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.08s
    $ cargo run
        Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.00s
         Running `target/debug/guessing_game`
    Guess the number!
    Please input your guess.
    37
    You guessed: 37
    
    
  5. 秘密の数を生成する ... v02
  6. random クレートを利用して機能を追加する。クレートとは Rust ソースコードを集めたものである。 Cargo.toml ファイルの [dependencies] セクションヘッダの下に、に rand クレートと依存関係にあることを記述する。
    rand = "0.8.3"
    
    guessing_game/Cargo.tomlの変更
    *** v01/guessing_game/Cargo.toml	Sat Jan 24 20:47:48 2026
    --- v02/guessing_game/Cargo.toml	Sat Jan 24 20:52:53 2026
    ***************
    *** 4,6 ****
    --- 4,7 ----
      edition = "2024"
      
      [dependencies]
    + rand = "0.8.3"
    
    ビルドしてみる。
    randクレートを加えてビルドする
    $ cargo build
        Updating crates.io index
         Locking 14 packages to latest Rust 1.93.0 compatible versions
          Adding cfg-if v1.0.4
          Adding getrandom v0.2.17
          Adding libc v0.2.180
          Adding ppv-lite86 v0.2.21
          Adding proc-macro2 v1.0.106
          Adding quote v1.0.44
          Adding rand v0.8.5 (available: v0.9.2)
          Adding rand_chacha v0.3.1
          Adding rand_core v0.6.4
          Adding syn v2.0.114
          Adding unicode-ident v1.0.22
          Adding wasi v0.11.1+wasi-snapshot-preview1
          Adding zerocopy v0.8.33
          Adding zerocopy-derive v0.8.33
     Downloading crates ...
      Downloaded cfg-if v1.0.4
      Downloaded rand_core v0.6.4
      Downloaded rand_chacha v0.3.1
      Downloaded ppv-lite86 v0.2.21
      Downloaded getrandom v0.2.17
      Downloaded rand v0.8.5
      Downloaded zerocopy v0.8.33
      Downloaded libc v0.2.180
       Compiling libc v0.2.180
       Compiling zerocopy v0.8.33
       Compiling cfg-if v1.0.4
       Compiling getrandom v0.2.17
       Compiling rand_core v0.6.4
       Compiling ppv-lite86 v0.2.21
       Compiling rand_chacha v0.3.1
       Compiling rand v0.8.5
       Compiling guessing_game v0.1.0 (/home/nitta/doc/rust/project/guessing_game)
        Finished `dev` profile [unoptimized + debuginfo] target(s) in 2.03s
    

    cargo は cargo build を最初に実行したときに Cargo.lock ファイルを作成し、 cargo は指示がない限り、指定したバージョンの依存のみを使用する。

    クレートをアップグレードしたい場合は、 cargo update コマンドを使用する。 デフォルトでは現在の記述が "0.8.3" の場合は「0.8.3以上0.9.0未満」のバージョンのみを検索する。

  7. 乱数を生成する ... v03
  8. 1..101 という表現は 1..=100 と同じ意味であり「1から100までの数」を表す。

    guessing_game/src/main.rs の変更
    *** v02/guessing_game/src/main.rs	Sat Jan 24 20:50:57 2026
    --- v03/guessing_game/src/main.rs	Sun Jan 25 05:25:20 2026
    ***************
    *** 1,7 ****
    --- 1,11 ----
      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();  // ユーザの入力を格納する変数 (可変 mutable)
    
    guessing_game の実行
    $ cargo run
       Compiling guessing_game v0.1.0 (/mnt/hostos/www/html/lec/rust/doc_rust_self/ch02/v03/guessing_game)
        Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.09s
         Running `target/debug/guessing_game`
    Guess the number!
    The secret number is: 31
    Please input your guess.
    50
    You guessed: 50
    
  9. 推測と秘密の数字を比較する ... v04
  10. guessing_game/src/main.rs の変更
    *** v03/guessing_game/src/main.rs	Sun Jan 25 05:25:20 2026
    --- v04/guessing_game/src/main.rs	Sun Jan 25 06:16:40 2026
    ***************
    *** 1,4 ****
    --- 1,5 ----
      use std::io;
    + use std::cmp::Ordering;
      use rand::Rng;
      
      fn main() {
    ***************
    *** 13,17 ****
    --- 14,27 ----
              .read_line(&mut guess)
              .expect("Failed 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!"),
    +     }
        }
    
    guessing_game の実行
    $ cargo run
       Compiling guessing_game v0.1.0 (/mnt/hostos/www/html/lec/rust/doc_rust_self/ch02/v04/guessing_game)
        Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.11s
         Running `/mnt/hostos/www/html/lec/rust/doc_rust_self/ch02/v04/guessing_game/target/debug/guessing_game`
    Guess the number!
    The secret number is: 95
    Please input your guess.
    37
    You guessed: 37
    Too small!
    
  11. ループで複数回の予想を可能にする ... v05
  12. guessing_game/src/main.rs の変更
    *** v04/guessing_game/src/main.rs	Sun Jan 25 06:16:40 2026
    --- v05/guessing_game/src/main.rs	Sun Jan 25 06:38:23 2026
    ***************
    *** 6,27 ****
          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();  // ユーザの入力を格納する変数 (可変 mutable)
    !     io::stdin()
    !         .read_line(&mut guess)
    !         .expect("Failed 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!"),
          }
    !   }
    --- 6,29 ----
          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();  // ユーザの入力を格納する変数 (可変 mutable)
    !         io::stdin()
    !             .read_line(&mut guess)
    !             .expect("Failed 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!"),
    !         }
          }
    ! }
    
    guessing_game の実行
    $ cargo run
       Compiling guessing_game v0.1.0 (/mnt/hostos/www/html/lec/rust/doc_rust_self/ch02/v05/guessing_game)
        Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.11s
         Running `target/debug/guessing_game`
    Guess the number!
    The secret number is: 88
    Please input your guess.
    50
    You guessed: 50
    Too small!
    Please input your guess.
    75
    You guessed: 75
    Too small!
    Please input your guess.
    87
    You guessed: 87
    Too small!
    Please input your guess.
    94
    You guessed: 94
    Too big!
    Please input your guess.
    90
    You guessed: 90
    Too big!
    Please input your guess.
    88
    You guessed: 88
    You win!
    Please input your guess.
    quit
    
    )thread 'main' (64610) panicked at src/main.rs:19:14:
    Please type a number !: ParseIntError { kind: InvalidDigit }
    note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
  13. 推測が正しい場合に終了する ... v06
  14. guessing_game/src/main.rs の変更
    *** v05/guessing_game/src/main.rs	Sun Jan 25 06:38:23 2026
    --- v06/guessing_game/src/main.rs	Sun Jan 25 06:44:19 2026
    ***************
    *** 23,29 ****
              match guess.cmp(&secret_number) {
                  Ordering::Less => println!("Too small!"),
                  Ordering::Greater => println!("Too big!"),
    !             Ordering::Equal => println!("You win!"),
              }
          }
      }
    --- 23,32 ----
              match guess.cmp(&secret_number) {
                  Ordering::Less => println!("Too small!"),
                  Ordering::Greater => println!("Too big!"),
    !             Ordering::Equal => {
    !                 println!("You win!");
    !                 break;
    !             }
              }
          }
      }
    
    guessing_game の実行
    $ cargo run
       Compiling guessing_game v0.1.0 (/mnt/hostos/www/html/lec/rust/doc_rust_self/ch02/v06/guessing_game)
        Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.11s
         Running `target/debug/guessing_game`
    Guess the number!
    The secret number is: 16
    Please input your guess.
    50
    You guessed: 50
    Too big!
    Please input your guess.
    25
    You guessed: 25
    Too big!
    Please input your guess.
    12
    You guessed: 12
    Too small!
    Please input your guess.
    18
    You guessed: 18
    Too big!
    Please input your guess.
    15
    You guessed: 15
    Too small!
    Please input your guess.
    16
    You guessed: 16
    You win!
  15. 不正な入力を処理する ... v07
  16. guessing_game/src/main.rs の変更
    *** v06/guessing_game/src/main.rs	Sun Jan 25 06:44:19 2026
    --- v07/guessing_game/src/main.rs	Sun Jan 25 08:51:11 2026
    ***************
    *** 15,22 ****
                  .read_line(&mut guess)
                  .expect("Failed to read line");
      
    !         let guess: u32 = guess.trim().parse()
    !             .expect("Please type a number !");
      
              println!("You guessed: {}", guess);
      
    --- 15,24 ----
                  .read_line(&mut guess)
                  .expect("Failed to read line");
      
    !         let guess: u32 = match guess.trim().parse() {
    !             Ok(num) => num,
    !             Err(_) => continue,
    !         };
      
              println!("You guessed: {}", guess);
      
    
    guessing_game の実行
    $ cargo run
        Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.01s
         Running `target/debug/guessing_game`
    Guess the number!
    The secret number is: 84
    Please input your guess.
    50
    You guessed: 50
    Too small!
    Please input your guess.
    seventy      ←   不正な入力に対しては再入力を促す
    Please input your guess.
    75
    You guessed: 75
    Too small!
    Please input your guess.
    87
    You guessed: 87
    Too big!
    Please input your guess.
    81
    You guessed: 81
    Too small!
    Please input your guess.
    84
    You guessed: 84
    You win!
    
  17. 正解の表示を削除する ... v08
  18. guessing_game/src/main.rs の変更
    *** v07/guessing_game/src/main.rs	Sun Jan 25 08:51:11 2026
    --- v08/guessing_game/src/main.rs	Sun Jan 25 09:38:06 2026
    ***************
    *** 5,11 ****
      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.");
    --- 5,11 ----
      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.");
    
    guessing_game の実行
    $ cargo run
       Compiling guessing_game v0.1.0 (/mnt/hostos/www/html/lec/rust/doc_rust_self/ch02/v08/guessing_game)
        Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.11s
         Running `target/debug/guessing_game`
    Guess the number!
    Please input your guess.
    50
    You guessed: 50
    Too small!
    Please input your guess.
    75
    You guessed: 75
    Too big!
    Please input your guess.
    63
    You guessed: 63
    Too small!
    Please input your guess.
    69
    You guessed: 69
    Too small!
    Please input your guess.
    72
    You guessed: 72
    Too small!
    Please input your guess.
    74
    You guessed: 74
    Too big!
    Please input your guess.
    73
    You guessed: 73
    You win!
    


http://ynitta.net