Last active
June 13, 2022 09:02
-
-
Save notsobad/333b8d63814c4f7c6ee069cce5756aef to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
>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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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