# Python 撲克牌模擬遊戲教學
這篇文章分享如何使用 Python 製作一個簡易的撲克牌模擬遊戲,適合初學者練習類別(class)、發牌邏輯與迴圈模擬。
---
# 用 Python 實作撲克牌玩家系統:物件導向設計介紹
本文將教你如何用 Python 建立一個撲克牌博弈模擬系統的核心類別,包括玩家(Player)、莊家(Dealer)、與賭徒(Gambler)的物件導向設計。
---
## 🎴 玩家類別設計:Player, Dealer, Gambler
撲克牌遊戲中,不同角色有不同特性。本節使用 Python 類別繼承機制,建立三個類別:
- `Player`:基本玩家,具有名字、金額、預設下注金額
- `Dealer`:莊家,繼承自 Player,並加入莊家止損限制
- `Gambler`:賭徒,繼承自 Player,並加入賭徒的預算限制
### 🧩 程式碼範例:
```python
class Player:
def __init__(self, name, money, defaultbet):
self.name = name
self.money = money
self.defaultbet = defaultbet
class Dealer(Player):
def __init__(self, name, money, defaultbet, limit):
super().__init__(name, money, defaultbet)
self.limit = limit
class Gambler(Player):
def __init__(self, name, money, defaultbet, budget):
super().__init__(name, money, defaultbet)
self.budget = budget
```
範例檔案內容如下:
## 📂 玩家資料載入:從 CSV 建立 Dealer 與 Gambler
玩家資訊通常來自外部資料來源,例如資料庫或 `.csv` 檔案。以下程式碼範例示範如何從 `players.csv` 讀取內容,並依照欄位建立 `Dealer` 和多位 `Gambler` 物件。請注意第 2 行是莊家,第 3 行開始是玩家。
```python
with open("players.csv", "r") as file:
lines = file.readlines()
dealer_info = lines[1].strip().split(",")
dealer1 = Dealer(dealer_info[1], int(dealer_info[2]), int(dealer_info[4]), int(dealer_info[3]))
players = []
for i in range(2, len(lines)):
info = lines[i].strip().split(",")
player = Gambler(info[1], int(info[2]), int(info[4]), int(info[3]))
players.append(player)
```
## 🧠 撲克牌比牌邏輯:get_hand_score()
比賽過程中,需要判斷每位玩家手上的 5 張牌所組成的牌型強度,例如是否為同花順、鐵支或兩對等。本函式 `get_hand_score()` 接收一組手牌,回傳一個二元組 `(等級, 主值)`,用以排序與比較。
- 等級對應如下:
- 8:同花順
- 7:鐵支(Four of a kind)
- 6:葫蘆(Full House)
- 5:同花(Flush)
- 4:順子(Straight)
- 3:三條(Three of a kind)
- 2:兩對(Two pair)
- 1:一對(One pair)
- 0:高牌(High card)
---
### 🧩 程式碼範例:
```python
face_rank = {
'2': 2, '3': 3, '4': 4, '5': 5,
'6': 6, '7': 7, '8': 8, '9': 9,
'10': 10, 'Jack': 11, 'Queen': 12,
'King': 13, 'Ace': 14
}
def get_hand_score(hand):
values = []
suits = []
for card in hand:
values.append(face_rank[card.face])
suits.append(card.suit)
values.sort(reverse=True)
counts = {}
for v in values:
counts[v] = counts.get(v, 0) + 1
count_list = sorted(counts.values(), reverse=True)
same_suit = all(s == suits[0] for s in suits)
if values == [14, 5, 4, 3, 2]:
is_straight = True
values = [5, 4, 3, 2, 1]
else:
is_straight = all(values[i-1] == values[i] + 1 for i in range(1, 5))
if same_suit and is_straight:
return (8, values[0])
if count_list == [4, 1]:
return (7, [v for v in counts if counts[v] == 4][0])
if count_list == [3, 2]:
return (6, [v for v in counts if counts[v] == 3][0])
if same_suit:
return (5, values[0])
if is_straight:
return (4, values[0])
if count_list == [3, 1, 1]:
return (3, [v for v in counts if counts[v] == 3][0])
if count_list == [2, 2, 1]:
return (2, max(v for v in counts if counts[v] == 2))
if count_list == [2, 1, 1, 1]:
return (1, [v for v in counts if counts[v] == 2][0])
return (0, values[0])
```
## 🎮 撲克遊戲主迴圈與勝負判斷
模擬進行 1000 回合撲克牌發牌與比對,條件如下:
- 當莊家的資金歸零或全部玩家破產,遊戲提前結束
- 每回合玩家與莊家各發 5 張牌
- 使用 `get_hand_score()` 評估牌力,進行金錢結算
- 若莊家當回合損失超過其 `limit`,則立即停止本回合
最後統計誰的錢最多,作為最終勝利者。
---
### 🧩 程式碼範例:
```python
from deck import DeckOfCards
for i in range(1000):
all_dead = True
for player in players:
if player.money > 0:
all_dead = False
if dealer1.money <= 0 or all_dead:
break
deck = DeckOfCards()
deck.shuffle()
dealer1.hand = []
for player in players:
player.hand = []
for j in range(5):
dealer1.hand.append(deck.deal_card())
for player in players:
player.hand.append(deck.deal_card())
dealer_score = get_hand_score(dealer1.hand)
dealer_lost = 0
for player in players:
if player.money <= 0:
continue
player_score = get_hand_score(player.hand)
if player_score > dealer_score:
player.money += dealer1.defaultbet
dealer1.money -= dealer1.defaultbet
dealer_lost += dealer1.defaultbet
elif player_score < dealer_score:
player.money -= player.defaultbet
dealer1.money += player.defaultbet
if dealer_lost >= dealer1.limit:
break
print(dealer1.name, dealer1.money)
for p in players:
print(p.name, p.money)
print('-'*20)
highest = dealer1.money
for player in players:
if player.money > highest:
highest = player.money
print("贏家是:")
if dealer1.money == highest:
print(dealer1.name)
for player in players:
if player.money == highest:
print(player.name)
```
---
## 🏁 結語與延伸挑戰
透過本篇文章,我們完整實作了一個以 Python 撲克牌為題材的小型模擬遊戲,從資料建模、檔案讀取、牌型評估到勝負邏輯一應俱全。
你可以嘗試進一步擴充這個專案,例如:
- 設計更詳細的下注策略與風險模型
- 加入圖形化介面或回合記錄
- 引入統計模擬觀察玩家勝率變化
希望這篇教學對你理解 Python 類別設計與模擬流程有所幫助!
> 📬 如果你有任何想法或改進建議,也歡迎留言交流 🙌