11日目の勉強はブラックジャックのゲームをPythonで再現する。
まずはブラックジャックのゲーム内容をおさらい。
今回はディーラーvsプレイヤーの2人だけの対決。
1・まずゲームをしますか?という質問。はいならゲーム開始。いいえならbreak。
2・ゲーム開始でカードがランダムでプレイヤーに配られる。
ディーラーには1枚配られて見えるようになる。
・カードは数字を足すのでJ,Q,K,Aは文字なので数字に置き換える必要がある。
11,2,3,4,5,6,7,8,9,10,10,10,10となる。
・Aは1にも11にもなるので、合計が21になるようであればAは11に、
22以上になるのならAは1に変化する。
3・21に近づけるためにカードをもらうか、そのまま対決するか決める。
・カードをもらって22以上になったらバースト、負け。
4・対決になるとディーラーもカードを追加して勝負する。
5・21に近い方が勝ち。2人ともブラックジャックならドロー。
6・1の質問で続けるか決める。
こんな感じ。
ではプログラミングしていく。
1・まずゲームをしますか?という質問。はいならゲーム開始。いいえならbreak。
input("ブラックジャックしますか? Type 'y' or 'n': ") == "y":
はいを選んだら、カードを配る。
2・ゲーム開始でカードがランダムでプレイヤーに配られる。
カードを配るのはプレイヤーとディーラー2人に同じことをするので、
ファンクション化した方が楽そう。
調べたところrandom.sampleだと複数配れるみたいだけど、
カードがいる時は1まいずつなので1枚ずつで。
カードはAは最初は11からスタートで、21を超えたら1になると。
import random
def deal_card():
cards = [11, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10]
card = random.choice(cards)
return card
ランダムにもらったカードをreturnする。
ついでに現在のカード合計がどれくらいかを計算する機能も書く。
def calculate_score(cards):
if sum(cards) == 21 and len(cards) == 2:
return 0
if 11 in cards and sum(cards) > 21:
cards.remove(11)
cards.append(1)
return sum(cards)
カードが最初の2枚でBJだった場合は0を返す。
もしくは
・Aは1にも11にもなるので、合計が21になるようであればAは11に、
22以上になるのならAは1に変化する。
この部分をremove(11) とappend(1)
でクリアしてから、合計を返す。
0を返す場合は後々の勝負の時に使う。
ゲーム全体もファンクション化する。
プレイヤーのカード・ディーラーのカードを空リストで定義して、
最初に2枚配るのはfor文で繰り返す。
def play_game():
user_cards = []
computer_cards = []
is_game_over = False
for _ in range(2):
user_cards.append(deal_card())
computer_cards.append(deal_card())
while not is_game_over:
user_score = calculate_score(user_cards)
computer_score = calculate_score(computer_cards)
print(f" あなたのカード: {user_cards}, 現在のスコア: {user_score}")
print(f" ディーラーの1枚目: {computer_cards[0]}")
・ディーラーには1枚配られて見えるようになる。
これらは21にを目指すまでカードを配るかやめるかなので
繰り返しのwhileで囲う。
if user_score == 0 or computer_score == 0 or user_score > 21:
is_game_over = True
else:
user_should_deal = input("カードをもらう? y /n: ")
if user_should_deal == "y":
user_cards.append(deal_card())
else:
is_game_over = True
プレイヤーのターンが終わったら、次はディーラーのターン。
こちらもwhileで21を目指すまでカードをくばる。
ギリギリ21だとディーラーも負けやすくなるので、18以上にいったらカードをとめる。
while computer_score != 0 and computer_score < 17:
computer_cards.append(deal_card())
computer_score = calculate_score(computer_cards)
最後に現在のプレイヤーのスコアとディーラーのスコアを計算して、
比較して勝負。
print(f" 手持ちのカードは: {user_cards}, 現在のスコアは: {user_score}")
print(f" ディーラーのカードは: {computer_cards}, ディーラーのスコアは: {computer_score}")
print(compare(user_score, computer_score))
最後のcompare()部分はまだファンクションかしていないので、
書き終えたあとにdef game()の上で書く。
def compare(user_score, computer_score):
if user_score > 21 and computer_score > 21:
return "バースト!負け 😤"
if user_score == computer_score:
return "引き分け🙃"
elif computer_score == 0:
return "ディーラーがブラックジャック!負け 😱"
elif user_score == 0:
return "ブラックジャック!勝ち 😎"
elif user_score > 21:
return "バースト!負け 😭"
elif computer_score > 21:
return "ディーラーがバースト!勝ち 😁"
elif user_score > computer_score:
return "勝ち! 😃"
else:
return "負け 😤"
6・1の質問で続けるか決める。
1と6を同時にするということでwhileを先につけて解決。
clear()はこの前も作ったimport osでファンクションを作る。
while input("ブラックジャックしますか? Type 'y' or 'n': ") == "y":
clear()
play_game()
これでおしまい。
結構コード量多めだったな。。。
プログラムもそうだけどやっぱりゲームの勝負の条件とか
動作の条件とかをしっかり設計してからプログラムにとりかからないと
あとで大変な目にあうなあと思う。