不間斷 Python 挑戰 Day 16 - 專題:21點 (Blackjack)

更新於 發佈於 閱讀時間約 9 分鐘

這篇文章將利用之前所學過的一些東西,包括if敘述、串列、while迴圈、函數等等的觀念,來實作一個撲克牌的小遊戲-21點[1]。

遊戲規則

使用一副撲克牌,不含鬼牌,由電腦扮演莊家,使用者為玩家,牌局結束後由點數高的一方獲勝,但點數不可超過21點。A可記為1點或11點,2點到10點的點數以牌面的點數計算,J、Q、K都計為10點。

遊戲與程式邏輯

  1. 隨機發給玩家一張牌。
  2. 隨機發給莊家一張牌(暗牌)。
  3. 隨機發給玩家第二張牌。
  4. 隨機發給莊家第二張牌(明牌)。
  5. 顯示莊家的明牌,並詢問玩家是否加牌,直到玩家不加牌,或是點數超過21點。
  6. 莊家的點數若不足17點必須加牌,直到點數超過或等於17點。
  7. 依以下條件依序判斷獲勝者:
    - 若玩家超過21點,則莊家獲勝,無論莊家是否超過21點。
    - 若莊家超過21點,則玩家獲勝。
    - 若玩家和莊家的點數相同,則平手。
    - 若玩家的點數大於莊家的點數,則玩家獲勝。
    - 若玩家的點數小於莊家的點數,則莊家獲勝。

程式架構

建立牌組

A到K共13種點數的牌各4張,不區分花色,A先預設為11點,J、Q、K皆為10點。

cards = [11, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10] * 4

建立發牌函數

當函數被呼叫時,從牌組中隨機選出一張牌,並將該點數的牌從牌組中移除。

def deal_card():
  card = random.choice(cards)
  cards.remove(card)
  return card

建立記點函數

先計算傳入牌組的點數總和,再根據傳入牌組的張數有不同的判斷邏輯:

  • 若傳入2張牌,不須修改點數,直接回傳。
  • 若傳入超過2張牌,且點數超過21點,檢查牌組中是否有A(11點),若有則將其改成1點。
  • 其它狀況則直接回傳點數。
def calculate_points(cards):
  total_points = sum(cards)

  # 2 cards
  if len(cards) == 2:
    return total_points

  # more than 2 cards
  if total_points > 21:
    if 11 in cards:
      cards.remove(11)
      cards.append(1)
      total_points = sum(cards)

  return total_points

建立遊戲流程函數

將遊戲流程建成一個函數play_blackjack(),依序執行:隨機發兩張牌給玩家和莊家、玩家加牌、莊家加牌、判斷贏家。

首先分別為玩家和莊家建立兩個空的牌組:

user_cards = []
dealer_cards = []

使用for迴圈為玩家和莊家隨機發兩張牌,並顯示玩家的牌和莊家的明牌:

for _ in range(2):
  user_cards.append(deal_card())
  dealer_cards.append(deal_card())

print(f"玩家的牌:{user_cards}")
print(f"莊家的明牌:{dealer_cards[1]}")

使用while迴圈持續詢問玩家是否加牌,直到玩家停止加牌,或點數超過21點:

ask_for_card = ""
while ask_for_card != "n":
  ask_for_card = input("輸入y加牌、輸入n看結果:")
  
  if ask_for_card == "y":
    user_cards.append(deal_card())
    user_points = calculate_points(user_cards)
    if user_points > 21:
      ask_for_card = "n"
    else:
      print(f"玩家的牌:{user_cards}")
    elif ask_for_card == "n":
      user_points = calculate_points(user_cards)
  else:
    print("請重新輸入!輸入y加牌、輸入n看結果:")

若莊家的牌點數小於17點,則使用while迴圈持續為莊家加牌:

dealer_points = calculate_points(dealer_cards)
while dealer_points < 17:
  dealer_cards.append(deal_card())
  dealer_points = calculate_points(dealer_cards)

顯示玩家和莊家最後的牌組:

print(f"玩家的牌:{user_cards},共{user_points}點")
print(f"莊家的牌:{dealer_cards},共{dealer_points}點")

根據「遊戲與程式邏輯」一節的規則判斷最後的贏家:

if user_points > 21:
  print("你輸了!")
elif dealer_points > 21:
  print("你贏了!")
elif user_points == dealer_points:
  print("平手!")
elif user_points > dealer_points:
  print("你贏了!")
else:
  print("你輸了!")

主程式

到目前為止,我們已經將相同功能的單位包裝成函數。主程式的部分,我們呼叫play_blackjack()函數執行遊戲流程,並使用while迴圈持續詢問玩家是否要重新開始,或是結束遊戲。

