Skip to content

Instantly share code, notes, and snippets.

@notsobad
Last active June 13, 2022 09:02
Show Gist options
  • Save notsobad/333b8d63814c4f7c6ee069cce5756aef to your computer and use it in GitHub Desktop.
Save notsobad/333b8d63814c4f7c6ee069cce5756aef to your computer and use it in GitHub Desktop.
>python3 blackjack.py -h
usage: blackjack.py [-h] -n NROUND [-j BLACKJACK_NUM] [-u PLAYER_HIT_UNTIL] [-s PLAYER_SKIP_LARGE] [--verbose]
Blackjack
optional arguments:
-h, --help show this help message and exit
-n NROUND, --nround NROUND
-j BLACKJACK_NUM, --blackjack_num BLACKJACK_NUM
-u PLAYER_HIT_UNTIL, --player_hit_until PLAYER_HIT_UNTIL
player skip when total number exceed this number, like 15
-s PLAYER_SKIP_LARGE, --player_skip_large PLAYER_SKIP_LARGE
player skip when total number exceed dealer card this number, like 10, 0 means no compare
--verbose, -v
参数:
-n 运行多少轮
-j 总点数是多少,默认21点
-u 玩家到多少点的时候跳过,默认为15
-s 玩家点数超过庄家明面牌点数多少时跳过,如10, 如果不提供这个参数则默认不进行此项判断
-v 详细输出
-vv 输出更多信息
每一轮都是全新的, 从52张牌中洗牌后抽取。
> python3 blackjack.py -n 10 -v
> python3 blackjack.py -n 10 -vv
# 运行10轮,总点数20,玩家点数超过16就不在叫牌, 详细输出
> python3 blackjack.py -n 10 -j 20 -u 16 -vv
# 运行10轮,总点数21,玩家点数超过16就不在叫牌, 并且玩家点数超过庄家明面牌9点就不叫牌, 详细输出
> python3 blackjack.py -n 10 -j 20 -u 16 -s 9 -vv
#coding=utf-8
import os
import random
import argparse
import logging
WIN = 1
LOSE = 0
PUSH = -1
def deal(deck):
# 初始每人两张牌
hand = []
for i in range(2):
card = deck.pop()
if card == 11:card = "J"
if card == 12:card = "Q"
if card == 13:card = "K"
if card == 14:card = "A"
hand.append(card)
return hand
def total(hand):
total = 0
for card in hand:
if card == "J" or card == "Q" or card == "K":
total+= 10
elif card == "A":
if total >= 11:
total+= 1
else:
total+= 11
else:
total += card
return total
def hit(deck, hand):
card = deck.pop()
if card == 11:card = "J"
if card == 12:card = "Q"
if card == 13:card = "K"
if card == 14:card = "A"
hand.append(card)
return hand
def play(player_hit_until=0, blackjack_num=21, player_skip_large=0):
# 庄家牌超过这个值就停止抽牌
DEALER_SKIP_NUM = 17
# 每一轮都单独洗牌
deck = [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]*4
random.shuffle(deck)
# 每人发两张牌, 玩家可以看到庄家的第一张牌
player_hand = deal(deck)
dealer_hand = deal(deck)
logging.debug(f"Round start. Dealer: {dealer_hand}, Player {player_hand}")
# 玩家阶段
while True:
# 如果玩家点数大于等于某个值就跳过
if player_hit_until and total(player_hand) >= player_hit_until:
break
if player_skip_large and total(player_hand) - total(dealer_hand[:1]) >= player_skip_large:
# 玩家点数如果大于庄家明面点数一定值,就跳过
logging.debug(f"player skiped because of player_skip_large argument")
break
hit(deck, player_hand)
logging.debug(f"Player hit. Dealer: {dealer_hand}, Player {player_hand}")
# 庄家抽牌,不管player是否busted,在判定时统一处理
while total(dealer_hand) < DEALER_SKIP_NUM:
hit(deck, dealer_hand)
logging.debug(f"Dealer hit. Dealer: {dealer_hand}, Player {player_hand}")
logging.info(f"Round end. Dealer: {dealer_hand}, Player {player_hand}")
# 抽牌结束,开始判定
player_total = total(player_hand)
dealer_total = total(dealer_hand)
if player_total > blackjack_num:
logging.info("Player busted")
return LOSE
if player_total == blackjack_num:
if dealer_total == blackjack_num:
logging.info("It's a push, nobody win")
return PUSH
else:
# 玩家21点且庄家不能是21点
logging.info("Player win, blackjack")
return WIN
if dealer_total > blackjack_num:
logging.info("Player win, dealer busted")
return WIN
if dealer_total == blackjack_num:
logging.info("Player lose, dealer blackjack")
return LOSE
if player_total > dealer_total:
logging.info("Player win, larger than dealer")
return WIN
if player_total < dealer_total:
logging.info("Player lose, smaller than dealer")
return LOSE
logging.info("It's a push, nobody win ")
return PUSH
def main():
parser = argparse.ArgumentParser(description='Blackjack')
parser.add_argument('-n', '--nround', type=int, required=True)
parser.add_argument('-j', '--blackjack_num', default=21, type=int)
parser.add_argument('-u', '--player_hit_until', default=15, type=int, help="player skip when total number exceed this number, like 15")
parser.add_argument('-s', '--player_skip_large', default=0, type=int, help="player skip when total number exceed dealer card this number, like 10, 0 means no compare")
parser.add_argument('--verbose', '-v', action='count', default=0)
args = parser.parse_args()
nround = args.nround
if args.verbose == 0:
level = "WARNING"
elif args.verbose == 1:
level = "INFO"
else:
level = "DEBUG"
logging.basicConfig(level=level, format="%(message)s")
# 结果统计
win_count = lose_count = push_count = 0
for i in range(nround):
logging.info(f">> round {i}")
ret = play(args.player_hit_until, args.blackjack_num, args.player_skip_large)
if ret == WIN:
win_count += 1
elif ret == LOSE:
lose_count += 1
else:
push_count += 1
print(f"\nSettings: play {nround} round, blackjack num is {args.blackjack_num}, player keep hit until {args.player_hit_until}, player_skip_large is {args.player_skip_large}")
print(f"Results: win: {win_count}/{nround}, lose: {lose_count}/{nround}, push: {push_count}/{nround}, wining rate is {win_count / nround}")
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment