iT邦幫忙

2023 iThome 鐵人賽

DAY 16
0
自我挑戰組

chatGPT 帶你從零開始寫 websocket 連線遊戲系列 第 16

D16 探索事件溯源 - 以簡易的井字遊戲為例

  • 分享至 

  • xImage
  •  

在昨天我提到事件溯源,但老實說我對這個概念還是不太清楚,所以今天又接續再花了一些時間研究它。我想先簡單地總結它,然後以 chatGPT 提供的簡單範例作結尾

事件溯源的好處 (賣點)

  1. 可追蹤性和可重現性:事件溯源可以幫助你追蹤過去的事件,並重建應用程式的狀態,這對於故障排除、測試和日誌記錄非常有價值。它可以捕獲應用程式運行時的每個操作,使問題的追蹤變得更容易。

  2. 歷史記錄和版本控制:事件溯源允許你查看過去的應用程式狀態,並比較不同時刻的狀態。這對於版本控制和歷史記錄非常有用,特別是在多玩家遊戲或競技場上。

  3. 分佈式系統:對於分佈式系統來說,事件溯源可以幫助確保不同部分之間的一致性,因為它提供了一個單一的、可信的事件源頭。

  4. 事件驅動的架構:事件溯源促使開發者採用事件驅動的架構,這有助於解耦不同部分的應用程式,提高了可維護性和擴展性。

  5. 回測和仿真:事件溯源可以用於回測和仿真,以評估應用程式的性能和行為,並優化其設計。

壞處

  1. 需要先熟悉 DDD, 聚合根之類的概念
  2. 可能會被置入 EventStore DB,會增加認知負擔

井字遊戲範例

為了降低認知負擔,所以請 chatGPT 先提供簡單的範例當學習範本

# 定義遊戲事件類型
class GameEvent:
    def __init__(self, event_type, data=None):
        self.event_type = event_type
        self.data = data

# 定義遊戲狀態
class GameState:
    def __init__(self):
        self.board = [[' ' for _ in range(3)] for _ in range(3)]
        self.current_player = 'X'

    def make_move(self, row, col):
        if self.board[row][col] == ' ':
            self.board[row][col] = self.current_player
            self.current_player = 'O' if self.current_player == 'X' else 'X'

# 定義事件記錄和回放
class EventSourcingGame:
    def __init__(self):
        self.events = []
        self.state = GameState()

    def record_event(self, event):
        self.events.append(event)
        # 執行事件處理
        self.handle_event(event)

    def handle_event(self, event):
        if event.event_type == 'move':
            row, col = event.data
            self.state.make_move(row, col)

    def replay_events(self):
        for event in self.events:
            self.handle_event(event)

# 創建遊戲實例
game = EventSourcingGame()

# 玩家進行動作並記錄事件
game.record_event(GameEvent('move', (0, 0)))
game.record_event(GameEvent('move', (1, 1)))
game.record_event(GameEvent('move', (0, 1)))
game.record_event(GameEvent('move', (1, 0)))

# 回放事件以重建遊戲狀態
game.replay_events()

# 打印最終遊戲狀態
for row in game.state.board:
    print(' '.join(row))

疑問 1:move 事件沒有行動玩家?

事件通常設計為包含足夠的信息來描述一個操作,但不應包含過多的與邏輯相關的信息。玩家執行操作的信息通常可以在事件處理過程中由當前遊戲狀態派生,這有助於保持事件的簡潔性和獨立性,並使事件回放更容易實現。

疑問 2:如何保存遊戲初始化過程中的隨機事件?

可以獨立出 game_init 事件,把隨機事件的結果保存下來。這樣可以讓事件本身變得更單純,不用再額外維護多餘的邏輯。其實在這也可以看出事件溯源真正保存的是已發生的事件紀錄,對於中間的隨機過程其實不怎麼關心

詳細問答過程在此 => 完整問答紀錄


上一篇
D15 驅動遊戲前進的是什麼? - 談談遊戲循環、狀態機、事件溯源
下一篇
D17 繼續討論 - 從遊戲循環到狀態機的演進
系列文
chatGPT 帶你從零開始寫 websocket 連線遊戲31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言