iT邦幫忙

2024 iThome 鐵人賽

DAY 27
0
Python

用 Python 打造你的 Discord BOT系列 第 27

[Day 27] 開發實戰 (一):定義需求

  • 分享至 

  • xImage
  •  

接下來,以我開發的 Discord BOT 為例,來看看怎麼靈活應用前面所學吧!

進度

接下來會用實戰演練的角度出發,以我的 Discord BOT 為例,去實作出一個符合需求的 Discord BOT 出來。在這個過程中,各位可以思考看看,如果是你,會怎麼實作這些功能?

今天以說明 Discord BOT 的需求為主,同時也會盡量說明這些需求背後的原因。

遊戲機制

在介紹之前,需要先稍微解釋一下遊戲機制。

遊戲中有一類稱為「線索」的道具,一共有編號 1 到 7 號七種不同的線索,玩家每天可以隨機蒐集到數個線索。當玩家蒐集完整一套 (1 到 7 號) 線索之後,可以獲得遊戲獎勵。此外,玩家也可以贈送線索給其他玩家,贈送和接收線索同樣也可以獲得遊戲獎勵,但接收來的線索不能再繼續轉送。不過,接收線索的獎勵有每日上限,一天最多拿三次。

其他沒那麼重要的細節就省略了

線索效益最佳化

這一個部分比較偏數學,會介紹計算最佳化結果的思路,與 Discord BOT 的需求有一點點關係。不過,就算直接跳過頂多只是不理解為何要開那樣的需求規格而已,不影響後續實作 Discord BOT。

懶人包:這個計算最佳化的程式,會需要評估在各種情況下的所有交換組合之中,哪個做法最好。不過,計算量可能很大,因此這部分不會使用 Python 計算。

先從比較簡單的情況開始討論。

2 個玩家

當玩家 A 與玩家 B 各有一套完整線索時,最理想的做法是,玩家 A 和玩家 B 把所有的線索都互相交換,既可以拿到贈送與接收的獎勵,也可以拿到蒐集完整的獎勵。

3 個玩家

如果有三個玩家各有一套完整線索時,就是三個人互換,也是 A 給 B,B 給 C,C 再給 A。

讓我們換個方式來表達:

A -> B   1234567
B -> C   1234567
C -> A   1234567

當然,要完全反過來也可以,所以 3 個玩家時,一共有 2 種做法。

4 個玩家

從這時候開始,可能的做法開始變多了。我們可以 4 個人依序給下一個人,也可以倆倆分組進行對換。

A -> B   1234567
B -> C   1234567
C -> D   1234567
D -> A   1234567

或是

A -> B   1234567
B -> A   1234567
C -> D   1234567
D -> C   1234567

此時,可能的做法變成是 4!/4 (一個給一個) + (C 4 取 2)/2 (分成兩組),也就一共是 9 種做法。

更多玩家

這邊就不列詳細的計算過程了,直接秀結果。

  • 5 位玩家:44 種
  • 6 位玩家:265 種
  • 7 位玩家:1854 種
  • 8 位玩家:14833 種

目前我們一共有 8 位玩家... 😨

如果不是一整套線索...

假如每位玩家都只有部分的線索,那就只交換該玩家所擁有的線索,並且只會有同號線索交換 (不會有線索 2 換線索 5 的狀況發生)。

例如玩家 A 有 123,玩家 B 有 234,玩家 C 有 1234,那麼
就 2、3 號線索三人互換,1 號線索 AC 互換,4 號線索 BC 互換。

以下就會是一個可能的做法:

A -> B   23
A -> C   1

B -> C   234

C -> A   123
C -> B   4

如果不一定全部的線索都要交換...

由於交換完的線索有保存期限的問題 (10 天),所以拿到線索就立刻拿出去交換不一定是個好選擇,有時候等確定已經湊滿一套再交換會是比較穩妥的作法。

因此,應該要把當天的線索分成兩部分:

  1. 可以交換的線索
  2. 可以交換線索中,一定要交換的線索

如果把前一個範例的狀況再調整一下:

  • A:123, 23
  • B:234, 23
  • C:1234, 234

以下會是一個可能的做法:

A -> B   23

B -> C   234

C -> A   23
C -> B   4

注意到了嗎?此時,玩家 A 的 1 號線索就沒有參與交換,畢竟它沒有把它列入一定要交換的線索。而玩家 B 雖然沒有一定要換 4 號線索,但因為玩家 C 想要換,而在場的只剩下玩家 B 有,所以玩家 B 參與了 4 號線索的交換。

