學習軌道
/
Rust
Rust
/
練習
/
低功耗嵌入式遊戲
低功耗嵌入式遊戲

低功耗嵌入式遊戲

學習練習

簡介

元組是一種輕量的方式,能把一組型別各異、數量固定的資料聚集在一起。元組沒有特定的名稱;為資料結構命名後,它就變成了 struct。元組的欄位沒有名稱,而是透過解構或依位置來存取。

語法

建立

元組一律使用元組運算式建立:

// pointless but legal
let unit = ();
// single element
let single_element = ("note the comma",);
// two element
let two_element = (123, "elements can be of differing types");

元組可以有任意數量的元素。

以解構存取

我們可以透過解構來存取元組的元素。這只是把變數名稱指定給元組中的個別元素,並在過程中消耗掉整個元組。

let (elem1, _elem2) = two_element;
assert_eq!(elem1, 123);

依位置存取

也可以透過數字位置索引來存取元組的元素。索引一如往常,從 0 開始。

let notation = single_element.0;
assert_eq!(notation, "note the comma");

元組結構體

你之後也會需要處理元組結構體。和一般結構體一樣,它們是具名型別;但和一般結構體不同的是,它們的欄位是匿名的。它們的語法和一般的元組語法非常相似。解構與依位置存取兩者都可以使用。

struct TupleStruct(u8, i32);
let my_tuple_struct = TupleStruct(123, -321);
let neg = my_tuple_struct.1;
let TupleStruct(byte, _) = my_tuple_struct;
assert_eq!(neg, -321);
assert_eq!(byte, 123);

欄位可見性

匿名元組的所有欄位一律都是公開的。不過,元組結構體的每個欄位各自擁有可見性,預設為私有,就和標準結構體的欄位一樣。你可以用 pub 修飾詞把欄位設為公開,就和標準結構體一樣。

// fails due to private fields
mod tuple { pub struct TupleStruct(u8, i32); }
fn main() { let _my_tuple_struct = tuple::TupleStruct(123, -321); }
// succeeds: fields are public
mod tuple { pub struct TupleStruct(pub u8, pub i32); }
fn main() { let _my_tuple_struct = tuple::TupleStruct(123, -321); }

說明

你正在開發一款目標為低功耗嵌入式系統的遊戲,需要撰寫幾個便利函式,供遊戲的其他部分使用。

1. 計算除法的商與餘數

商是除法的輸出。

fn divmod(dividend: i16, divisor: i16) -> (i16, i16)

範例:

assert_eq!(divmod(10, 3), (3, 1));

2. 從疊代器中挑選位於偶數位置的項目

你的老闆保證,這對啟用螢幕緩衝區最佳化會有幫助。

疊代器是會公開 Iterator trait 所定義之方法的項目。那份文件相當詳盡,因為疊代器提供了許多方法;以下是最相關的幾個特性:

  • 疊代器是任意長度的項目串流
  • 疊代器有 enumerate方法,會為每個值回傳一個元組(i, val)
  • 疊代器有 filter方法,會用閉包判斷是否要產出疊代器中的某個元素
  • 疊代器有 map方法,會用閉包修改疊代器中的元素

由於你的函式可以執行在任何種類的疊代器上,因此它使用impl來表示這是 trait 實例,而不是單純的項目。同樣地,<Item=T>語法只是表示疊代器產生什麼種類的項目並不重要;你的函式可以產生任何疊代器的偶數元素。

fn evens<T>(iter: impl Iterator<Item=T>) -> impl Iterator<Item=T>

範例:

let mut even_ints = evens(0_u8..);
assert_eq!(even_ints.next(), Some(0));
assert_eq!(even_ints.next(), Some(2));
assert_eq!(even_ints.next(), Some(4));
assert_eq!(even_ints.next(), Some(6));
let mut evens_from_odds = evens(1_i16..);
assert_eq!(evens_from_odds.next(), Some(1));
assert_eq!(evens_from_odds.next(), Some(3));
assert_eq!(evens_from_odds.next(), Some(5));
assert_eq!(evens_from_odds.next(), Some(7));

3. 計算某個位置與原點之間的曼哈頓距離

為了方便對應,你有一個元組結構Position:

struct Position(i16, i16);

你需要為Position實作一個manhattan方法,回傳該位置與原點(Position(0, 0))之間的曼哈頓距離。

impl Position {
    fn manhattan(&self) -> i16
}

範例:

assert_eq!(Position(3, 4).manhattan(), 7);
透過 GitHub 編輯 連結會在新視窗或分頁中開啟
Rust Exercism

準備好開始 低功耗嵌入式遊戲 了嗎?

註冊 Exercism,透過 99 個練習 和真人引導來學習並精通 Rust,全部免費。