嗨,各位程式碼冒險家!歡迎來到我的 「順著感覺走!從零開始的 Python & Vibe Coding 遊戲創作」第十九天。在任何卡牌遊戲中,卡牌的順暢流動都是維繫遊戲節奏與策略深度的命脈。今天,我們將深入 GameManager
的內部,揭示《奇幻卡牌競技場》是如何透過一系列精密的方法,管理從牌組(Deck)、手牌(Hand)、桌面牌堆(Center Pile) 到棄牌堆(Discard Pile) 的完整生命週期。
這些機制不僅確保了遊戲的公平性與不可預測性,更是實現回合推進、資源補充與策略平衡的程式碼基石。
遊戲的起點,始於一個完整且經過洗牌的牌組。這個任務由 initialize_game_elements
方法負責,它確保了每場對局的獨特性與公平性。
gamemanager.py
)def initialize_game_elements(self):
GameManager.play_battle_music() # 播放戰鬥音樂
# 1. 建立完整的 54 張牌組
for card_type in CardType:
for _ in range(6): # 每種職業卡牌各有 6 張
self.full_deck.append(Card(card_type))
# 2. 隨機洗牌
random.shuffle(self.full_deck)
self.remaining_deck = list(self.full_deck)
# 3. 初始發牌給玩家
initial_deal_size = min(10, self.max_hand_size)
for player in self.players:
for _ in range(initial_deal_size):
if self.remaining_deck:
player.hand.append(self.remaining_deck.pop())
# 4. 補充初始桌面牌堆
self._refill_center_pile_initial(8) # 初始放置 8 張牌
# ... 更新遊戲狀態
self.turn_count = 1
self.game_state = "PLAYER_TURN"
for
迴圈遍歷 CardType
這個 Enum(列舉) 的所有成員,並為每種職業類型建立 6 張 Card
物件,最終構成一副 54 張的完整牌組(full_deck
)。random.shuffle()
函式是實現遊戲不可預測性的關鍵。它會原地打亂 self.full_deck
清單中的所有卡牌順序。remaining_deck
)中抽取 10 張手牌,同時桌面牌堆(center_pile
)會被補充至 8 張。這些初始設定為整場遊戲奠定了戰術基礎。advance_turn
)advance_turn
方法是回合轉換之間的總管,它在每個回合結束後被呼叫,負責處理所有與卡牌資源相關的結算與補充,是維持遊戲持續進行的關鍵。
gamemanager.py
)def advance_turn(self):
current_player = self.get_current_player()
# 1. 手牌上限處理 (強制棄牌)
while len(current_player.hand) > self.max_hand_size:
if current_player.hand:
discarded = current_player.hand.pop(random.randint(0, len(current_player.hand)-1))
self.discard_piles[current_player].append(discarded)
# 2. 手牌補充
cards_to_draw_for_hand = 0
if len(current_player.hand) < 5:
cards_to_draw_for_hand = 2
for _ in range(cards_to_draw_for_hand):
if self.remaining_deck:
drawn_card = self.remaining_deck.pop()
current_player.hand.append(drawn_card)
# 3. 桌面牌堆補充
cards_to_draw_for_center = self.min_center_cards - len(self.center_pile)
if cards_to_draw_for_center > 0:
for _ in range(cards_to_draw_for_center):
drawn_card = self.draw_card_to_center()
if not drawn_card:
break # 牌組已空,停止補充
# ... 切換玩家、更新回合數等
手牌上限處理(強制棄牌):
self.max_hand_size
(預設為 10 張)。while
迴圈,使用 random.randint
隨機選取一張超出的手牌,並透過 pop()
方法將其從玩家手牌 (current_player.hand
) 移除,再加入到該玩家的棄牌堆 (self.discard_piles
) 中。這個機制有效地防止了玩家囤積過多手牌,迫使其進行策略性出牌。手牌補充:
current_player.hand
的長度。若小於 5,則從 self.remaining_deck
中 pop()
兩張卡牌並 append()
到玩家手牌中。這確保了玩家在下個回合總有足夠的戰術選擇,避免因無牌可出而陷入僵局。桌面牌堆補充:
self.center_pile
) 的卡牌數量低於 self.min_center_cards
(預設為 5 張)時。draw_card_to_center
方法,從牌組中翻牌到桌面,直到滿足最低數量為止。這保證了戰場中央始終有足夠的卡牌供雙方進行配對,維持遊戲的互動性。透過 initialize_game_elements
的開局設定與 advance_turn
在每回合間的精準調控,GameManager
成功地建立了一套穩定而動態的卡牌生態系統。從洗牌、發牌,到回合結束時的強制棄牌與自動補充,每一個環節都經過精心設計,確保了遊戲體驗的流暢性與策略深度。
明天,我們將聚焦於遊戲中最核心的互動——玩家如何進行卡牌配對,以及那激動人心的「自動連擊」是如何在程式碼中實現的。敬請期待!