BLACK JACK
[룰 설명]
[BlackJack 기본 규칙]
목적: 블랙잭의 목표는 딜러(dealer)를 상대로 21을 넘지 않으면서, 21에 가까운 숫자를 만드는 것입니다.
카드의 값:
- 숫자 카드(2-10): 각 카드에 적힌 숫자대로 점수를 가집니다.
- 그림 카드(J, Q, K): 각 카드의 값은 10점입니다.
- 에이스(A): 11점으로 계산합니다.
게임 진행:
- 각 플레이어는 두 장의 카드를 받고, 딜러도 두 장의 카드를 받습니다. 딜러의 한 장은 보통 뒤집어서 숨깁니다.
- 플레이어는 자신의 카드 합계가 21에 가까워지도록 추가 카드를 요청(hit)하거나 현재 점수로 만족하여 더 이상 카드를 받지 않겠다고 선언할 수 있습니다(stay 또는 stand).
- 딜러는 자신의 카드 합계가 17 이상이 될 때까지 반드시 카드를 추가로 받아야 합니다.
- 플레이어의 카드 합계가 21을 초과하면 패배(bust)합니다.
- 플레이어가 멈춘 후 딜러의 차례가 되며, 딜러의 카드 합계가 21을 초과하면 딜러가 패배합니다.
- 딜러의 카드 합계가 21을 넘지 않으면, 딜러와 플레이어의 카드 합계를 비교하여 높은 쪽이 승리합니다.
[파이썬 코드]
import random # 랜덤 모듈을 가져옵니다. 덱을 섞을 때 사용합니다.
# 문제 1: 카드 덱 생성하기
# 빈칸을 채워 카드 덱을 생성하는 create_deck 함수를 완성하세요.
def create_deck():
"""
이 함수는 52장의 카드로 구성된 덱을 생성하고 이를 무작위로 섞어서 반환합니다.
카드 덱은 네 가지 무늬(하트, 다이아몬드, 클로버, 스페이드)와
각각의 무늬마다 13개의 랭크(2-10, 잭, 퀸, 킹, 에이스)로 이루어져 있습니다.
Returns:
list: 무작위로 섞인 카드 덱
"""
deck = [] # 빈 리스트로 덱을 초기화합니다.
suits = ['하트', '다이아몬드', '클로버', '스페이드'] # 카드의 네 가지 무늬를 리스트로 정의합니다.
ranks = ['2', '3', '4', '5', '6', '7', '8', '9', '10', '잭', '퀸', '킹', '에이스'] # 카드의 13가지 랭크를 리스트로 정의합니다.
# 모든 무늬와 랭크를 조합하여 덱을 만듭니다.
for suit in suits: # suits 리스트를 순회합니다.
for rank in ranks: # ranks 리스트를 순회합니다.
deck.append((rank, suit)) # 각 카드(rank와 suit의 조합)를 덱에 추가합니다.
random.shuffle(deck) # 덱을 무작위로 섞습니다.
return deck # 섞인 덱을 반환합니다.
# 힌트:
# - suits 리스트의 각 항목을 suit 변수에 담아 순회합니다.
# - ranks 리스트의 각 항목을 rank 변수에 담아 순회합니다.
# - deck 리스트를 shuffle 함수로 섞습니다.
# - 최종적으로 생성된 deck 리스트를 반환합니다.
# 문제 2: 카드 점수 계산하기
# 빈칸을 채워 손에 있는 카드의 점수를 계산하는 calculate_score 함수를 완성하세요.
def calculate_score(hand):
"""
이 함수는 주어진 카드 리스트(hand)의 총 점수를 계산합니다.
점수 계산 규칙:
- 숫자 카드는 해당 숫자만큼 점수를 더합니다.
- '잭', '퀸', '킹'은 10점으로 계산합니다.
- '에이스'는 11점으로 계산하되, 점수가 21을 초과할 경우 1점으로 계산합니다.
Args:
hand (list): 카드의 리스트, 각 카드는 (랭크, 무늬) 튜플로 표현됩니다.
Returns:
int: 손에 있는 카드의 총 점수
"""
score = 0 # 점수를 0으로 초기화합니다.
ace_count = 0 # 에이스 카드의 개수를 세기 위한 변수를 0으로 초기화합니다.
# 각 카드의 점수를 계산합니다.
for card, suit in hand: # hand 리스트를 순회합니다.
if card in ['잭', '퀸', '킹']: # '잭', '퀸', '킹'은 10점으로 계산합니다.
score += 10 # score에 10을 더합니다.
elif card == '에이스': # '에이스'는 11점으로 계산합니다.
ace_count += 1 # 에이스 개수를 하나 증가시킵니다.
score += 11 # score에 11을 더합니다.
else: # 숫자 카드는 해당 숫자만큼 점수를 더합니다.
score += int(card) # card를 정수로 변환하여 score에 더합니다.
# 점수가 21점을 초과하고 에이스가 있을 경우, 에이스를 1점으로 계산합니다.
while score > 21 and ace_count: # score가 21점을 초과하고 ace_count가 0보다 클 때
score -= 10 # score에서 10을 뺍니다.
ace_count -= 1 # ace_count를 하나 감소시킵니다.
return score # 최종 점수를 반환합니다.
# 힌트:
# - hand 리스트의 각 항목을 card와 suit 변수에 담아 순회합니다.
# - '에이스'는 초기 11점으로 계산하고, 필요시 1점으로 조정합니다.
# - 최종적으로 계산된 score를 반환합니다.
# 문제 3: 카드 출력하기
# 빈칸을 채워 손에 있는 카드를 출력하는 show_cards 함수를 완성하세요.
def show_cards(player, hand):
"""
이 함수는 주어진 플레이어의 이름과 해당 플레이어의 손에 있는 카드를 출력합니다.
Args:
player (str): 플레이어의 이름
hand (list): 플레이어의 손에 있는 카드 리스트, 각 카드는 (랭크, 무늬) 튜플로 표현됩니다.
"""
print(f"{player}의 카드: ", end="") # 플레이어의 이름을 출력합니다.
for card, suit in hand: # hand 리스트를 순회합니다.
print(f"{card} {suit}", end=", ") # 각 카드의 랭크와 무늬를 출력합니다.
print() # 줄 바꿈을 위해 빈 print문을 추가합니다.
# 힌트:
# - player를 출력합니다.
# - hand 리스트를 순회하며 각 카드의 랭크와 무늬를 출력합니다.
# 유효한 입력만 받도록 하는 함수
def get_valid_input(prompt, valid_options):
"""
이 함수는 사용자가 유효한 옵션을 입력할 때까지 반복하여 입력을 받습니다.
Args:
prompt (str): 사용자에게 표시할 입력 메시지
valid_options (list): 유효한 입력 옵션 리스트
Returns:
str: 유효한 입력 값
"""
while True:
choice = input(prompt).lower()
if choice in valid_options:
return choice
print(f"유효하지 않은 입력값입니다. {valid_options}중에서 선택해주세요.")
# 문제 4: 블랙잭 게임 진행하기
# 빈칸을 채워 블랙잭 게임을 진행하는 play_blackjack 함수를 완성하세요.
def play_blackjack():
"""
이 함수는 블랙잭 게임의 전체 진행을 관리합니다.
게임 시작 메시지를 출력하고, 덱을 생성하며, 초기 카드를 분배합니다.
플레이어와 딜러의 행동을 처리하고, 최종 결과를 출력합니다.
"""
print("블랙잭 게임에 오신 것을 환영합니다!") # 게임 시작 메시지를 출력합니다.
deck = create_deck() # 덱을 생성합니다.
# 초기 카드 분배
player_hand = [deck.pop(), deck.pop()] # 플레이어에게 두 장의 카드를 분배합니다.
dealer_hand = [deck.pop(), deck.pop()] # 딜러에게 두 장의 카드를 분배합니다.
show_cards("플레이어",player_hand ) # 플레이어의 카드를 출력합니다.
show_cards("딜러", [dealer_hand[0], ("?", "?")]) # 딜러의 첫 번째 카드만 공개하고 두 번째 카드는 숨깁니다.
# 플레이어의 선택
while True:
player_score = calculate_score(player_hand) # 플레이어의 점수를 계산합니다.
print(f"플레이어의 점수: {player_score}") # 플레이어의 점수를 출력합니다.
if player_score > 21: # 플레이어가 21점을 초과하면 버스트입니다.
print("플레이어가 버스트 했습니다! 딜러 승리!")
return
choice = get_valid_input("카드를 더 받으시겠습니까? (y/n): ", "[y,n]") # 플레이어에게 카드를 더 받을지 물어봅니다.
if choice.lower() == 'y': # 'y'를 선택하면 카드를 한 장 더 받습니다.
player_hand.append(deck.pop())
show_cards("플레이어", player_hand) # 플레이어의 새로운 카드를 출력합니다.
else: # 'n'을 선택하면 반복문을 종료합니다.
break
# 딜러의 카드 공개 및 추가 카드 받기
show_cards("딜러", dealer_hand) # 딜러의 모든 카드를 공개합니다.
while calculate_score(dealer_hand) < 17: # 딜러의 점수가 17점 미만이면 카드를 더 받습니다.
dealer_hand.append(deck.pop())
show_cards("딜러", dealer_hand) # 딜러의 새로운 카드를 출력합니다.
dealer_score = calculate_score(dealer_hand) # 딜러의 최종 점수를 계산합니다.
print(f"딜러의 점수: {dealer_score}") # 딜러의 점수를 출력합니다.
# 결과 판단
if dealer_score > 21:
print("딜러가 버스트 했습니다! 플레이어 승리!") # 딜러가 버스트 했으면 플레이어가 승리합니다.
elif dealer_score > player_score:
print("딜러 승리!") # 딜러의 점수가 더 높으면 딜러가 승리합니다.
elif dealer_score < player_score:
print("플레이어 승리!") # 플레이어의 점수가 더 높으면 플레이어가 승리합니다.
else:
print("무승부!") # 점수가 같으면 무승부입니다.
# 힌트:
# - create_deck 함수를 호출하여 덱을 생성합니다.
# - 플레이어와 딜러에게 각각 두 장의 카드를 분배합니다.
# - 플레이어의 점수를 계산하고, 21점을 초과하면 버스트 처리합니다.
# - 딜러의 점수를 계산하고, 필요한 경우 추가 카드를 받습니다.
# - 최종 점수를 비교하여 승자를 결정합니다.
# 메인 함수: 게임을 시작하고, 사용자가 원하면 반복합니다.
if __name__ == "__main__":
while True:
play_blackjack() # 블랙잭 게임을 시작합니다.
replay = get_valid_input("다시 게임을 하시겠습니까? (y/n): ","[y,n]") # 사용자가 게임을 다시 할지 물어봅니다.
if replay.lower() != 'y': # 'y'가 아니면 게임을 종료합니다.
break
# 해당 코드는 오즈코딩스쿨의 프로젝트 과제의 일부 입니다.
'Code-note' 카테고리의 다른 글
[프로젝트] snake 게임 만들기 -python (2) | 2024.10.05 |
---|---|
[프로젝트] PingPong 게임 만들기 -python (8) | 2024.10.05 |
[프로젝트]QR code 생성기 -python (2) | 2024.09.11 |
[문제리뷰] 방문 길이-python ; (programmers/Lv2) (2) | 2024.09.10 |
[자료구조]클래스(class) 개념 이해하기 -python (2) | 2024.09.03 |