學習軌道
/
Go
Go
/
練習
/
機器人模擬器
機器人模擬器

機器人模擬器

中等

說明

撰寫一個機器人模擬器。

某間機器人工廠的測試設施需要一支程式來驗證機器人的移動。

機器人有三種可能的移動:

  • 向右轉
  • 向左轉
  • 前進

機器人會被放在一個假想的無限網格上,面朝某個特定方向(北、東、南或西),並位於一組 {x,y} 座標上,例如 {3,8},座標值往北和往東遞增。

接著機器人會收到一連串指令,此時測試設施會驗證機器人的新位置,以及它面朝哪個方向。

  • 字母字串 "RAALAL" 的意思是:
    • 向右轉
    • 前進兩次
    • 向左轉
    • 前進一次
    • 再一次向左轉
  • 假設機器人從 {7, 3} 出發,面朝北方。 那麼執行這串指令後,它應該會停在 {9, 4},面朝西方。

實作說明

測試分成 3 個步驟。

用 go test 執行所有測試,或用 -tags 選項執行特定測試。

範例:

go test                      # run all tests
go test -tags step1          # run just step 1 tests.
go test -tags 'step1 step2'  # run step1 and step2 tests

你會拿到一個原始檔 defs.go,它定義了測試程式所需的若干項目。 這個檔案依步驟分成三個區段。

步驟 1

要完成步驟 1,你需要定義 Right、Left、Advance、N、S、E、W 和 Dir。 完成步驟 1 之後再繼續進行步驟 2。

步驟 2

在步驟 1 中你實作了機器人的移動,但這還稱不上是模擬。 例如,原始碼裡的「機器人」在哪裡?「網格」又在哪裡? 把機器人動作轉換成網格位置的運算又在哪裡?是在機器人裡,還是在網格裡? 真實世界可不是這樣運作的。

步驟 2 會引入一個「房間」。 這看起來只是個小小的補充,但我們會做很大的改變,來釐清「房間」、「機器人」和「測試程式」各自的角色,並開始釐清這個模擬的物理機制。 你要把 Room 和 Robot 定義成函式,測試程式會將它們以 goroutine 的方式啟動,藉此「讓它們誕生」。 資訊會透過 Go 的 channel 在測試程式、機器人和房間之間流動。

把 Room 想成一個「物理引擎」,用來建立模型並模擬一個有牆壁和機器人的實體房間。 它應該以某種方式為房間的座標空間、機器人和牆壁的位置建立模型,並且確保例如機器人不會穿牆而過。 我們希望 Robot 是執行各種動作的代理者,但希望 Room 維持一致的真實狀態。

測試程式會建立這些 channel,並啟動 Room 和 Robot 兩者。 接著測試程式會傳送指令給 Robot。 傳送完指令後,它會關閉指令 channel。 Robot 必須接受指令,並把它正在嘗試執行的動作告知 Room。 當它偵測到指令 channel 關閉時,必須自行關閉。 房間必須解讀機器人動作所造成的物理結果。 當它偵測到機器人關閉時,會傳送一份最終報告回測試程式,說明機器人的最終位置和方向。

步驟 3

步驟 3 有三項重大改變:

  • 機器人執行的是一份腳本,而不是回應個別指令。
  • 新增一個日誌 channel,讓機器人和房間可以記錄訊息。
  • 房間允許有多個機器人同時存在並運作。

至於 Room3 送出的最終位置報告,你可以直接回傳從 robots channel 收到的那個切片,只要把位置和方向更新過就好。 以下情況必須在日誌 channel 上傳送訊息:

  • 機器人沒有名字
  • 機器人名字重複
  • 多個機器人被放在同一個位置
  • 機器人被放在房間之外
  • 腳本中出現未定義的指令
  • 來自未知機器人的動作
  • 機器人試圖前進撞上牆壁
  • 機器人試圖前進撞上另一個機器人

出處

靈感來自某知名公司的面試題目。
透過 GitHub 編輯 連結會在新視窗或分頁中開啟
Go Exercism

準備好開始 機器人模擬器 了嗎?

註冊 Exercism,透過 34 個概念165 個練習 和真人引導來學習並精通 Go,全部免費。