
캡스톤 프로젝트 1
컴퓨터와 블랙잭 게임을 하는 프로그램
도전하려는 프로젝트 난이도에 따라 주어진 힌트를 차등 사용하기
1. Normal : 모든 힌트 사용 가능
2. Hard : 힌트 1, 2, 3만 사용하기
3. Extra Hard : 힌트 1, 2만 사용하기
4. Expert : 힌트 1만 사용하기
- Hint 1
Go to this website and try out the Blackjack game:
https://games.washingtonpost.com/games/blackjack/
Then try out the completed Blackjack project here:
https://appbrewery.github.io/python-day11-demo/- Hint 2
Read this breakdown of program requirements:
http://listmoz.com/view/6h34DJpvJBFVRlZfJvxF
Then try to create your own flowchart for the program.- Hint 3
Download and read this flow chart I've created:
https://drive.google.com/uc?export=download&id=1rDkiHCrhaf9eX7u7yjM1qwSuyEk-rPnt- Hint 4
Create a deal_card() function that uses the List below to return a random card.
- 11 is the Ace.
- cards = [11, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10]
- Hint 5
Deal the user and computer 2 cards each using deal_card() and append().
- user_cards = []
- computer_cards = []
- Hint 6
Create a function called calculate_score() that takes a List of cards as input
- and returns the score.
- Look up the sum() function to help you do this.
- Hint 7
Inside calculate_score() check for a blackjack (a hand with only 2 cards: ace + 10) and return 0 instead of the actual score.
0 will represent a blackjack in our game.- Hint 8
Inside calculate_score() check for an 11 (ace).
If the score is already over 21, remove the 11 and replace it with a 1.
You might need to look up append() and remove().- Hint 9
Call calculate_score().
If the computer or the user has a blackjack (0) or if the user's score is over 21,
then the game ends.- Hint 10
If the game has not ended, ask the user if they want to draw another card.
- If yes, then use the deal_card() function to add another card to the user_cards List.
- If no, then the game has ended.
- Hint 11
The score will need to be rechecked with every new card drawn and the checks in Hint 9 need to be repeated until the game ends.- Hint 12
Once the user is done, it's time to let the computer play.
The computer should keep drawing cards as long as it has a score less than 17.- Hint 13
Create a function called compare() and pass in the user_score and computer_score.
- If the computer and user both have the same score, then it's a draw.
- If the computer has a blackjack (0), then the user loses.
- If the user has a blackjack (0), then the user wins.
- If the user_score is over 21, then the user loses.
- If the computer_score is over 21, then the computer loses.
- If none of the above, then the player with the highest score wins.
- Hint 14
Ask the user if they want to restart the game.
If they answer yes, clear the console and start a new game of blackjack and show the logo from art.py.
🔍 유의 사항
힌트 1 & 2에서 제시된 규칙에 따라 정리
- 딜러(컴퓨터) vs 플레이어
- 목표 : 손에 든 카드를 21을 넘지 않는 가장 큰 숫자에 이를 때까지 더해서 딜러보다 큰 숫자 만들기
- 순서
- 딜러와 플레이어가 각각 카드 2장씩 갖고 시작
a. 딜러는게임 종료전까지 첫 번째 카드만 공개함
b. 만약 누구든 2장의 카드의 합이 21(블랙잭)이면, 바로게임 종료- 플레이어는 딜러에게
추가 카드를 받거나, 받지 않고패스중 선택
a.추가 카드는 합계가 21(블랙잭) 또는 21 초과(버스트)가 되지 않는 이상 제한없이 요구 가능
b.추가 카드로 인해 블랙잭 또는 버스트가 되면, 바로게임 종료- 플레이어가
패스하면, 카드 받기를 중단하고 딜러에게 차례를 넘김
a. 딜러의 카드 합이 17 미만이면, 17 이상이 될 때까지추가 카드를 받음(Dealer's hit rule)
b. 딜러 또한추가 카드로 인해 블랙잭 또는 버스트가 되면, 바로게임 종료- 딜러의 카드 합이 17 이상 되는 순간
게임 종료- 게임 종료 후 다시 플레이 또는 그대로 종료
- 승패 가리기
win
- 블랙잭일 경우 더 진행하지 않고 바로 승리
(다만, 카드 2장으로 시작했을 때 둘 다 블랙잭이 나왔을 경우에는 컴퓨터의 승리)- 게임 종료 시 상대보다 더 큰 숫자
lose
- 버스트일 경우 상대의 카드 합과 상관없이 패배
- 게임 종료 시 상대보다 더 작은 숫자
draw: 게임 종료 시 상대와 같은 숫자- 카드에 따른 점수 계산
2 ~ 10: 카드에 쓰여 있는 대로 계산Jack/Queen/King: 모두 10점으로 계산Ace: 카드 합에 따라 1 또는 11 중 선택 가능 (딜러의 경우 버스트가 아닌 이상 11로 계산)joker카드 없음- cards 리스트(덱) 에서 카드를 가져오는 방식
cards = [11, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10]
- ace는 카드 합이 21이 넘기 전까지 11로 계산
- 실제 블랙잭에서는 덱의 개수가 정해져있지만, 이 프로젝트에서는 덱의 개수가 무한
- 카드를 덱에서 가져올 때, 해당 카드가 제거되지 않는다는 의미
- 리스트의 각 카드가 나타날 확률을 동등하게 만든 것
(다만, 10은 4개이므로 다른 카드보다 경우 더 높은 확률을 가짐)
📄 art.py
아스키 코드 로고 저장
⌨️ 작성한 코드
from replit import clear
from art import logo
from random import choice
cards = [11, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10]
# 뽑은 카드가 Ace일 경우 1과 11 중 하나를 결정하는 함수
def is_ace(card, score):
if card == 11 and card + score > 21:
return 1
else:
return card
# 현재 손에 있는 카드와 점수를 보여주는 함수(컴퓨터는 첫 번째 카드만 공개)
def current_state(player_hand, player_score, computer_hand, computer_score):
print(f" * Your cards: {player_hand}, Your current score: {player_score}")
print(f" * computer's first card: [{computer_hand[0]}]")
# 최종 상태와 게임 결과를 나타내는 함수
def win(player_hand, player_score, computer_hand, computer_score):
print(f" * Your final hand: {player_hand}, Your final score: {player_score}")
print(f" * computer's final hand: {computer_hand}, computer's final score: {computer_score}")
if player_score == 21:
print("You got the blackjack. You win :)\n")
elif computer_score > 21:
print("Computer is busted. You win :)\n")
else:
print("You win :)\n")
def lose(player_hand, player_score, computer_hand, computer_score):
print(f" * Your final hand: {player_hand}, Your final score: {player_score}")
print(f" * computer's final hand: {computer_hand}, computer's final score: {computer_score}")
if player_score > 21:
print("You are busted. You lose :(\n")
elif computer_score == 21:
print("computer got the blackjack. You lose :(\n")
else:
print("You lose :(\n")
def draw(player_hand, player_score, computer_hand, computer_score):
print(f" * Your final hand: {player_hand}, Your final score: {player_score}")
print(f" * computer's final hand: {computer_hand}, computer's final score: {computer_score}")
print("Draw :/\n")
# 게임 오버 후 다시 시작할지 묻는 함수
def should_countinue():
if input("Do you want to play again? Type 'y' or 'n': ") == 'y':
clear()
# 재귀 호출
return blackjack_play()
else:
print("--See you again!------------------------------------------------")
# 게임 플레이 함수
def blackjack_play():
game_over = False # 게임 종료 조건이 되기 전까지
print(logo)
print("--Let's get started!--------------------------------------------")
# 각자의 카드와 점수를 초기화
player_hand = []
computer_hand = []
player_score = 0
computer_score = 0
# 각자 2장씩 카드를 받고 시작
for i in range(2):
player_hand.append(choice(cards))
player_score += player_hand[i]
computer_hand.append(choice(cards))
computer_score += computer_hand[i]
if computer_score == 21 and player_score == 21: # 둘 다 blackjack -> 컴퓨터 승
lose(player_hand, player_score, computer_hand, computer_score)
game_over = True
should_countinue()
elif computer_score == 21: # 컴퓨터가 blackjack -> 바로 패배
lose(player_hand, player_score, computer_hand, computer_score)
game_over = True
should_countinue()
elif player_score == 21: # 플레이어가 blackjack -> 바로 승리
win(player_hand, player_score, computer_hand, computer_score)
game_over = True
should_countinue()
else: # 종료 조건 아님 -> 현 상태 보여주기
current_state(player_hand, player_score, computer_hand, computer_score)
# 플레이어가 hit 또는 stand
while not game_over:
if input("Type 'y' to get another card, type 'n' to pass: ") == 'y':
get_card = is_ace(choice(cards), player_score) # 플레이어가 추가 카드 수령
player_hand.append(get_card)
player_score += get_card
if player_score > 21: # 플레이어가 bust -> 바로 패배
lose(player_hand, player_score, computer_hand, computer_score)
game_over = True
should_countinue()
elif player_score == 21: # 플레이어가 blackjack -> 바로 승리
win(player_hand, player_score, computer_hand, computer_score)
game_over = True
should_countinue()
else: # 종료 조건 아님 -> 현 상태 보여주기
current_state(player_hand, player_score, computer_hand, computer_score)
else: # 컴퓨터 차례
if computer_score < 17: # Dealer's hit rule 먼저 체크
while computer_score < 17: # 17 이상이 될 때까지 추가 카드 반복 수령
get_card = is_ace(choice(cards), computer_score)
computer_hand.append(get_card)
computer_score += get_card
# 컴퓨터의 최종 점수와 플레이어의 최종 점수 비교
if computer_score > 21: # 컴퓨터가 bust -> 승리
win(player_hand, player_score, computer_hand, computer_score)
elif computer_score == 21: # 컴퓨터가 blackjack -> 패배
lose(player_hand, player_score, computer_hand, computer_score)
elif computer_score < player_score: # 컴퓨터 < 플레이어 -> 승리
win(player_hand, player_score, computer_hand, computer_score)
elif computer_score > player_score: # 컴퓨터 > 플레이어 -> 패배
lose(player_hand, player_score, computer_hand, computer_score)
else: # 컴퓨터 = 플레이어 -> 무승부
draw(player_hand, player_score, computer_hand, computer_score)
game_over = True
should_countinue()
# 게임 플레이 함수 호출
blackjack_play()
[ 출력 결과 ]
.------. _ _ _ _ _
|A_ _ |. | | | | | | (_) | |
|( \/ ).-----. | |__ | | __ _ ___| | ___ __ _ ___| | __
| \ /|K /\ | | '_ \| |/ _` |/ __| |/ / |/ _` |/ __| |/ /
| \/ | / \ | | |_) | | (_| | (__| <| | (_| | (__| <
`-----| \ / | |_.__/|_|\__,_|\___|_|\_\ |\__,_|\___|_|\_\
| \/ K| _/ |
`------' |__/
--Let's get started!--------------------------------------------
* Your cards: [10, 10], Your current score: 20
* computer's first card: [11]
Type 'y' to get another card, type 'n' to pass: n
* Your final hand: [10, 10], Your final score: 20
* computer's final hand: [11, 8], computer's final score: 19
You win :)
Do you want to play again? Type 'y' or 'n': y
.------. _ _ _ _ _
|A_ _ |. | | | | | | (_) | |
|( \/ ).-----. | |__ | | __ _ ___| | ___ __ _ ___| | __
| \ /|K /\ | | '_ \| |/ _` |/ __| |/ / |/ _` |/ __| |/ /
| \/ | / \ | | |_) | | (_| | (__| <| | (_| | (__| <
`-----| \ / | |_.__/|_|\__,_|\___|_|\_\ |\__,_|\___|_|\_\
| \/ K| _/ |
`------' |__/
--Let's get started!--------------------------------------------
* Your cards: [7, 10], Your current score: 17
* computer's first card: [3]
Type 'y' to get another card, type 'n' to pass: n
* Your final hand: [7, 10], Your final score: 17
* computer's final hand: [3, 3, 10, 6], computer's final score: 22
Computer is busted. You win :)
Do you want to play again? Type 'y' or 'n': n
--See you again!------------------------------------------------
🔍 유의 사항
- 리스트 뒤에 무언가를 추가할 때 주의할 점
❌ '리스트 += 리스트가 아닌 하나의 항목' 은 불가능
⭕️ '리스트 += 리스트'가 아닐 때는 append() 사용하기
🖍️ 답안
#Hint 4: Create a deal_card() function that uses the List below to *return* a random card.
#11 is the Ace.
#cards = [11, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10]
import random
from replit import clear
from art import logo
def deal_card():
"""Returns a random card from the deck."""
cards = [11, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10]
card = random.choice(cards)
return card
#Hint 5: Deal the user and computer 2 cards each using deal_card() and append().
#user_cards = []
#computer_cards = []
user_cards = []
computer_cards = []
for _ in range(2):
user_cards.append(deal_card())
computer_cards.append(deal_card())
🔍 유의 사항
- 사용 함수
- sum( iterable, [start] ) : 주어진 목록의 요소들을 전부 더하는 함수
iterable: 요소들의 목록start: 목록 안의 요소들을 전부 더한 값에 추가로 더할 값 [디폴트 값 = 0]- list.append(elmnt) : 리스트에 끝에 주어진 요소를 더하는 함수
- list.remove(elmnt) : 리스트에서 주어진 요소의 첫 번째 인스턴스를 찾아서 삭제하는 함수
calculate_score(cards): 카드 합을 계산하는 함수- 카드 합이 21이고 두 장의 카드를 갖고 있을 경우(= 2장으로 시작 시 블랙잭),
return 0- 카드 합이 21을 넘을 경우, 만약 에이스가 있다면 11을 제거하고 1을 넣음
🖍️ 답안
#Hint 6: Create a function called calculate_score() that takes a List of cards as input
#and returns the score.
#Look up the sum() function to help you do this.
def calculate_score(cards):
"""Take a list of cards and return the score calculated from the cards"""
#Hint 7: Inside calculate_score() check for a blackjack (a hand with only 2 cards:ace + 10) and return 0 instead of the actual score.
#0 will represent a blackjack in our game.
if sum(cards) == 21 and len(cards) == 2:
return 0
#Hint 8: Inside calculate_score() check for an 11 (ace).
#If the score is already over 21, remove the 11 and replace it with a 1.
#You might need to look up append() and remove().
if 11 in cards and sum(cards) > 21:
cards.remove(11)
cards.append(1)
return sum(cards)
변수나 함수를 많이 만들 필요 없이 calculate_score 함수 하나 안에
의 3가지 기능을 구현
🔍 유의 사항
- 리팩토링 : 소스코드의 구조를 변경하는 작업
- Hint 6에서 선언한
calculate_score함수를 Hint 5 위로 옮겨야 동작함- Hint 5에
is_game_over = False추가하기- 컴퓨터가 블랙잭, 유저가 블랙잭, 또는 유저의 점수가 21을 넘으면 게임 오버
🖍️ 답안
#Hint 6
def calculate_score(cards):…
#Hint 5
…
is_game_over = False
#Hint 9: Call calculate_score().
#If the computer or the user has a blackjack (0) or if the user's score is over 21
#,then the game ends.
user_score = calculate_score(user_cards)
computer_score = calculate_score(computer_cards)
print(f" Your cards: {user_cards}, current score: {user_score}")
print(f" Computer's first card: {computer_cards[0]}")
if user_score == 0 or computer_score == 0 or user_score > 21:
is_game_over = True
🔍 유의 사항
- Hint 11에 while문 작성 후, Hint 9의 위로 올리고, 밑의 모든 코드를 while문 안에 넣어야 함
- Hint 12에서 컴퓨터가 계속 카드를 뽑을 때,
computer_score가 0이면 블랙잭이므로,
그냥< 17이 아니라and로 조건을 추가해야 함
🖍️ 답안
#Hint 11: The score will need to be rechecked with every new card drawn
#and the checks in Hint 9 need to be repeated until the game ends.
while not is_game_over:
#Hint 9
…
if user_score == 0 or computer_score == 0 or user_score > 21:
is_game_over = True
#Hint 10: If the game has not ended, ask the user if they want to draw another card.
#If yes, then use the deal_card() function to add another card to the user_cards List.
#If no, then the game has ended.
else:
user_should_deal = input("Type 'y' to get another card, type 'n' to pass: ")
if user_should_deal == "y":
user_cards.append(deal_card())
else:
is_game_over = True
#Hint 12: Once the user is done, it's time to let the computer play.
#The computer should keep drawing cards as long as it has a score less than 17.
while computer_score != 0 and computer_score < 17:
computer_cards.append(deal_card())
computer_score = calculate_score(computer_cards)
🔍 유의 사항
- Hint 13을 Hint 6의
calculate_score함수 선언 밑으로 옮겨서compare함수 작성하기
compare함수의 if문 순서에 주의하기
- 컴퓨터와 유저가 둘 다 버스트일 경우, 무승부가 아니라 유저의 패배이기 때문에 가장 먼저 체크
- 그 다음 무승부 여부를 체크
- 그 다음 각자의 블랙잭 여부를 체크
- 그 다음 각자의 버스트 여부를 체크
- 마지막으로 어느 쪽의 점수가 더 큰지 체크
compare함수를 Hint 12의 끝에서 호출compare함수를 호출한 줄 위에 final 결과를 알려주는 print문 작성- Hint 14에서 while문으로 게임을 다시 실행할지 물어보기
- Hint 14에서
play_game함수를 작성하고 Hint 5 ~ 14까지의 내용을 함수 안에 넣기
🖍️ 답안
#Hint 6
…
def calculate_score(cards):…
#Hint 13: Create a function called compare() and pass in the user_score and computer_score.
#If the computer and user both have the same score, then it's a draw.
#If the computer has a blackjack (0), then the user loses.
#If the user has a blackjack (0), then the user wins.
#If the user_score is over 21, then the user loses.
#If the computer_score is over 21, then the computer loses.
#If none of the above, then the player with the highest score wins.
def compare(user_score, computer_score):
#Bug fix. If you and the computer are both over, you lose.
if user_score > 21 and computer_score > 21:
return "You went over. You lose 😤"
if user_score == computer_score:
return "Draw 🙃"
elif computer_score == 0:
return "Lose, opponent has Blackjack 😱"
elif user_score == 0:
return "Win with a Blackjack 😎"
elif user_score > 21:
return "You went over. You lose 😭"
elif computer_score > 21:
return "Opponent went over. You win 😁"
elif user_score > computer_score:
return "You win 😃"
else:
return "You lose 😤"
# Hint 14
def play_game():
print(logo)
#Hint 5
…
#Hint 12
…
print(f" Your final hand: {user_cards}, final score: {user_score}")
print(f" Computer's final hand: {computer_cards}, final score: {computer_score}")
print(compare(user_score, computer_score))
#Hint 14: Ask the user if they want to restart the game.
#If they answer yes,
#clear the console and start a new game of blackjack and show the logo from art.py.
while input("Do you want to play a game of Blackjack? Type 'y' or 'n': ") == "y":
clear()
play_game()
작성한 코드 : 처음 프로그램 실행 시 바로 게임을 시작하고, 그 다음부터 다시 시작할 것인지 여부를 묻는 방식
강의 : 처음 프로그램을 실행했을 때부터 게임을 실행할 것인지 아닌지 여부를 묻기 때문에 맨 밑의 while문부터 시작
🖍️ 전체 답안
#Hint 4
import random
from replit import clear
from art import logo
def deal_card():
"""Returns a random card from the deck."""
cards = [11, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10]
card = random.choice(cards)
return card
#Hint 6
def calculate_score(cards):
"""Take a list of cards and return the score calculated from the cards"""
#Hint 7
if sum(cards) == 21 and len(cards) == 2:
return 0
#Hint 8
if 11 in cards and sum(cards) > 21:
cards.remove(11)
cards.append(1)
return sum(cards)
#Hint 13
def compare(user_score, computer_score):
if user_score > 21 and computer_score > 21:
return "You went over. You lose 😤"
if user_score == computer_score:
return "Draw 🙃"
elif computer_score == 0:
return "Lose, opponent has Blackjack 😱"
elif user_score == 0:
return "Win with a Blackjack 😎"
elif user_score > 21:
return "You went over. You lose 😭"
elif computer_score > 21:
return "Opponent went over. You win 😁"
elif user_score > computer_score:
return "You win 😃"
else:
return "You lose 😤"
def play_game():
print(logo)
#Hint 5
user_cards = []
computer_cards = []
is_game_over = False
for _ in range(2):
user_cards.append(deal_card())
computer_cards.append(deal_card())
#Hint 11
while not is_game_over:
#Hint 9
user_score = calculate_score(user_cards)
computer_score = calculate_score(computer_cards)
print(f" Your cards: {user_cards}, current score: {user_score}")
print(f" Computer's first card: {computer_cards[0]}")
if user_score == 0 or computer_score == 0 or user_score > 21:
is_game_over = True
else:
#Hint 10
user_should_deal = input("Type 'y' to get another card, type 'n' to pass: ")
if user_should_deal == "y":
user_cards.append(deal_card())
else:
is_game_over = True
#Hint 12
while computer_score != 0 and computer_score < 17:
computer_cards.append(deal_card())
computer_score = calculate_score(computer_cards)
print(f" Your final hand: {user_cards}, final score: {user_score}")
print(f" Computer's final hand: {computer_cards}, final score: {computer_score}")
print(compare(user_score, computer_score))
#Hint 14
while input("Do you want to play a game of Blackjack? Type 'y' or 'n': ") == "y":
clear()
play_game()