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],以此類推。
填入正確的索引,讓每個 print 印出註解說的那張牌。填完按「執行看看」!
ranks = ["A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"] print(ranks[]) # 印出第一張:A print(ranks[]) # 印出最後一張:K print(ranks[]) # 印出第五張:5
切片 [a:b] 會取出索引 a 到 b-1 的元素。試著填入正確的切片!
nums = [10, 20, 30, 40, 50] print(nums[]) # [20, 30] print(nums[]) # [10, 20] 從頭取 2 個 print(nums[]) # [40, 50] 從索引 3 到底
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 = ["7", "A", "3"]
hand.("K")
print("加入 K:", hand)
hand.()
print("排序後:", hand)
last = hand.()
print("抽出:", last)
print("剩下:", hand)
| 操作 | 語法 | 說明 |
|---|---|---|
| 建立 | 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)
完成迴圈,讓它印出每張牌和編號。
hand = ["A♠", "7♥", "K♦", "3♣", "10♠"]
i, card (hand):
print(f"第 {i+1} 張:{card}")
一行就能產生或過濾 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}")
tuple 可以一次把值拆給多個變數,叫做「解包」。完成下面的程式!
deck = [("♠", "A"), ("♥", "K"), ("♦", "7"), ("♣", "3")]
for , in deck:
print(f"{}{}")
用「鍵」查找「值」,就像查字典:
# 每張牌面對應幾點
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 — 檢查玩家是否存在
dict 有 keys()、values()、items() 三種方法,輸出完全不同。填對後執行看看!
scores = {"小明": 100, "小華": 85, "小美": 90}
print("--- 只印名字 ---")
for name in scores.():
print(name)
print("--- 只印分數 ---")
for val in scores.():
print(val)
print("--- 名字 + 分數 ---")
for name, score in scores.():
print(f"{name}:{score} 分")
# 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 去重的特性!
& 交集、| 聯集、- 差集。填入正確的運算符號,執行看看結果!
p1 = {"A", "K", "Q", "7"}
p2 = {"K", "3", "7", "J"}
common = p1 p2
print("共同的牌:", common)
all_cards = p1 p2
print("全部的牌:", all_cards)
only_p1 = p1 p2
print("只有 P1 有:", only_p1)
| list | tuple | dict | set | |
|---|---|---|---|---|
| 符號 | [ ] | ( ) | { k: v } | { } |
| 有順序 | O | O | O (3.7+) | X |
| 可修改 | O | X | O | O |
| 可重複 | O | O | 鍵不行 | X |
| 取值方式 | 索引 [0] | 索引 [0] | 鍵 ["A"] | 無法直接取 |
| 撲克牌比喻 | 手牌、牌堆 | (花色, 牌面) | 牌面→點數 | 有哪些花色 |
根據需求選出最適合的容器類型。
# 手牌可以加牌、出牌 → 用可修改的有序容器 hand = "A", "7", "K" # 一張牌的花色和牌面固定不變 → 用不可修改的容器 card = "♠", "A" # 牌面對應點數,用名字查值 → 用鍵值對 values = "A": 14, "K": 13 print(hand, card, values)
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']}")
list 裡面放 dict,要用兩層取值。先 [索引] 再 [鍵]。
players = [
{"name": "小明", "hand": ["A♠", "K♥"], "score": 10},
{"name": "小華", "hand": ["Q♠", "J♣"], "score": 5},
]
# 印出小明的名字
print(players[][])
# 印出小華的手牌
print(players[][])
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):
p, c = deck.pop(), deck.pop()
pv, cv = get_value(p), get_value(c)
print(f"第 {r} 回合")
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} 電腦")
學會了 list、tuple、dict、set 四種資料結構,
還用它們組出了一個完整的撲克牌遊戲!