def test_get_final_result_basic(self): blackjack = Blackjack() blackjack.bet = 10 blackjack.spec_player_add_hand([0, 9]) # A, 10: 21 blackjack.spec_house_set_hand([9, 4]) # 10, 5: 15 result, net_money = blackjack.get_final_result(0) self.assertEqual(result, Blackjack.PlayResult.BLACKJACK) self.assertEqual(net_money, 15) blackjack.clear() blackjack.spec_player_add_hand([4, 9]) # 15 blackjack.spec_house_set_hand([9, 9]) # 20 result, net_money = blackjack.get_final_result(0) self.assertEqual(result, Blackjack.PlayResult.LOSS) self.assertEqual(net_money, -10) blackjack.clear() blackjack.spec_player_add_hand([9, 9]) # 20 blackjack.spec_house_set_hand([9, 6]) # 17 result, net_money = blackjack.get_final_result(0) self.assertEqual(result, Blackjack.PlayResult.WIN) self.assertEqual(net_money, 10) blackjack.clear() blackjack.spec_player_add_hand([9, 9]) # 20 blackjack.spec_house_set_hand([9, 9]) # 20 result, net_money = blackjack.get_final_result(0) self.assertEqual(result, Blackjack.PlayResult.PUSH) self.assertEqual(net_money, 0) blackjack.clear() blackjack.spec_player_add_hand([9, 9, 3]) # 22 blackjack.spec_house_set_hand([9, 9]) # 20 result, net_money = blackjack.get_final_result(0) self.assertEqual(result, Blackjack.PlayResult.BUST) self.assertEqual(net_money, -10)
class Application(tk.Frame): """Root window for Blackjack application.""" def __init__(self, master=None): super().__init__(master) self.master = master self.master.title("Blackjack - Basic Strategy") # self.master.iconbitmap('out3_nr3_icon.ico') self.master.geometry("900x500") self.pack(fill="both", expand=1) self.game = Blackjack() self.bg_color = "#006644" self.t_color = "#fcf403" self.h_color = "#005634" self.card_width = 100 self.card_height = 145 self.display_hidden_house = False self.game_finished = True self.images_load() self.widgets_create() self.scene_update() def board_clear(self): self.game.clear() self.b_hit["state"] = "disabled" self.b_double["state"] = "disabled" self.b_hold["state"] = "disabled" self.l_game_result["text"] = "" self.display_hidden_house = False self.scene_update() def board_deal(self): self.l_game_result["text"] = "" self.display_hidden_house = False self.game_finished = False self.b_deal["state"] = "disabled" self.b_clear["state"] = "disabled" self.b_change_bet.grid_remove() self.game.clear() result = self.game.deal() if(result == Blackjack.PlayResult.BLACKJACK): self.board_finish() else: self.b_hit["state"] = "normal" self.b_double["state"] = "normal" self.b_hold["state"] = "normal" if(self.game.splittable()): self.b_split["state"] = "normal" self.scene_update() def board_double(self): self.game.player.double = True hand_ind = self.game.player_hands.index(self.game.player) result = self.game.hit() if(hand_ind != 0): self.board_split_next() else: self.board_finish() self.b_split["state"] = "disabled" self.scene_update() # Determine status of all split hands compared with dealer, display those # results, and apply final winnings/losings. def board_finish(self): net_money_total = 0 # If there is any hand that is not a bust, the house must play. for index in range(0, len(self.game.player_hands)): result, net_money = self.game.get_final_result(index) if(result != Blackjack.PlayResult.BUST): self.board_house_plays() break if len(self.game.player_hands) > 1: lst_text = [] for index, player_hand in enumerate(self.game.player_hands): result, net_money = self.game.get_final_result(index) net_money_total += net_money d_text = "D-" if player_hand.double else "" if(result == Blackjack.PlayResult.BUST): lst_text.append(d_text + "Bust") elif(result == Blackjack.PlayResult.BLACKJACK): lst_text.append("Blackjack") self.display_hidden_house = True elif(result == Blackjack.PlayResult.WIN): lst_text.append(d_text + "Win") self.display_hidden_house = True elif(result == Blackjack.PlayResult.PUSH): lst_text.append("Push") self.display_hidden_house = True else: #(result == Blackjack.PlayResult.LOSS): lst_text.append(d_text + "Loss") self.display_hidden_house = True self.l_game_result["text"] = (" + ".join(lst_text) ) + " = {}".format(net_money_total) else: result, net_money_total = self.game.get_final_result(0) d_text = "Double " if self.game.player.double else "" if(result == Blackjack.PlayResult.BUST): self.l_game_result["text"] = d_text + "Bust!" elif(result == Blackjack.PlayResult.BLACKJACK): self.l_game_result["text"] = "Blackjack!" self.display_hidden_house = True elif(result == Blackjack.PlayResult.WIN): self.l_game_result["text"] = d_text + "Win!" self.display_hidden_house = True elif(result == Blackjack.PlayResult.PUSH): self.l_game_result["text"] = "Push" self.display_hidden_house = True else: #(result == Blackjack.PlayResult.LOSS): self.l_game_result["text"] = d_text + "Loss!" self.display_hidden_house = True self.game.money += net_money_total self.game_finished = True self.b_hit["state"] = "disabled" self.b_double["state"] = "disabled" self.b_split["state"] = "disabled" self.b_hold["state"] = "disabled" self.b_deal["state"] = "normal" self.b_clear["state"] = "normal" self.b_shuffle["state"] = "normal" self.b_change_bet.grid() def board_hit(self): result = self.game.hit() hand_ind = self.game.player_hands.index(self.game.player) # Player did not bust or hit a blackjack. It is still their turn. if(result == Blackjack.PlayResult.CONTINUE): pass elif(hand_ind != 0): self.board_split_next() else: self.board_finish() self.b_split["state"] = "disabled" self.scene_update() def board_hold(self): hand_ind = self.game.player_hands.index(self.game.player) if(hand_ind == 0): self.board_finish() else: self.board_split_next() self.scene_update() # House plays cards till they win, lose or tie. def board_house_plays(self): self.b_hit["state"] = "disabled" self.b_double["state"] = "disabled" self.b_hold["state"] = "disabled" self.b_deal["state"] = "disabled" self.b_shuffle["state"] = "disabled" self.b_clear["state"] = "disabled" self.display_hidden_house = True self.scene_update() while(True): sleep_total = 1 sleep_step = 0.1 sleep_reps = math.floor(sleep_total / sleep_step) + 1 for _ in range(0, sleep_reps): time.sleep(sleep_step) self.master.update() result = self.game.house_play() if(result != Blackjack.PlayResult.CONTINUE): return result; else: self.scene_update() # Reset the whole board, cards, and buttons. def board_shuffle(self): self.game.reset() self.b_hit["state"] = "disabled" self.b_double["state"] = "disabled" self.b_hold["state"] = "disabled" self.b_deal["state"] = "normal" self.b_clear["state"] = "normal" self.l_game_result["text"] = "" self.scene_update() def board_split(self): self.game.split() if(self.game.splittable() == False): self.b_split["state"] = "disabled" self.scene_update() def board_split_next(self): self.game.split_next() if(self.game.splittable()): self.b_split["state"] = "normal" else: self.b_split["state"] = "disabled" def change_bet(self): bet = DialogBet(master=self).show() self.game.bet = bet["bet"] self.scene_update() def dialog_config(self): config = DialogConfig(master=self).show() self.game.decks = config["decks"] self.b_hit["state"] = "disabled" self.b_hold["state"] = "disabled" self.game.reset() self.scene_update() def images_load(self): self.card_sprites = dict() files = os.listdir("sprites") for file in files: image = Image.open("sprites/" + file) image = image.resize((self.card_width, self.card_height), Image.ANTIALIAS) self.card_sprites[file.replace(".png", "")] = image # Update all visuals. This includes deck labels, card sprites, etc. def scene_update(self): # Update deck labels self.l_deck_ct_val["text"] = str(self.game.decks) self.l_card_ct_val["text"] = str(len(self.game.deck)) self.l_money_val["text"] = str(self.game.money) self.l_bet_val["text"] = str(self.game.bet) # Update card sprites num_to_card = Blackjack.number_to_card len_h = len(self.game.house) len_phs = len(self.game.player_hands) house_card1 = "back" house_card2 = num_to_card( self.game.house[1] ) if len_h >= 2 else "back" # # DEBUG: # for index, hand in enumerate(self.game.player_hands): # print("Player hand {0}: {1}".format(index, hand)) # print(self.game.player_hands) # print(self.game.player) # Render each player card on top of each other. ph_images = [] for hand in self.game.player_hands: len_p = len(hand.cards) ph_image = Image.new("RGBA", (self.card_width + (len_p-1) * 20, self.card_height)) for num, card in enumerate(hand.cards): card_name = num_to_card(card) ph_image.paste(self.card_sprites[card_name], (20 * num, 0 ), self.card_sprites[card_name]) if(hand != self.game.player and self.game_finished != True): enhancer = ImageEnhance.Brightness(ph_image) ph_image = enhancer.enhance(0.5) ph_images.append(ph_image) # We have to add to append None until we hit 4, since there are 4 # labels. If there are no cards for the label to display, None must be # passed through to get rid of any existing image. while len(ph_images) < self.game.max_splits: ph_images.append(None) for index, ph_image in enumerate(ph_images): Application.tk_set_image(self.l_player_hands[index], ph_image) # Render each dealer card on top of each other. hh_image = None if len_h > 0: hh_image = Image.new("RGBA", (self.card_width + (len_h-1) * 20, self.card_height)) for num, card in enumerate(self.game.house): card_name = None # First dealer card is hidden. if num == 0 and self.display_hidden_house == False: card_name = "back" else: card_name = num_to_card(card) hh_image.paste(self.card_sprites[card_name], (20 * num, 0 ), self.card_sprites[card_name]) else: hh_image = None Application.tk_set_image(self.deck, self.card_sprites["back"]) Application.tk_set_image(self.house_hand, hh_image) def tk_set_image(tk_object, img): if(img == None): tk_object["image"] = "" tk_object.image = None else: pimg = ImageTk.PhotoImage(img) tk_object["image"] = pimg tk_object.image = pimg def widgets_create(self): card_padx = 5 card_pady = 10 self.menu = tk.Menu(self.master) self.master.config(menu=self.menu) self.filemenu = tk.Menu(self.menu, tearoff=False) self.menu.add_cascade(label="File", menu=self.filemenu) self.filemenu.add_command(label="Configuration", command=self.dialog_config) self.f1 = tk.Frame(self) self.f1["bg"] = self.bg_color self.f1.pack(side="left", fill="both", expand=0) self.f2 = tk.Frame(self) self.f2["bg"] = self.bg_color self.f2.pack(side="left", fill="both", expand=1) self.f3 = tk.Frame(self) self.f3["bg"] = self.bg_color self.f3.pack(side="right", fill="y", expand=0) self.deck = tk.Label(self.f1) # self.deck["visible"] = False self.deck.grid(row=0, column=0, columnspan=2, padx=20, pady=10) self.l_deck_ct = tk.Label(self.f1, text="Decks: ") self.l_deck_ct["fg"] = self.t_color self.l_deck_ct["bg"] = self.bg_color self.l_deck_ct.grid(row=1, column=0, sticky="e") self.l_deck_ct_val = tk.Label(self.f1, text=str(self.game.decks)) self.l_deck_ct_val["fg"] = self.t_color self.l_deck_ct_val["bg"] = self.bg_color self.l_deck_ct_val.grid(row=1, column=1, sticky="w") self.l_card_ct = tk.Label(self.f1, text="Card Count: ") self.l_card_ct["fg"] = self.t_color self.l_card_ct["bg"] = self.bg_color self.l_card_ct.grid(row=2, column=0, sticky="e") self.l_card_ct_val = tk.Label(self.f1, text=str(len(self.game.deck))) self.l_card_ct_val["fg"] = self.t_color self.l_card_ct_val["bg"] = self.bg_color self.l_card_ct_val.grid(row=2, column=1, sticky="w") self.l_money = tk.Label(self.f1, text="Money: ") self.l_money["fg"] = self.t_color self.l_money["bg"] = self.bg_color self.l_money.grid(row=3, column=0, sticky="e") self.l_money_val = tk.Label(self.f1, text=str(self.game.money)) self.l_money_val["fg"] = self.t_color self.l_money_val["bg"] = self.bg_color self.l_money_val.grid(row=3, column=1, sticky="w") self.l_bet = tk.Label(self.f1, text="Bet: ") self.l_bet["fg"] = self.t_color self.l_bet["bg"] = self.bg_color self.l_bet.grid(row=4, column=0, sticky="e") self.l_bet_val = tk.Label(self.f1, text=str(self.game.bet)) self.l_bet_val["fg"] = self.t_color self.l_bet_val["bg"] = self.bg_color self.l_bet_val.grid(row=4, column=1, sticky="w") self.b_change_bet = tk.Button(self.f1, text="Change", command=self.change_bet) self.b_change_bet["fg"] = self.t_color self.b_change_bet["bg"] = self.bg_color self.b_change_bet["activebackground"] = self.h_color self.b_change_bet["activeforeground"] = self.t_color self.b_change_bet.grid(row=4, column=2, sticky="w") self.f_house = tk.Frame(self.f2) self.f_house["bg"] = self.bg_color self.f_house.pack(side="top") self.house_hand = tk.Label(self.f_house) self.house_hand["bg"] = self.bg_color self.house_hand.grid(row=0, column=1, padx=card_padx, pady=card_pady) self.f_split = tk.Frame(self.f2) self.f_split["bg"] = self.bg_color self.f_split.pack(side="top", fill="both", expand=1) self.l_game_result = tk.Label(self.f_split) self.l_game_result["bg"] = self.bg_color self.l_game_result["fg"] = self.t_color self.l_game_result["font"] = ("Helvetica", 30) self.l_game_result.pack(fill="both", expand=1) self.f_player = tk.Frame(self.f2) self.f_player["bg"] = self.bg_color self.f_player.pack(side="top", expand=0, padx=card_padx, pady=card_pady) self.l_player_hands = [] l_player_hand0 = tk.Label(self.f_player) l_player_hand0["bg"] = self.bg_color l_player_hand0.pack(side="left") self.l_player_hands.append(l_player_hand0) l_player_hand1 = tk.Label(self.f_player) l_player_hand1["bg"] = self.bg_color l_player_hand1.pack(side="left") self.l_player_hands.append(l_player_hand1) l_player_hand2 = tk.Label(self.f_player) l_player_hand2["bg"] = self.bg_color l_player_hand2.pack(side="left") self.l_player_hands.append(l_player_hand2) l_player_hand3 = tk.Label(self.f_player) l_player_hand3["bg"] = self.bg_color l_player_hand3.pack(side="left") self.l_player_hands.append(l_player_hand3) self.f_buttons = tk.Frame(self.f3) self.f_buttons["bg"] = self.bg_color self.f_buttons.pack(side="bottom") self.b_hit = tk.Button(self.f_buttons) self.b_hit["text"] = "Hit" self.b_hit["command"] = self.board_hit self.b_hit["state"] = "disabled" self.b_hit.grid(row=0, column=0, sticky="nsew") self.b_double = tk.Button(self.f_buttons) self.b_double["text"] = "Double" self.b_double["command"] = self.board_double self.b_double["state"] = "disabled" self.b_double.grid(row=1, column=0, sticky="nsew") self.b_split = tk.Button(self.f_buttons) self.b_split["text"] = "Split" self.b_split["command"] = self.board_split self.b_split["state"] = "disabled" self.b_split.grid(row=2, column=0, sticky="nsew") self.b_hold = tk.Button(self.f_buttons) self.b_hold["text"] = "Hold" self.b_hold["command"] = self.board_hold self.b_hold["state"] = "disabled" self.b_hold.grid(row=3, column=0, sticky="nsew") self.b_deal = tk.Button(self.f_buttons) self.b_deal["text"] = "Deal Cards" self.b_deal["command"] = self.board_deal self.b_deal.grid(row=4, column=0, sticky="nsew") self.b_clear = tk.Button(self.f_buttons) self.b_clear["text"] = "Clear Board" self.b_clear["command"] = self.board_clear self.b_clear.grid(row=5, column=0, sticky="nsew") self.b_shuffle = tk.Button(self.f_buttons) self.b_shuffle["text"] = "Shuffle" self.b_shuffle["command"] = self.board_shuffle self.b_shuffle.grid(row=6, column=0, sticky="nsew")