这里是github存储库,如果这里允许的话,因为接收建议似乎很容易。
我正在寻找批评,因为我所学到的一切都是自学成才,主要是以这种方式。自学,实践,建立,张贴,完善,继续前进。
第一段代码是继承的代码。
import time, itertools, random
def countyDots():
for i in range(5):
line = "." * i
print(line, end="")
print("\r", end="")
time.sleep(0.5)
class Card(object):
def __init__(self, rank, suit):
self.rank = rank
self.suit = suit
self.valueChart = {
"2": 2,
"3": 3,
"4": 4,
"5": 5,
"6": 6,
"7": 7,
"8": 8,
"9": 9,
"10": 10,
"J": 10,
"Q": 10,
"K": 10,
"A": 11,
}
def getValues(self):
cardValues = self.valueChart
returnedValue = 0
for rank, value in cardValues.items():
if self.rank == rank:
returnedValue = value
return returnedValue
class Player(object):
def __init__(self):
self.name = self.defineName()
#initialize player bank to $200
self.balance = 200
print("Beginning Balance: $200.00 USD\n")
##initialize player hand
self.hand = []
#initialize score and currentBet to 0
self.score = 0
self.bet = 0
def placeBet(self):
currentBet = input(f"BALANCE: ${self.balance}\nHow much would you like to bet? (1, 2, 5, 10, 25): ")
def is_number(n):
try:
int(n)# Type-casting the string to `float`.
# If string is not a valid `float`,
# it'll raise `ValueError` exception
except ValueError:
return False
return True
if is_number(currentBet):
currentBet = int(currentBet)
if currentBet in (1, 2, 5, 10, 25):
self.balance -= currentBet
self.bet = currentBet
print(f"\nCurrent Bet: {currentBet}\nBALANCE: {self.balance}\n")
else:
self.placeBet()
else:
self.placeBet()
def defineName(self):
#Ask for name from user
newName = input("What is your Name?: ")
#confirm new name with user
confirmation = input(f"Your name is {newName}, correct? (Y/N): ")
#convert confirmation to all lowercase and eliminate whitespace
confirmation = confirmation.lower().strip()
while confirmation != "y":
newName = input("Sorry. What is your Name?: ")
countyDots()
confirmation = input(f"So you prefer to be called {newName}? (Y/N): ")
confirmation = confirmation.lower().strip()
if confirmation == "y":
return newName
def showHand(self):
print(f"{self.name}'s HAND")
for card in self.hand:
rank = card[0]
suit = card[1]
print(f"{rank} of {suit}")
def getAction(self):
action = input("Would you like to HIT or STAND?: ")
action = action.lower().strip()
return action
def calculateScore(self):
self.score = 0
for card in self.hand:
rank = card[0]
suit = card[1]
card = Card(rank, suit)
value = card.getValues()
self.score += value
print(f"{self.name}'s SCORE: {self.score}\n")
return self.score
def showBalance(self):
print(f"BALANCE: {self.balance}")
class Dealer(object):
def __init__(self):
self.name = "Dealer"
#initialize a dealer score to 0
self.score = 0
#initialize a dealer hand
self.hand = []
#initialize a dealer bank of 1,000,000
self.bank = 1000000
def showHand(self):
print(f"{self.name}'s HAND")
for card in self.hand:
rank = card[0]
suit = card[1]
print(f"{rank} of {suit}")
def calculateScore(self):
self.score = 0
for card in self.hand:
rank = card[0]
suit = card[1]
card = Card(rank, suit)
value = card.getValues()
self.score += value
print(f"{self.name}'s SCORE: {self.score}\n")
return self.score
class Deck(object):
def __init__(self):
self.deck = []
self.ranks = (
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"10",
"J",
"Q",
"K",
"A",
)
def buildDeck(self):
suits = ("Spades ♠", "Clubs ♣", "Hearts ♥", "Diamonds ♦")
cards = list(itertools.product(self.ranks, suits))
random.shuffle(cards)
for card in cards:
self.deck.append(card)
return self.deck
class Shoe(Deck):
def __init__(self):
self.shoe = []
def buildShoe(self):
for i in range(5):
newDeck = Deck()
newDeck.buildDeck()
for card in newDeck.deck:
self.shoe.append(card)
def dealCard(self):
gameDeck = self.shoe
dealtCard = self.shoe[0]
self.shoe.pop(0)
return dealtCard第二位代码是在底部执行的gameLogic文件。
class GameLogic(object):
def __init__(self, player, dealer, shoe):
self.player = player
self.dealer = dealer
self.gameShoe = shoe
def beginGame(self):
self.dealer.hand = []
self.player.hand = []
#initalize the players first bet
self.player.placeBet()
#initialize the shoe of cards (5 decks of cards)
self.gameShoe.buildShoe()
self.player.hand.append(self.gameShoe.dealCard())
self.dealer.hand.append(self.gameShoe.dealCard())
self.player.hand.append(self.gameShoe.dealCard())
self.dealer.hand.append(self.gameShoe.dealCard())
self.player.showHand()
self.player.calculateScore()
countyDots()
self.dealer.showHand() #These need to be changed so that they reflect one face up card
self.dealer.calculateScore() #and one face down card
countyDots()
self.playerAction(self.player.getAction())
def keepPlaying(self):
userResponse = input("\nPRESS ENTER FOR NEXT HAND\nType 'EXIT' to quit game\n")
userResponse = userResponse.lower().strip()
if userResponse == "":
self.beginGame()
elif userResponse == "exit":
exit()
else:
self.keepPlaying()
def playerAction(self, action):
if action == "hit":
print("You chose to Hit")
#player takes on an additional card
self.player.hand.append(self.gameShoe.dealCard())
self.player.showHand()
self.player.calculateScore()
if self.player.score <= 21:
newAction = self.player.getAction()
self.playerAction(newAction)
elif self.player.score > 21:
print("BUSTED!!! YOU LOSE")
#Proceed to
self.dealer.showHand()
#set currentbet to 0
self.player.bet = 0
self.keepPlaying()
#show dealers hand for good faith
#set player bet to 0
#set forth with "would you like to play another round"
#if player total score isnt higher than 21, we ask the same question
#if the player total score is higher than 21, we end the game immediately and proceed to ask endgame()
elif action == "stand":
print("You chose to STAND\n")
#if action is to stand then we need to proceed forward with the game logic for the dealer.
self.dealer.showHand()
self.dealer.calculateScore()
while self.dealer.score < 16:
countyDots()
self.dealer.hand.append(self.gameShoe.dealCard())
self.dealer.showHand()
self.dealer.calculateScore()
if self.dealer.score > 21:
print("The dealer has busted!")
#pay the player the player 2times their bet
payout = self.player.bet * 2
self.player.balance += payout
print(f"{self.player.name} WON {self.player.bet}")
self.player.showBalance()
#reset bet to 0 for the next round
self.player.bet = 0
self.keepPlaying()
elif self.dealer.score <= 21 and self.dealer.score >= 16:
if self.player.score > self.dealer.score:
print("The player WINS!")
#pay the player the player 2times their bet
payout = self.player.bet * 2
self.player.balance += payout
print(f"{self.player.name} WON {self.player.bet}")
self.player.showBalance()
#reset bet to 0 for the next round
self.player.bet = 0
self.keepPlaying()
elif self.player.score <= self.dealer.score:
print("The PLAYER LOSES!")
print(f"{self.player.name} LOST {self.player.bet}")
self.player.showBalance()
#reset bet to 0 for the next round
self.player.bet = 0
self.keepPlaying()
else:
print("Some Real Bad shit happened herrrrrr")
#initialize a dealer
dealer1 = Dealer()
#initialize a player
player1 = Player()
#initialize a game shoe
gameShoe = Shoe()
#Initialize GamePlay
game = GameLogic(player1, dealer1, gameShoe)
#Begin Game Play
game.beginGame()发布于 2022-10-04 18:28:24
class Card(object):被废弃为Python2语法。使用Python3,(object)基类是隐含的,只是不必要的混乱。写class Card:就行了。
每个Card都有一个字典,将卡级转换为一个值。一副牌里有52张牌,你就会有52个相同的字典。鞋里有5层甲板,你会有260本相同的字典!
此外,每个Deck都有一个ranks元组。5层产生5个相同的元组的牌号。
(另外,一个Shoe继承了Deck (后来更多),所以更多的副本??)
您应该在您的程序中,在一个全局结构中指定一次卡级。在这方面,Enum是一个很好的选择:
from enum import Enum
class Rank(Enum):
TWO = ('2', 2)
THREE = ('3', 3)
FOUR = ('4', 4)
FIVE = ('5', 5)
SIX = ('6', 6)
SEVEN = ('7', 7)
EIGHT = ('8', 8)
NINE = ('9', 9)
TEN = ('10', 10)
JACK = ('J', 10)
QUEEN = ('Q', 10)
KING = ('K', 10)
ACE = ('A', 11)
@property
def symbol(self):
return self.value[0]
@property
def points(self):
return self.value[1]同样,您也可以使用Enum来制作西装:
class Suit(Enum):
CLUBS = ('Clubs', '♣')
DIAMONDS = ('Diamonds', '♦')
HEART = ('Hearts', '♥')
SPADES = ('Spades', '♠')
@property
def suit_name(self):
return self.value[0]
@property
def symbol(self):
return self.value[1]一张卡片是一对价值:等级和套装。但更重要的是,它有一个字符串来描述它,比如"Queen of Clubs ♣"。您可以在两个不同的位置使用f"{rank} of {suit}"将一个卡片(实际上是一个元组)转换为一个合适的字符串。因为您有一个Card类,所以它应该能够将自己转换成一个合适的字符串。
一张牌有一个点值,这个值(在21点的情况下)完全由牌的等级决定。但是我们不应该要求卡片的等级,然后把它转换成一个点值,相反,我们应该只要求卡片的点值,让它从它的排名和适应来确定它的价值。
牌是不可变的。如果你有一个Card,你不应该能够把它换成另一套衣服,或者用一个像card.rank = 'A'这样的语句来排名。我们可以使用dataclass使我们的Card对象抵抗恶意更改:
from dataclasses import dataclass
...
@dataclass(frozen=True)
class Card:
rank: Rank
suit: Suit
def point_value(self):
return self.rank.points
def __str__(self):
return f"{self.rank.symbol} of {self.suit.suit_name} {self.suit.symbol}">>> card = Card(Rank.ACE, Suit.SPADES)
>>> print(card)
A of Spades ♠
>>> print(card.point_value())
11class Deck(object):
def __init__(self):
self.deck = []真奇怪。如果我创建了一副牌,deck = Deck(),它没有任何卡在里面!
一副牌的构造函数实际上应该创建一副牌:
class Deck(object):
def __init__(self):
self.deck = [Card(rank, suit) for rank, suit in itertools.product(Rank, Suit)]请注意,上面实际上在这里创建了一个Card对象列表,而不仅仅是秩和适合值的元组。
您的Deck类的功能似乎相当有限。你不能把牌退到牌上,也不能把剩下的牌洗牌,以此类推。
class Shoe(Deck):
def __init__(self):
self.shoe = []正如所写的,Shoe是一个Deck,但是没有Deck的任何功能。虽然它是从Deck继承的,但由于super().__init__()从未被调用,这种继承就中断了。Show().buildDeck()将给一个AttributeError。
Shoe不是Deck;不要继承它。
该鞋是由5个甲板,顺序!想象一下,你有5个甲板,有红色、黄色、绿色、蓝色和橙色的背。你把每一个甲板都单独地洗洗,然后把它们一个堆放在鞋的另一个上面,而不把它们放在一起。这样就不可能(而不是不太可能)从鞋中依次画出三个"Ace of Spaces♠“。
你应该把5层的卡片加到鞋里,然后再把鞋子洗牌。
发布于 2022-10-04 18:57:30
有几个方法包含不必要的递归,即这些方法包含对自己的调用。我注意到了(在Player.placeBet()、GameLogic.keepPlaying()和GameLogic.playerAction()中),但可能还有更多。这是非常危险的-它基本上意味着,如果你玩足够长的时间,你的游戏将耗尽内存,并将崩溃与一个RecursionError。
这意味着您必须修改这些部分,可能需要使用适当的while循环。下面是placeBet()的一个修订版--注意while True循环的使用,即一个非常流行的Python成语。对于其他有问题的方法,您也可以采用。
def place_bet(self):
while True:
response = input(f"BALANCE: ${self.balance}\n"
"How much would you like to bet? (1, 2, 5, 10, 25): ")
try:
bet = int(response)
except ValueError:
print("Please enter a number!")
else:
if bet not in (1, 2, 5, 10, 25):
print("Only bets of 1, 2, 5, 10, or 25 are possible.")
else:
self.balance -= bet
self.bet = bet
print(f"\nCurrent Bet: {currentBet}\nBALANCE: {self.balance}\n")
break许多方法包含不必要的局部变量。例如,Card.getValues()创建cardValues (valueChart的副本)以及变量returnedValues。您可以通过创建另外两个循环变量rank和value来遍历D18,这两个变量也是不需要的:基本上,这里所需要的是:
def getValues(self):
return self.valueChart[self.rank]考虑到这一点,您可能首先考虑去掉getValues(),因为它可以被简单的字典查找所取代。
GameLogic.playerAction()被压倒的方法- it做的太多了,比你想象的要多得多。它不仅处理选定的行动,它似乎也负责经销商的反应,例如,当玩家输,它负责现金,并为下一轮重置。你真的需要把这里的逻辑分解成更小的部分。
您的代码当前的行为有时有些出乎意料。我注意到的事情:
hir而不是hit)时,您的游戏是非常不可原谅的。像这样的错误应该被另一个while循环捕获。发布于 2022-10-12 04:00:28
其他人说了很多话,我觉得可能没有必要重复。关于你提出的问题,我还有另一个看法:
import random
import time
class Card:
cards_values = {
"2": 2,
"3": 3,
"4": 4,
"5": 5,
"6": 6,
"7": 7,
"8": 8,
"9": 9,
"10": 10,
"J": 10,
"Q": 10,
"K": 10,
"A": 11,
}
allowed_suits = {
"Spades ♠",
"Clubs ♣",
"Hearts ♥",
"Diamonds ♦"
}
def __init__(self, rank, suit):
self.rank = rank
self.suit = suit
@property
def value(self):
return self.cards_values[self.rank]
class Participant:
def __init__(self, name, balance):
self.name = name
self.balance = balance
self.clear_hand()
def receive_card(self, card):
self.hand.append(card)
self.score += card.value
def clear_hand(self):
self.hand = []
self.score = 0
def wins(self, amount):
self.balance += amount
def loses(self, amount):
self.balance -= min(amount, self.balance)
@staticmethod
def ask_user_for_choice(question, choices, please_give_good_answer):
not_chosen = True
while not_chosen:
answer = input(question).upper().strip()
if not_chosen := (answer not in {x.upper().strip() for x in choices}):
print(please_give_good_answer)
return answer
def show_hand_and_score(self):
# Show dots
self.show_dots()
hand = "\n".join(
(
f"{self.name}'s hand:",
'\n'.join(
f"{current_card.rank} of {current_card.suit}"
for current_card in self.hand
)
)
)
print(hand)
print(f"{self.name}'s score: {self.score}")
@staticmethod
def show_dots():
for nb_dots in range(5):
print("." * nb_dots, "\r", end='')
time.sleep(0.5)
print()
def show_balance(self):
print(f"{self.name}'s BALANCE: {self.balance}$")
def has_busted(self):
if has_busted := self.score > 21:
print(f"{self.name} has busted!")
return has_busted
class Player(Participant):
def ask_bet(self):
self.show_balance()
current_bet = int(
self.ask_user_for_choice(
f"How much would you like to bet? (1, 2, 5, 10, 25): ",
("1", "2", "5", "10", "25"),
"Please only choose your bet as one of these choices: 1, 2, 5, 10 or 25"
)
)
if current_bet > self.balance:
raise ValueError(f'Balance (${self.balance})is not big enough for bet (${current_bet})')
return current_bet
def ask_if_hit_is_next_move(self):
player_action = self.ask_user_for_choice(
"Would you like to HIT or STAND? ",
('HIT', 'STAND'),
'Please only answer "HIT" or "STAND"'
)
return player_action == 'HIT'
def has_busted_after_hitting(self, card_received):
self.receive_card(card_received)
self.show_hand_and_score()
return self.has_busted ()
def has_won(self, dealers_score):
return self.score > dealers_score
def wins(self, current_bet):
super().wins(current_bet)
print(f"{self.name} WON {current_bet}$")
def loses(self, current_bet):
super().loses(current_bet)
print(f"{self.name} LOST {current_bet}$")
def ask_if_we_continue(self):
player_answer = self.ask_user_for_choice(
"\nPRESS ENTER FOR NEXT HAND\nType 'EXIT' to quit game\n",
('', 'EXIT'),
'Please only press enter for next hand or type "EXIT" to quit the game'
)
return player_answer == 'EXIT'
class Dealer(Participant):
def __init__(self, name, balance, nb_decks):
super().__init__(name, balance)
self.nb_decks = nb_decks
self.shoe = None
def deal_card(self):
if not self.shoe:
self.create_shoe()
return next(self.shoe)
def create_shoe(self):
def create_deck():
cards = [
Card(current_rank, current_suit)
for current_rank in Card.cards_values
for current_suit in Card.allowed_suits
]
random.shuffle(cards)
return cards
self.shoe = (
current_card
for _ in range(self.nb_decks)
for current_card in create_deck()
)
def has_busted_after_getting_cards(self):
self.show_hand_and_score()
while self.score < 16:
self.receive_card(self.deal_card())
self.show_hand_and_score()
return self.has_busted()
def has_enough_funds_for_bet(self, current_bet):
return self.balance >= current_bet
def already_won(self):
return self.score == 21
def show_hand_and_score(self, hidden=False):
if hidden:
self.show_dots()
hand = "\n".join(
(
f"{self.name}'s hand:",
f"{self.hand[0].rank} of {self.hand[0].suit}",
"(hidden card)"
)
)
print(hand)
else:
super().show_hand_and_score()
class Blackjack_table:
def __init__(self, bank=1000000, nb_decks=5, default_player_starting_bablance=200):
name_not_confirmed = True
while name_not_confirmed:
player_name = input("What name do you want to use? ")
name_not_confirmed = Player.ask_user_for_choice(
f"Is your name {player_name} (Y/N)? ",
'YN',
'Please answer only "Y" or "N"'
) == 'N'
self.player = Player(player_name, default_player_starting_bablance)
self.dealer = Dealer("Dealer", bank, nb_decks)
def play_rounds(self):
finished_playing = False
while not finished_playing:
if self.player.balance <= 0:
print("You don't have any funds left")
break
if self.dealer.balance <= 0:
print("The bank has lost all their funds.")
break
self.player.clear_hand()
self.dealer.clear_hand()
try:
self.current_bet = self.player.ask_bet()
except ValueError as bet_error:
print(bet_error.args[0])
continue
if not self.dealer.has_enough_funds_for_bet(self.current_bet):
print("Sorry, the dealer doesn't have enough funds for this bet")
self.dealer.show_balance()
finished_playing = self.player.ask_if_we_continue()
continue
for _ in range(2):
self.player.receive_card(self.dealer.deal_card())
self.dealer.receive_card(self.dealer.deal_card())
self.player.show_hand_and_score()
self.dealer.show_hand_and_score(hidden=True)
if self.player.has_busted():
self.dealer_wins()
finished_playing = self.player.ask_if_we_continue()
continue
if self.dealer.has_busted():
self.player_wins()
finished_playing = self.player.ask_if_we_continue()
continue
round_is_not_finished = True
while round_is_not_finished:
if self.player.ask_if_hit_is_next_move():
if self.player.has_busted_after_hitting(self.dealer.deal_card()):
self.dealer.show_hand_and_score()
self.dealer_wins()
round_is_not_finished = False
# round_is_not_finished stays True otherwise
else: # player is standing
if self.dealer.has_busted_after_getting_cards():
self.player_wins()
else:
if self.player.has_won(self.dealer.score):
self.player_wins()
else:
self.dealer_wins()
round_is_not_finished = False
finished_playing = self.player.ask_if_we_continue()
print("Gave over. Hope to see you sson!")
def player_wins(self):
print("The player WINS!")
self.player.wins(self.current_bet)
self.dealer.loses(self.current_bet)
self.player.show_balance()
self.dealer.show_balance()
def dealer_wins(self):
print("The player LOSES!")
self.dealer.wins(self.current_bet)
self.player.loses(self.current_bet)
self.player.show_balance()
self.dealer.show_balance()
if __name__ == '__main__':
table = Blackjack_table(100)
table.play_rounds()除了其他人已经说过的话之外,我还要补充说,你们应该研究:
Card类中的方法getValues()本质上是在字典中查找值)for可以帮助您“平整”列表的层次结构。在大多数情况下,我试图:
https://codereview.stackexchange.com/questions/280178
复制相似问题