0%

[Rust]教學系列-猜謎遊戲:取亂數

前提情要

筆者這邊利用下班、假日時間,打算花半年時間學習新的程式語言,將所學過程紀錄下來,寫成部落格,雖然Rust的教學文件非常的完整,也有繁體中文的版本,但筆者認為唯有用自己的話寫下來,讓別人懂,才是真正學會,因此決定撰寫Rust教學系列文章。

目前來到官網範例中的「猜謎遊戲」環節,[Rust]教學系列-猜謎遊戲:取得使用者輸入值已經可以取得使用者輸入的猜數值,這篇要來繼續撰寫,取亂數的部份,我們要用到Cargo的方式將取得隨機亂數函式庫引進來,使用該套件產生1~100間的亂數,跟著筆者一起實作吧。

內容

這篇使用rand套件來實作取亂數,筆者之前就有提到官方建議cargo來管理其相依套件,那套件本身會在哪裡,讓我們使用cargo指令來下載呢,答案就是crate,使用其他的語言舉例來說的話,nodejs使用npm管理相依套件,那會有npm public registry,讓我們可以用npm i去下載相依套件,又如寫.net的工程師來說,會使用nuget管理相依套件,那也會有一個nuget gallery公開的registry,可以連線下載,那Rust語言來說用cargo管理相依套件,會從https://crates.io/下載其相關套件。

Crates.io 是個讓 Rust 生態系統中的每個人都能發佈它們的開源 Rust 專案並讓其他人使用的地方

安裝rand套件

筆者[Rust]教學系列-Hello Cargo中有大概講解一下其cargo指令建立專案後的檔案結構,其中Cargo.toml中的dependencies區塊中宣告我們相依套件,因此我們會在這宣告需要使用到的套件rand

1
2
[dependencies]
rand = "0.8.3"

接著使用cargo指令建置,因為上面已設定相依套件,因此建置過程會安裝相依套件,意即rand套件相依的套件也會一併安裝

1
2
3
4
5
6
7
8
9
10
11
12
13
cargo build
# 輸出結果
Blocking waiting for file lock on package cache
Updating crates.io index
Blocking waiting for file lock on package cache
Compiling cfg-if v1.0.0
Compiling ppv-lite86 v0.2.15
Compiling getrandom v0.2.3
Compiling rand_core v0.6.3
Compiling rand_chacha v0.3.1
Compiling rand v0.8.4
Compiling guession_game v0.1.0 (\Projects\guession_game)
Finished dev [unoptimized + debuginfo] target(s) in 28.19s

可以看出rand套件相依套件有

  • cfg-if
  • ppv-lite86
  • getrandom
  • rand_core
  • rand_chacha

上述這些rand套件相依的套件也會一併安裝

產生隨機數字

使用gen_range這個方法取得隨機產生數值,可以傳入start..end,該方法會從startend之間的數字中,隨機取得一個數字當作回傳值

1
2
3
4
use rand::Rng;

let secret_number = rand::thread_rng().gen_range(1..101);
println!("秘密數字為:{}", secret_number);

上述程式碼中,引入rand package中的Rng Trait,其中使用thread_rng的函式中的gen_range方法,傳入參數為start..end,包含start,不包含end,若要包含end則需改用start..=end,以上述例子來說,我們需要改成gen_range(1..=100),也是一樣的效果的。

透過Cargo指令產生技術文件

這時候是時候要來講一下Rust語言的特色之一生產力部份,以上述來說我們要從何而知這些套件有哪些方法可以使用,Rust這邊有一個產生技術文件的機制,不過筆者不知道公開套件是否要上架前必須得提供技術文件,就不得而知了,不過筆者猜測是一定要的程序。

我們可以透過cargo doc —open的方式產生並開啟,他就是一個html格式的技術文件。基本上cargo會掃描該專案下相依的套件(包含自己),產生成可讀性高的html檔案,因為有下—open,因此會產生完畢後會自動開啟。

產生技術文件檔案的相對路徑為{專案目錄}target/doc/guession_game/index.html

亦可到creates.io中的該套件下的documentation連結中看到一模一樣的技術文件,筆者猜測就是拿各套件的技術文件加以包裝,變成local的技術文件檔案

完整程式碼

最後附上以上篇及這篇組合之下的程式碼

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
use std::io;
use rand::Rng;
fn main() {
println!("請猜測一個數字!");

let secret_number = rand::thread_rng().gen_range(1..101);
println!("秘密數字為:{}", secret_number);

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
# 輸出結果
Finished dev [unoptimized + debuginfo] target(s) in 0.01s
Running `target\debug\guession_game.exe`
請猜測一個數字!
秘密數字為:51
請輸入你的猜測數字!
10
你的猜測數字:10

結論

到這邊,已經完成猜謎遊戲的第二部份了,最後只剩下將使用者輸入值與隨機產生的神秘數字做一個比較,此部份會於下篇說明,最後筆者recap一下這篇講到的內容

  • 編輯Cargo.toml中的dependencies區塊,宣告其套件其版本號,例:rand = "0.8.3",透過cargo build,將相依套件安裝好
  • 透過gen_range方法可以取得在特定範圍內隨機產生的一組數字,有overload方法,一個是傳入start..end,另一個則start..=end,依照個人喜好做選擇
  • cargo doc —open指令的方式產生技術文件並開啟技術文件

參考