play_game = True
print("歡迎來到21點遊戲!")
play_blackjack()

while play_game == True:
  print("=======================================")
  user_input = input("重新進行遊戲?請輸入y開始、輸入n結束:")
  if user_input == "y":
    play_blackjack()
  elif user_input == "n":
    play_game = False
    print("Bye~")
  else:
    continue

遊戲畫面

歡迎來到21點遊戲!
玩家的牌:[10, 8]
莊家的明牌:3
輸入y加牌、輸入n看結果:n
玩家的牌:[10, 8],共18點
莊家的牌:[10, 3, 2, 8],共23點
你贏了!
=======================================
重新進行遊戲?請輸入y開始、輸入n結束:y
玩家的牌:[4, 11]
莊家的明牌:2
輸入y加牌、輸入n看結果:y
玩家的牌:[4, 8, 1]
輸入y加牌、輸入n看結果:y
玩家的牌:[4, 8, 1, 10],共23點
莊家的牌:[10, 2, 7],共19點
你輸了!
=======================================
重新進行遊戲?請輸入y開始、輸入n結束:n
Bye~

程式範例

https://github.com/wjweng/marathon_python/blob/master/venv/marathon_python_day16.py

[1] https://en.wikipedia.org/wiki/Blackjack


留言
avatar-img
留言分享你的想法!
avatar-img
Wei-Jie Weng的沙龍
48會員
36內容數
Wei-Jie Weng的沙龍的其他內容
2022/07/13
對於程式的初學者而言,理解程式的流程、迴圈的進行、或是變數的變化會需要一定程度將程式在腦中進行運算的能力,要一段時間熟悉與適應,尤其是當程式執行的結果不如預期時,往往是計算的過程和自己所想像的不同,這時又更難靠自己的能力找出錯誤。因此,這邊要介紹的這個工具可以將程式執行的過程逐行將變數的變化視覺化地
Thumbnail
2022/07/13
對於程式的初學者而言,理解程式的流程、迴圈的進行、或是變數的變化會需要一定程度將程式在腦中進行運算的能力,要一段時間熟悉與適應,尤其是當程式執行的結果不如預期時,往往是計算的過程和自己所想像的不同,這時又更難靠自己的能力找出錯誤。因此,這邊要介紹的這個工具可以將程式執行的過程逐行將變數的變化視覺化地
Thumbnail
2022/07/13
在上一節介紹了 JSON 資料的基本架構後,我們將改寫並擴充密碼產生器程式,讓它能夠藉由 JSON 的資料結構完成帳密搜尋的功能。
Thumbnail
2022/07/13
在上一節介紹了 JSON 資料的基本架構後,我們將改寫並擴充密碼產生器程式,讓它能夠藉由 JSON 的資料結構完成帳密搜尋的功能。
Thumbnail
2022/06/23
JSON的全名叫JavaScript Object Notation,是由Douglas Crockford所設計的一種資料格式,最初應用在JavaScript程式語言中,做為一種資料交換的格式,而後被廣泛運用在Web開發與NoSQL資料庫,現今已成為一種重要的資料格式。
Thumbnail
2022/06/23
JSON的全名叫JavaScript Object Notation,是由Douglas Crockford所設計的一種資料格式,最初應用在JavaScript程式語言中,做為一種資料交換的格式,而後被廣泛運用在Web開發與NoSQL資料庫,現今已成為一種重要的資料格式。
Thumbnail
看更多
你可能也想看
Thumbnail
「欸!這是在哪裡買的?求連結 🥺」 誰叫你太有品味,一發就讓大家跟著剁手手? 讓你回購再回購的生活好物,是時候該介紹出場了吧! 「開箱你的美好生活」現正召喚各路好物的開箱使者 🤩
Thumbnail
「欸!這是在哪裡買的?求連結 🥺」 誰叫你太有品味,一發就讓大家跟著剁手手? 讓你回購再回購的生活好物,是時候該介紹出場了吧! 「開箱你的美好生活」現正召喚各路好物的開箱使者 🤩
Thumbnail
賓果的遊戲描述 在一個5x5的方陣上隨機填充1~25的數字。 玩家(使用者) 和 電腦(AI)輪流叫一個號碼,最先占據一整條直線連線的獲勝。 就像小時候玩的bingo 賓果連線遊戲一樣! (可以是占據兩條對角線,可以是占據水平直線,可以是占據垂直直線)
Thumbnail
賓果的遊戲描述 在一個5x5的方陣上隨機填充1~25的數字。 玩家(使用者) 和 電腦(AI)輪流叫一個號碼,最先占據一整條直線連線的獲勝。 就像小時候玩的bingo 賓果連線遊戲一樣! (可以是占據兩條對角線,可以是占據水平直線,可以是占據垂直直線)
Thumbnail
你一定有玩過猜拳遊戲,但你知道怎麼用Python寫一個猜拳遊戲嗎?今天我要分享一個簡單又好玩的程式碼,讓你可以和電腦對戰! 首先,我們要導入random模組,這個模組可以讓我們隨機生成一個數字,代表電腦出的拳。 然後,我們要用input函數讓使用者輸入自己出的拳,0代表剪刀,1代表石頭,2代表
Thumbnail
你一定有玩過猜拳遊戲,但你知道怎麼用Python寫一個猜拳遊戲嗎?今天我要分享一個簡單又好玩的程式碼,讓你可以和電腦對戰! 首先,我們要導入random模組,這個模組可以讓我們隨機生成一個數字,代表電腦出的拳。 然後,我們要用input函數讓使用者輸入自己出的拳,0代表剪刀,1代表石頭,2代表
Thumbnail
小穎每次看到小賢在變魔術,都覺得很帥,於是他也去看了一撲克牌魔術大全,從中他選擇了一個魔術要來跟小賢較量一下。 下課時小穎走到小賢旁邊說:「小賢,我跟你玩個魔術。」 小賢有點驚訝地說:「你沒說錯吧!」 「真的啦!」一說完,小穎就拿出一副撲克牌,交到小賢手上。
Thumbnail
小穎每次看到小賢在變魔術,都覺得很帥,於是他也去看了一撲克牌魔術大全,從中他選擇了一個魔術要來跟小賢較量一下。 下課時小穎走到小賢旁邊說:「小賢,我跟你玩個魔術。」 小賢有點驚訝地說:「你沒說錯吧!」 「真的啦!」一說完,小穎就拿出一副撲克牌,交到小賢手上。
Thumbnail
入門系列篇主要講解基本規則,適合初學者,一起輕鬆學圍棋吧🌟
Thumbnail
入門系列篇主要講解基本規則,適合初學者,一起輕鬆學圍棋吧🌟
Thumbnail
桌遊的魅力真的很特別,即使是現在大家都習慣滑手機的時代,有時候在聚會時特地玩一款桌遊或紙牌遊戲,還是能帶給大家很多的歡笑。 特別記錄自己在過年時玩到的一款撲克接龍,它有一些數學的概念很適合作為教具使用,當然本身也簡單好上手,遊玩的人數也算多,推薦給大家!
Thumbnail
桌遊的魅力真的很特別,即使是現在大家都習慣滑手機的時代,有時候在聚會時特地玩一款桌遊或紙牌遊戲,還是能帶給大家很多的歡笑。 特別記錄自己在過年時玩到的一款撲克接龍,它有一些數學的概念很適合作為教具使用,當然本身也簡單好上手,遊玩的人數也算多,推薦給大家!
Thumbnail
遊戲規則如下: 此方法可以套用在任何過年會玩到的賭博遊戲,如麻將、十點半、大老二......等。 開始前,每人先拿出固定金額本金投入,例如每人500。(可以先拿一個罐子裝)。 遊戲每一輪結算一次(依遊戲而定,例如:十點半每人輪流當莊2次為一輪),並需要一名計分人員(可以是參賽者)。 優點
Thumbnail
遊戲規則如下: 此方法可以套用在任何過年會玩到的賭博遊戲,如麻將、十點半、大老二......等。 開始前,每人先拿出固定金額本金投入,例如每人500。(可以先拿一個罐子裝)。 遊戲每一輪結算一次(依遊戲而定,例如:十點半每人輪流當莊2次為一輪),並需要一名計分人員(可以是參賽者)。 優點
Thumbnail
近期是上班族最期待的新年假期,先祝大家新年快樂。 雖然再過幾天大家就得回去面對現實上班,但總歸還有2~3天可以好好耍耍廢、補充點精氣神(?) 說到過年,除了和親人一起圍爐、吃吃東西、聊的天南地北外,最近重要的就是一起,玩 遊 戲! 以下介紹我自己過年時會玩的幾款遊戲。 麻將 德州撲克 21點
Thumbnail
近期是上班族最期待的新年假期,先祝大家新年快樂。 雖然再過幾天大家就得回去面對現實上班,但總歸還有2~3天可以好好耍耍廢、補充點精氣神(?) 說到過年,除了和親人一起圍爐、吃吃東西、聊的天南地北外,最近重要的就是一起,玩 遊 戲! 以下介紹我自己過年時會玩的幾款遊戲。 麻將 德州撲克 21點
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News