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

閱讀時間約 8 分鐘
這篇文章將利用之前所學過的一些東西,包括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~

程式範例

avatar-img
47會員
36內容數
留言0
查看全部
avatar-img
發表第一個留言支持創作者!
Wei-Jie Weng的沙龍 的其他內容
在前面的文章中我們學習了關於字典的基本用法,今天再討論更多關於字典的其它用法,以及它和串列、元組等的關聯。
在程式設計中,我們會使用到一些固定不會變動的資料內容,例如一年的月份、物體的邊長、過去一周的氣溫等等,使用串列的結構固然也可以用來儲存這些資料,但串列可以被新增或刪除,不能有效保護這類不可變動的資料。因此,Python也提供了另一種形式的資料結構,稱為元組,它的資料結構和串列相同,但資料的內容不可變
當我們查字典時,會先找到想查詢的單字在字典裡的位置,才能在那個位置找到單字的定義;在Python中,也有一個類似的資料結構稱作字典,字典的鍵(key)就對應到我們要查詢的單字,字典的值(value)則是該單字的定義。
隨著程式的功能愈來愈複雜,程式碼也愈來愈多,若程式從頭寫到尾沒有任何的段落,可讀性會愈來愈差,甚至會發現同樣的一段程式碼重覆很多遍,因為類似的功能區塊在程式中可能會一再出現。這樣的程式碼不利於多人的協作開發,即使是寫作者本身在一段時間後回來看,可能也難以一眼就掌握程式的主要架構。
另一種迴圈的形式是while迴圈,和for迴圈常常可以達到相同的功能,差別在於for迴圈是在一定的範圍內迭代,例如從1到100,或是串列裡的每一個元素;而while迴圈是一個條件判斷的迴圈,當滿足這個條件就執行迴圈的內容,不滿足時就跳出迴圈。
目前為止,我們學到了基本的for迴圈,也就是僅對一個可迭代物件進行迭代。當一個迴圈裡面還有另一個迴圈,這時就形成了巢狀迴圈,最基本的例子就是九九乘法表,每個被乘數都對應到9個乘數,當被乘數和9個乘數都計算完了之後,才換下一個被乘數,不斷迴圈直到每個被乘數和乘數都計算過。另個for迴圈的應用是將串列和
在前面的文章中我們學習了關於字典的基本用法,今天再討論更多關於字典的其它用法,以及它和串列、元組等的關聯。
在程式設計中,我們會使用到一些固定不會變動的資料內容,例如一年的月份、物體的邊長、過去一周的氣溫等等,使用串列的結構固然也可以用來儲存這些資料,但串列可以被新增或刪除,不能有效保護這類不可變動的資料。因此,Python也提供了另一種形式的資料結構,稱為元組,它的資料結構和串列相同,但資料的內容不可變
當我們查字典時,會先找到想查詢的單字在字典裡的位置,才能在那個位置找到單字的定義;在Python中,也有一個類似的資料結構稱作字典,字典的鍵(key)就對應到我們要查詢的單字,字典的值(value)則是該單字的定義。
隨著程式的功能愈來愈複雜,程式碼也愈來愈多,若程式從頭寫到尾沒有任何的段落,可讀性會愈來愈差,甚至會發現同樣的一段程式碼重覆很多遍,因為類似的功能區塊在程式中可能會一再出現。這樣的程式碼不利於多人的協作開發,即使是寫作者本身在一段時間後回來看,可能也難以一眼就掌握程式的主要架構。
另一種迴圈的形式是while迴圈,和for迴圈常常可以達到相同的功能,差別在於for迴圈是在一定的範圍內迭代,例如從1到100,或是串列裡的每一個元素;而while迴圈是一個條件判斷的迴圈,當滿足這個條件就執行迴圈的內容,不滿足時就跳出迴圈。
目前為止,我們學到了基本的for迴圈,也就是僅對一個可迭代物件進行迭代。當一個迴圈裡面還有另一個迴圈,這時就形成了巢狀迴圈,最基本的例子就是九九乘法表,每個被乘數都對應到9個乘數,當被乘數和9個乘數都計算完了之後,才換下一個被乘數,不斷迴圈直到每個被乘數和乘數都計算過。另個for迴圈的應用是將串列和
你可能也想看
Google News 追蹤
21點遊戲的核心在於讓手牌點數接近21但不超過,並比莊家的點數更高。莊家在16點或以下時必須要牌,而17點以上則停牌。玩家應掌握基本策略如要牌、停牌以及倍數賠率的影響,這些都是提高勝率的關鍵。隨著經驗增加,使用基礎和進階策略如分牌和加倍下注,以及概率計算器來幫助決策,可以顯著提升勝率。
Thumbnail
本篇介紹單人遊戲的核心架構與邏輯,涵蓋發牌、抽牌、出牌及遊戲結算等重要步驟。文章也詳細介紹了使用 socket.io 建立連線的過程,並說明如何利用 React Hooks 管理遊戲狀態,提及後端伺服器如何處理玩家加入房間的事件,並簡要介紹了房間資訊的管理,此文將分為多篇進一步介紹遊戲事件部分。
Thumbnail
賓果的遊戲描述 在一個5x5的方陣上隨機填充1~25的數字。 玩家(使用者) 和 電腦(AI)輪流叫一個號碼,最先占據一整條直線連線的獲勝。 就像小時候玩的bingo 賓果連線遊戲一樣! (可以是占據兩條對角線,可以是占據水平直線,可以是占據垂直直線)
Thumbnail
相信大家小時候都有和朋友或玩伴玩過一個猜數字的小遊戲,一個人先在1~100裡面設定一個隱藏數字,其他的人去猜,看誰是最後一個猜中的就算輸,或者看誰最快猜中就算贏。 今天要示範如何用Python寫一個猜數字遊戲, 並且會從上層的思考邏輯開始,一步步構建出這個猜數字的小遊戲。
你有沒有玩過經典遊戲23點呢?這篇文章將分享規則和攻略,讓你快速上手並獲得勝利。最後還介紹了一些改變規則的方式,讓遊戲更有趣味性。不僅可增進數學邏輯還可提升智力。
Thumbnail
winbet小編將介紹21點遊戲規則,並分享親身實測得出的21點教學,包括21點莊家優勢、21點算牌技巧和21點術語。此外,也會提供玩家在實戰中累積經驗的建議。另外,玩家也會得知21點線上遊戲的推薦。歡迎來winbet試試看!
Thumbnail
賓果這款遊戲我想大家應該都不陌生才對,常常會出現在各種活動場合,看誰最快達到指定的連線數量,誰就能得到獎品 賓果遊戲基本概念 這種賓果遊戲使用的卡片由一個5x5的方格組成,每個方格中填入1到25之間的數字,每張卡片上的數字排列是隨機的。 🕹️遊戲規則 準備工作:每個玩家獲得一張或多
Thumbnail
天九牌 墊牌是沒有限制的,任何時候也可墊牌,亦可墊任何牌。墊牌時牌面必須向下,不可讓任何人看到墊的牌是什麼。但要切記「上家不打,下家不墊」這一個守則。 五子棋與圍棋 其实围棋和五子棋的棋子有一个很大的区别:那就是数量不一样。 在五子棋中,棋子白子的数量是112,但是围棋却是180;而黑色的棋子
Thumbnail
可能包含敏感內容
百家樂算牌公式   如果莊閒只發兩張牌比點,開莊閒機率顯然是50:50,連算都不用算。但百家樂中莊閒勝出機率不同的關鍵,就在他的補牌規則。 閒只在 0-5 補牌,莊只在 0-6 補牌,而且莊6點只能在閒加到 6或7 時補牌。 在百家樂中對勝出結果影響較大的是4的周圍號,以簡單的加減計算牌值,
Thumbnail
前幾天聽了一位在海外從事博弈產業的朋友,敘述一些博弈產業的商業模式,與賭場的一些趣事,還有玩21點要怎麼算牌,誰是負責控牌的人,算牌的概念是甚麼。 賭場為什麼可以賺錢?難道他不怕賭客贏走大把的賭金,讓賭場虧損嗎? 是,總會有人運氣很好,一次贏走大筆賭金,但那畢竟是極少數,大部分的人都
21點遊戲的核心在於讓手牌點數接近21但不超過,並比莊家的點數更高。莊家在16點或以下時必須要牌,而17點以上則停牌。玩家應掌握基本策略如要牌、停牌以及倍數賠率的影響,這些都是提高勝率的關鍵。隨著經驗增加,使用基礎和進階策略如分牌和加倍下注,以及概率計算器來幫助決策,可以顯著提升勝率。
Thumbnail
本篇介紹單人遊戲的核心架構與邏輯,涵蓋發牌、抽牌、出牌及遊戲結算等重要步驟。文章也詳細介紹了使用 socket.io 建立連線的過程,並說明如何利用 React Hooks 管理遊戲狀態,提及後端伺服器如何處理玩家加入房間的事件,並簡要介紹了房間資訊的管理,此文將分為多篇進一步介紹遊戲事件部分。
Thumbnail
賓果的遊戲描述 在一個5x5的方陣上隨機填充1~25的數字。 玩家(使用者) 和 電腦(AI)輪流叫一個號碼,最先占據一整條直線連線的獲勝。 就像小時候玩的bingo 賓果連線遊戲一樣! (可以是占據兩條對角線,可以是占據水平直線,可以是占據垂直直線)
Thumbnail
相信大家小時候都有和朋友或玩伴玩過一個猜數字的小遊戲,一個人先在1~100裡面設定一個隱藏數字,其他的人去猜,看誰是最後一個猜中的就算輸,或者看誰最快猜中就算贏。 今天要示範如何用Python寫一個猜數字遊戲, 並且會從上層的思考邏輯開始,一步步構建出這個猜數字的小遊戲。
你有沒有玩過經典遊戲23點呢?這篇文章將分享規則和攻略,讓你快速上手並獲得勝利。最後還介紹了一些改變規則的方式,讓遊戲更有趣味性。不僅可增進數學邏輯還可提升智力。
Thumbnail
winbet小編將介紹21點遊戲規則,並分享親身實測得出的21點教學,包括21點莊家優勢、21點算牌技巧和21點術語。此外,也會提供玩家在實戰中累積經驗的建議。另外,玩家也會得知21點線上遊戲的推薦。歡迎來winbet試試看!
Thumbnail
賓果這款遊戲我想大家應該都不陌生才對,常常會出現在各種活動場合,看誰最快達到指定的連線數量,誰就能得到獎品 賓果遊戲基本概念 這種賓果遊戲使用的卡片由一個5x5的方格組成,每個方格中填入1到25之間的數字,每張卡片上的數字排列是隨機的。 🕹️遊戲規則 準備工作:每個玩家獲得一張或多
Thumbnail
天九牌 墊牌是沒有限制的,任何時候也可墊牌,亦可墊任何牌。墊牌時牌面必須向下,不可讓任何人看到墊的牌是什麼。但要切記「上家不打,下家不墊」這一個守則。 五子棋與圍棋 其实围棋和五子棋的棋子有一个很大的区别:那就是数量不一样。 在五子棋中,棋子白子的数量是112,但是围棋却是180;而黑色的棋子
Thumbnail
可能包含敏感內容
百家樂算牌公式   如果莊閒只發兩張牌比點,開莊閒機率顯然是50:50,連算都不用算。但百家樂中莊閒勝出機率不同的關鍵,就在他的補牌規則。 閒只在 0-5 補牌,莊只在 0-6 補牌,而且莊6點只能在閒加到 6或7 時補牌。 在百家樂中對勝出結果影響較大的是4的周圍號,以簡單的加減計算牌值,
Thumbnail
前幾天聽了一位在海外從事博弈產業的朋友,敘述一些博弈產業的商業模式,與賭場的一些趣事,還有玩21點要怎麼算牌,誰是負責控牌的人,算牌的概念是甚麼。 賭場為什麼可以賺錢?難道他不怕賭客贏走大把的賭金,讓賭場虧損嗎? 是,總會有人運氣很好,一次贏走大筆賭金,但那畢竟是極少數,大部分的人都