喘口氣一下

這種討論交換線索的問題,這其實跟一個經典的數學問題非常像,那就是:錯排問題

有 n 個元素排成一列。如果這 n 個元素都不在原本位置上,這樣的排列就稱為錯排。

不過,我們要計算的不是有一共有多少種可能的做法,而是要知道從這些可能的做法中,哪個對我們來說最好?此外,對於那些可換可不換的線索,到底是要換還是不要換?

所以,需要有一個評分機制,來幫助我們判斷哪個做法比較好。不過,評分機制就跟 Discord BOT 沒有任何關係了,這邊就不繼續討論了。

小小結論

這個計算最佳化的程式,會需要評估在各種情況下 (有些線索可換可不換) 的所有交換組合 (例如:四人到底是倆倆交換還是依序傳遞一輪比較好?) 之中,哪個做法最好。

最佳化程式的實作

巨大的計算量

這個計算程式的計算量,會受到三個因素影響:

  1. 玩家數量
  2. 要交換的線索數量
  3. 可換可不換的線索數量

尤其是第三個,每多一個這樣的線索,需要評分的可能做法數量就直接翻倍。這導致這個計算可能會非常花時間,因此這個計算程式是選擇用 C 語言做開發的。

不是我寫的,我對 C 語言一竅不通...

Python 與 C 語言的整合

這部分我選擇的做法是,把 C 語言的計算程式編譯成一個執行檔,輸入和輸出就靠讀寫 txt 檔,Python 只要把計算程式所需的資料寫入一個檔案,等計算完畢後,再去讀取另一個專門記錄結果的檔案。

操作流程

在列出需求規格之前,還需要設想一下預期的操作流程。規劃如下:

  1. 每個人每天都在特定頻道內留言,告知兩件事:
    • 可以交換的線索
    • 一定要交換的線索
  2. 當每個人都留言後,呼叫 Discord BOT 開始計算。等待一段時間後,Discord BOT 就會公告計算結果在特定頻道內。

使用者故事 (User Story)

接下來,就是設想各種情境,並列出使用者故事:

1. 線索管理

  • 作為頻道成員,我可以輸入線索,讓 Discord BOT 取得並儲存相關資訊。
  • 作為頻道成員,若我輸入的線索格式不正確,會收到錯誤提示,且該線索不會被記錄。
  • 作為頻道成員,我可以編輯線索,並且 Discord BOT 會更新該線索資訊並檢查其格式。
  • 作為頻道成員,我可以刪除線索,Discord BOT 會相應更新線索資訊。
  • 作為頻道成員,我可以下達指令,要求根據歷史訊息來更新已儲存的線索資訊。
  • 作為頻道成員,我可以下達指令,要求查看目前儲存的線索資訊。
  • 作為頻道成員,我可以為其他頻道成員設定線索。

2. 計算最佳做法功能

  • 作為頻道成員,我可以下達指令要求開始計算。
  • 作為頻道成員,當我要求開始計算時,Discord BOT 會檢查是否所有成員當天都已提交線索,若不是,則會彈出提示訊息詢問是否確定要進行計算。
  • 作為頻道成員,我可以在計算開始前查看本次計算的組合數量。
  • 作為頻道成員,在 Discord BOT 計算時,我會看到「正在輸入…」的提示。
  • 作為頻道成員,計算完成後,我可以在特定頻道中看到 Discord BOT 提供的結果。
  • 作為頻道成員,我可以下達指令,查看當前最新的計算結果。

3. 其他功能

  • 作為頻道成員,我可以享有 Discord BOT 定時檢查所有人是否已報線索的功能,若有未報者,該成員會被 Tag 提醒。
  • 作為頻道成員,我可以開啟或關閉 Discord BOT 的定時檢查功能。
  • 作為頻道成員,我可以查看 Discord BOT 的使用指南或教學。

4. 使用限制

  • 線索只能在特定頻道中提交。
  • 只有特定的頻道成員可以提交線索。

補充:「在頻道內輸入線索」簡稱為「報線索」

小結

今天主要是介紹我對於我的 Discord BOT 的功能需求,並說明背後的原因 (遊戲機制)。最後,大家可以思考看看,如何使用 discord.py 完成上面所條列出來的功能?


上一篇
[Day 26] 部屬 (四):GCP (下)
下一篇
[Day 28] 開發實戰 (二):專案架構與主程式
系列文
用 Python 打造你的 Discord BOT31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言