Lists, Tuples & Dictionaries
用撲克牌建出完整的牌組和遊戲!
Python 提供不同的「容器」來存放多筆資料,就像生活中不同的收納工具:
有順序、可以隨時抽出或插入書。
像你的手牌,可以加牌、出牌、重排。
裝好就不能改,保證資料不被動到。
像一張牌的(花色, 牌面),印好就不會變。
用名字查電話,用鍵查值。
像牌面 → 點數的對照表。
丟進去自動去除重複,沒有順序。
像檢查「有哪些不同的花色」。
list:一副牌hand = ["A", "7", "K"]# 一副牌的 13 個牌面
ranks = ["A", "2", "3", "4", "5", "6", "7",
"8", "9", "10", "J", "Q", "K"]
print(ranks[0]) # A(索引從 0 開始)
print(ranks[-1]) # K(-1 是最後一個)
print(ranks[0:3]) # ['A', '2', '3'](切片)
print(len(ranks)) # 13(長度)
第一張牌是 [0],第二張是 [1],以此類推。
hand.append("K")
hand.pop(0)
len(hand)
hand = ["7", "A", "3"]
hand.append("K") # 加到末尾 → ['7','A','3','K']
hand.insert(0, "2") # 插入到最前面
hand.remove("3") # 移除指定的牌
popped = hand.pop() # 移除並回傳最後一張
hand.sort() # 排序
hand.reverse() # 反轉順序
print("A" in hand) # True/False — 手上有沒有 A?
| 操作 | 語法 | 說明 |
|---|---|---|
| 建立 | hand = ["A", "7", "K"] | 用 [ ] 包住,逗號隔開 |
| 取值 | hand[0] | 索引從 0 開始 |
| 切片 | hand[1:3] | 取索引 1 到 2(不含 3) |
| 長度 | len(hand) | 有幾個元素 |
| 加入 | hand.append("Q") | 加到末尾 |
| 插入 | hand.insert(0, "2") | 插入指定位置 |
| 移除 | hand.remove("7") | 移除指定值(第一個) |
| 抽出 | hand.pop() | 移除並回傳最後一個 |
| 排序 | hand.sort() | 由小到大排列 |
| 檢查 | "A" in hand | 是否包含某值 |
for 走訪手牌hand = ["A♠", "7♥", "K♦", "3♣", "10♠"]
# 方法 1:直接走訪每張牌
for card in hand:
print(card)
# 方法 2:用 enumerate 同時取得索引和值
for i, card in enumerate(hand):
print(f"第 {i+1} 張:{card}")
# 方法 3:用 range + 索引
for i in range(len(hand)):
print(f"hand[{i}] = {hand[i]}")
不需要索引 → 用 for card in hand
需要索引 → 用 for i, card in enumerate(hand)
一行就能產生或過濾 list:
# 傳統寫法:產生一副牌
suits = ["♠", "♥", "♦", "♣"]
ranks = ["A","2","3","4","5","6","7","8","9","10","J","Q","K"]
deck = []
for s in suits:
for r in ranks:
deck.append(r + s)
# List Comprehension:一行搞定!
deck = [r + s for s in suits for r in ranks]
print(len(deck)) # 52
print(deck[:5]) # ['A♠', '2♠', '3♠', '4♠', '5♠']
# 過濾:只要黑桃
spades = [card for card in deck if "♠" in card]
print(spades) # ['A♠', '2♠', ..., 'K♠']
import random
def create_deck():
"""建立一副 52 張的撲克牌"""
suits = ["♠", "♥", "♦", "♣"]
ranks = ["A","2","3","4","5","6","7","8","9","10","J","Q","K"]
return [r + s for s in suits for r in ranks]
def deal(deck, n=5):
"""從牌堆抽 n 張牌(會從牌堆移除)"""
hand = []
for i in range(n):
card = deck.pop() # 從牌堆頂抽一張
hand.append(card)
return hand
# --- 使用 ---
deck = create_deck()
random.shuffle(deck) # 洗牌(就地打亂)
print(f"牌堆共 {len(deck)} 張")
my_hand = deal(deck, 5)
print(f"你的手牌:{my_hand}")
print(f"牌堆剩 {len(deck)} 張")
一張牌可以用 (花色, 牌面) 的 tuple 表示:
# tuple 用小括號
card = ("♠", "A")
print(card[0]) # ♠
print(card[1]) # A
# tuple 不能修改!
# card[0] = "♥" # ❌ TypeError!
# 用 tuple 建牌組
deck = [("♠","A"), ("♥","K"), ("♦","7"), ("♣","3")]
for suit, rank in deck:
print(f"{rank}{suit}")
用「鍵」查找「值」,就像查字典:
# 每張牌面對應幾點
card_values = {
"A": 14, "K": 13, "Q": 12, "J": 11,
"10": 10, "9": 9, "8": 8, "7": 7,
"6": 6, "5": 5, "4": 4, "3": 3, "2": 2
}
print(card_values["A"]) # 14
print(card_values["7"]) # 7
print(card_values.get("Joker", 0)) # 0(找不到時的預設值)
list:用數字索引 [0], [1], [2]
dict:用有意義的鍵 ["A"], ["K"],語意更清楚
scores = {"小明": 0, "小華": 0}
# 新增 / 修改
scores["小美"] = 0 # 新增玩家
scores["小明"] = 10 # 小明加分
# 刪除
del scores["小美"]
# 遍歷
for player, score in scores.items():
print(f"{player}:{score} 分")
# 常用方法
print(scores.keys()) # dict_keys(['小明', '小華'])
print(scores.values()) # dict_values([10, 0])
print("小明" in scores) # True — 檢查玩家是否存在
# set 自動去除重複
hand = ["A", "7", "A", "K", "7"]
unique = set(hand)
print(unique) # {'A', '7', 'K'}
# 用途 1:檢查手牌有幾種不同的牌
print(f"有 {len(set(hand))} 種不同的牌")
# 用途 2:找出兩個玩家的共同牌
p1 = {"A", "K", "Q", "7"}
p2 = {"K", "3", "7", "J"}
print(p1 & p2) # {'K', '7'} 交集 — 共同的牌
print(p1 | p2) # 聯集 — 所有的牌
print(p1 - p2) # {'A', 'Q'} 差集 — p1 有但 p2 沒有
之前用 len(set(guess)) != 4 檢查數字是否重複,就是利用 set 去重的特性!
| list | tuple | dict | set | |
|---|---|---|---|---|
| 符號 | [ ] | ( ) | { k: v } | { } |
| 有順序 | O | O | O (3.7+) | X |
| 可修改 | O | X | O | O |
| 可重複 | O | O | 鍵不行 | X |
| 取值方式 | 索引 [0] | 索引 [0] | 鍵 ["A"] | 無法直接取 |
| 撲克牌比喻 | 手牌、牌堆 | (花色, 牌面) | 牌面→點數 | 有哪些花色 |
list 裡面放 dict,組合出複雜的資料:
players = [
{"name": "小明", "hand": ["A♠", "K♥", "7♦"], "score": 0},
{"name": "小華", "hand": ["Q♠", "J♣", "10♥"], "score": 0},
]
# 取得小明的手牌
print(players[0]["hand"]) # ['A♠', 'K♥', '7♦']
# 印出所有玩家的資訊
for p in players:
print(f"{p['name']}:{p['hand']},{p['score']} 分")
# 找出分數最高的玩家
best = max(players, key=lambda p: p["score"])
print(f"目前領先:{best['name']}")
import random
def create_deck():
suits = ["♠", "♥", "♦", "♣"]
ranks = ["A","2","3","4","5","6","7","8","9","10","J","Q","K"]
return [r + s for s in suits for r in ranks]
values = {"A":14,"K":13,"Q":12,"J":11,
"10":10,"9":9,"8":8,"7":7,"6":6,"5":5,"4":4,"3":3,"2":2}
def get_value(card):
return values[card[:-1]] # 去掉花色取牌面
deck = create_deck()
random.shuffle(deck)
p_score, c_score = 0, 0
print("🃏 撲克牌比大小!共 5 回合\n")
for r in range(1, 6):
input(f"--- 第 {r} 回合,按 Enter 翻牌 ---")
p, c = deck.pop(), deck.pop()
pv, cv = get_value(p), get_value(c)
print(f"你:{p}({pv}點) vs 電腦:{c}({cv}點)")
if pv > cv:
p_score += 1
print("→ 你贏!\n")
elif pv < cv:
c_score += 1
print("→ 電腦贏!\n")
else:
print("→ 平手!\n")
print(f"最終比分 — 你 {p_score} : {c_score} 電腦")
print("🎉 你獲勝!" if p_score > c_score else
"😢 電腦獲勝!" if c_score > p_score else "🤝 平手!")
學會了 list、tuple、dict、set 四種資料結構,
還用它們組出了一個完整的撲克牌遊戲!