0%

[Rust]教學系列-猜謎遊戲:取得使用者輸入值

前情提要

筆者就照著官方教學文件,繼續往下走了,來到撰寫猜謎遊戲的環節,主要是做一個command line互動遊戲,因為尚未講解到語法、資料型別等,因此這個猜謎遊戲就當作初試Rust的撰寫體驗,不了解的部份,由後面章節會繼續介紹其語法、資料型別等。官方文件的策略是先由一個簡單的小遊戲,來入門Rust的程式語法、思考邏輯、Coding Style等。

內容

程式內容為使用亂數產生1~100間的數字,與使用者輸入的數字做對比,沒有猜對,可以一直猜下去,猜對則跳出成功訊息結束。

建立專案

已經介紹過Cargo,官方也建議使用Cargo做建立專案,套件管理,建置、執行專案,首先,建立一個猜字遊戲專案

1
2
cargo new guessing_game
cd guessing_game

先用cargo指令執行驗證看看

1
2
3
4
5
6
cargo run
# 輸出結果
Compiling guessing_game v0.1.0 (/Projects/guessing_game)
Finished dev [unoptimized + debuginfo] target(s) in 0.38s
Running `target/debug/guessing_game`
Hello, world!

讀取使用者輸入值

猜謎遊戲第一步就是要讓使用者輸入猜數,程式實作要讀取使用者輸入值並存至變數中,爾後需與隨機產生的數字作比較,來看看Rust語言要怎麼實作吧

宣告變數值

首先要宣告一個變數值存入使用者輸入值

1
let mut guess = String::new();

由於Rust本身宣告變數時,預設是不可變的,若是可變動變數則需要加一個mut關鍵字於變數名稱前方,接著看到的是String::new(),new是String型別的關聯函式,需使用::這個符號串接,其實也沒這麼複雜,就是new出一個空字串。

讀取使用者輸入值

讀取使用者輸入值需引入標準函式庫,使用use關鍵字引入函式庫,函式庫為std底下的io

1
2
3
4
5
use std::io;

io::stdin()
.read_line(&mut guess)
.expect("讀取該行失敗")

若沒有使用use std::io;則撰寫時std::io::stdin(),就是呼叫標準函式庫下的io函式庫,io函式庫下有一個command line輸入值handle的型別函式stdin

stdin函式底下有一個method名稱叫read_line,使用該方法可以取得使用者輸入值,那讀出來的輸入值存到哪個變數中呢,由methodparameter中傳入,道理跟上面宣告變數一樣,Rust世界中預設皆不可變,因此需要使用&mut guess傳入,若維持不可變則使用&guess傳入即可,其中&這個符號reference的概念,之後筆者會照著官方教學,會有一篇獨立的教學文章來說明。

最後是expectRust這邊將標準函式庫中的method回傳值都包裝成泛型Result型別,因此透過Result型別我們可以處理可能發生的ExceptionResult型別底下有一個method,名稱叫expect,以結果okerror而傳入不同參數給expect方法,筆者以vscodeexpect的解說中的範例來說

1
2
3
4
5
6
7
// expect的方法定義
// pub fn expect(self, msg: &str) -> T
let x: Result<u32, &str> = Err("emergency failure");
x.expect("Testing expect");

// 執行結果
// thread 'main' panicked at 'Testing expect: "emergency failure"', src/main.rs:4:7

以結果來看,若發生Error則,顯示訊息會是「傳入的string:error訊息」,因此若以筆者上述宣告的來說,發生錯誤則會顯示「讀取該行失敗:error訊息」,先有這樣的概念即可。

輸出猜數

最後將使用者輸入的猜數印出來做這段的結尾,使用println!文字格式化輸出

1
println!("你的猜測數字:{}", guess);

完整程式碼

最後組合一下上面宣告的那些程式碼,完整程式碼如下

1
2
3
4
5
6
7
8
9
10
11
12
use std::io;
fn main() {
println!("請猜測一個數字!");
println!("請輸入你的猜測數字!");

let mut guess = String::new();
io::stdin()
.read_line(&mut guess)
.expect("讀取該行失敗");

println!("你的猜測數字:{}", guess);
}

執行結果

依照上述程式碼,跟著筆者一起來看看執行結果吧

1
2
3
4
5
6
7
8
9
cargo run
# 輸出結果
Compiling guessing_game v0.1.0 (/Projects/guessing_game)
Finished dev [unoptimized + debuginfo] target(s) in 0.44s
Running `target/debug/guessing_game`
請猜測一個數字!
請輸入你的猜測數字!
10
你的猜測數字:10

結論

猜謎遊戲就先到這邊,下篇繼續完成其他部份,筆者最後recap一下今天所學的東西

  • 引入package函式庫,使用use關鍵字,例:use std::io;
  • 宣告不可變參數,使用letmut關鍵字,例:let mut guess = String::new();
  • 取得使用者輸入值,使用io函式庫下的stdin函式庫中的read_line方法,例:io::stdin().read_line(&mut guess);
  • 泛型Result型別中的expect方法,宣告輸出error訊息時的搭配訊息,例:expect("該行讀取失敗");
  • 格式化輸出技巧,使用{}符號定義參數取代位置,會依序取代,例:println!("你的猜測數字:{}", guess);
  • ::符號:函式庫取用,例:io::stdin()String::new()
  • &符號:reference的方式傳入,例:read_line(&mut guess);

參考