数当てゲームコンプリート
これまでザ・ブックの数当てゲームを読みながら、Rustの機能「標準ライブラリ」「変数」「型の関数」「標準入力」「参照」「パニック処理」「クレート」「トレイト」「matchフロー制御演算子」「シャドーイング」を紹介した。今回取り上げるのはloopキーワードだ。これで数当てゲームは完了である。
最初に答えを見てみよう。ザ・ブックに掲載されている数当てゲームをベースに多少書き方ものが次のソースコードだ。
数当てゲーム main.rs
use rand::Rng;
use std::cmp::Ordering;
use std::io;
fn main() {
println!("数当てゲーム");
let secret_number = rand::thread_rng().gen_range(1, 101);
loop {
println!("どの数だとおもう? = ");
let mut guess = String::new();
io::stdin()
.read_line(&mut guess)
.expect("読み込み失敗");
let guess: u32 = match guess.trim().parse() {
Ok(num) => num,
Err(_) => continue,
};
println!("入力値: {}", guess);
match guess.cmp(&secret_number) {
Ordering::Less => println!("小さすぎです!"),
Ordering::Greater => println!("大きすぎです!"),
Ordering::Equal => {
println!("そのとおり!");
break;
}
}
}
}
このプログラムはユーザーからの入力を受け付け、最初に生成した数(1?100までの整数)を当てるまで繰り返しユーザーに入力を求める。前回から変更された点を以降で取り上げる。
loopキーワードとbreak
今回新しく追加されたのはloopキーワードだ。次のような使い方をするキーワードで、波括弧の間の処理を無限ループする目的で使われる。
loopキーワードで無限ループ
loop {
...略...
}
loopは動作としてはwhile trueに似ている。無限ループから抜ける時はbreakを使う。残りの処理を飛ばしてループの頭に戻る場合はcontinueだ。数当てゲームでは数が当たったら処理を終わらせたいので、次のように書き換えている。
数が当たったら無限ループを抜ける
loop {
...略...
match guess.cmp(&secret_number) {
Ordering::Less => println!("小さすぎです!"),
Ordering::Greater => println!("大きすぎです!"),
Ordering::Equal => {
println!("そのとおり!");
break;
}
}
}
matchフロー制御演算子のところでOrdering::Equalだった場合に無限ループを抜けているわけだ。
loopキーワードとcontinue
これまでの数当てゲームでは、ユーザーが入力したデータが数字以外だった場合にエラーを起こしていたが、最終版では数字以外のデータが入力された場合に再度数字の入力を促すようになっている。ゲームとしてはこのほうが使いやすい。該当部分は次のとおりだ。
数字以外のデータの場合の処理をエラーからcontinueへ変更
let guess: u32 = match guess.trim().parse() {
Ok(num) => num,
Err(_) => continue,
};
シャドーイングしていた部分なのだが、まずここが「let guess: u32 = guess.trim().parse()」から「let guess: u32 = match guess.trim().parse()」に書き換わっている点に注目だ。matchフロー制御演算子はこんな感じでも使用できる。
そして、分岐対象がOk()とErr()になっており、Ok()だった場合は変換した数字を、Err()だった場合にはcontinueでループを飛ばして次のループが始まるといった仕組みになっている。
matchフロー制御演算子はとても強力な機能だ。Rustに特徴的な機能のひとつであり、ぜひとも慣れておきたい書き方である。
数当てゲーム完成版
完成した数当てゲームを実行すると次のようになる。小さな値と大きな値を入力して徐々に正解の値に近づけていき、数が当たるとプログラムは終了する。
ザ・ブックに掲載されている数当てゲームはソースコードとしては短いものだが、このソースコードにはRustの特徴がいい感じに詰まっている。これだけ短いソースコードだが、そこに盛り込まれている概念や機能は結構多い。
今回取り上げた機能も含めれば、数当てゲームで「標準ライブラリ」「変数」「型の関数」「標準入力」「参照」「パニック処理」「クレート」「トレイト」「matchフロー制御演算子」「シャドーイング」「loopーワード」に触れたことになる。このソースコードを理解するだけで、Rustの基本的な部分をかなり把握できるのだ。
Rustの強みはやはり堅さにあるように見える。厳密に書かないとコンパイラは通らない。かといってガチガチかといえば、実用性を考慮した書き方もできるようになっている。知れば知るほど魅力を感じるプログラミング言語だ。
Rustは人気シェアの上ではまだ1%未満(TIOBE Programming Community Index調べ)だが、そのシェアは徐々に増加している。プログラミング言語の難しさもあり、万人向けするようなものではないのだが、この堅さは小幅ながらも増加を続けるRustのシェアに実用言語としての期待が集まっているように見える。今のところRustの人気が陰る強い理由はなく、今後も同様の増加推移を見せる可能性がある。