---
# System prepended metadata

title: Python 撲克牌模擬遊戲教學

---

# 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 類別設計與模擬流程有所幫助！

> 📬 如果你有任何想法或改進建議，也歡迎留言交流 🙌