首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >OO Blackjack游戏设计

OO Blackjack游戏设计
EN

Code Review用户
提问于 2015-01-24 20:13:29
回答 1查看 1.1K关注 0票数 5

我设置了carddeckhandplayerdealergame类。游戏类的存在是为了将大量的逻辑排除在接口(main.py)之外。告诉我对此有什么想法。

我还没有运行吡咯烷酮或PEP8检查,所以请记住这一点!

main.py

代码语言:javascript
运行
复制
from game import Game
from card import Card
from deck import Deck
from hand import Hand
from player import Player
from dealer import Dealer


name = input("Please enter your name: ")

dealer = Dealer()
player = Player(name)
deck = Deck()
game = Game(dealer, player, deck)
game_loop = True

while game_loop:

    game.new_turn()

    print("You have {} dollars".format(game.player.stack))
    print("How much would you like to bet?")
    game.place_bet(input("> "))

    game.dealer.show_hand()
    game.player.show_hand()

    hit = game.hit_or_stand()

    while hit and not game.player.hand.bust():
        game.player.hit(game.deck)
        game.player.show_hand()
        if game.player.hand.best_hand < 21:
            hit = game.hit_or_stand() #player can't bust

    if player.hand.best_hand <= 21 and dealer.hand.best_hand != 21:
        game.dealer.play_out_hand(game.deck)
        game.dealer.reveal_hand()
        game.player.show_hand()

        if game.dealer.hand.best_hand > 21:
            print("Dealer busts!, you win!")
            game.player.stack += game.pot * 2
        else:
            game.check_for_winner(game.dealer, game.player)
    else:
        if dealer.hand.best_hand == 21:
            print("Dealer has blackjack! You lose!")
        else:
            print("Your hand is over 21, you lose!!")

    if player.stack < 1:
        print("You are out of money! Game over!")
        break

    game_loop = game.play_again()

game.py

代码语言:javascript
运行
复制
from dealer import Dealer
from player import Player
from hand import Hand
from card import Card
from deck import Deck, Clubs, Diamonds, Hearts, Spades


class Game:
    """Information about the game.

    Responsibilities:

    * Check for winner
    * Handles betting and bankroll
    * Resets the game and hands

    Collaborators

    * Checks the player and dealer's hand amounts and compares them
    """

    def __init__(self, dealer, player, deck):
        self.dealer = dealer
        self.player = player
        self.deck = deck
        self.pot = 0

    def play_again(self):
        choice = input('Press "p" to play again or "q" to quit: ').lower()
        return choice == 'p'


    def hit_or_stand(self):
        choice = input('Press "h" to Hit, or "s" to stand: ').lower()
        return choice == 'h'

    def check_for_winner(self, dealer, player):
        if self.player.hand.best_hand < self.dealer.hand.best_hand:
            return("You Lose")
        elif self.dealer.hand.best_hand < self.player.hand.best_hand:
            print("You Win!")
            self.player.stack += self.pot * 2
        elif self.dealer.hand.best_hand == self.player.hand.best_hand:
            print("Push!")
            self.player.stack += self.pot

    def new_turn(self):
        self.dealer.hand.reset_hand()
        self.player.hand.reset_hand()
        self.deck = Deck()
        self.deck.shuffle()
        self.dealer.hand.new_hand(self.deck)
        self.player.hand.new_hand(self.deck)
        self.pot = 0


    def place_bet(self, amount):
        try:
            int(amount)
            if int(amount) <= self.player.stack:
                self.player.stack -= int(amount)
                self.pot += int(amount)
            else:
                self.place_bet(input("Not enough funds! You have {} dollars. "
                                     "Place a bet: ".format(self.player.stack)))
        except ValueError:
            self.place_bet(input("Place a bet: "))

player.py

代码语言:javascript
运行
复制
class Player:
    """The player of the blackjack game.

    Responsibilities:

    * Holds a hand
    * Can bet
    * Can hit
    * Can display hand

    Collaborators:

    *Uses a hand of cards
    """
    def __init__(self, name, stack = 100, hand = None):
        if hand is None:
            hand = Hand([])
        self.name = name
        self.hand = hand
        self.cards = hand.hand
        self.stack = stack


    def hit(self, deck):
        self.hand.draw(deck)


    def bet(self, amount):
        chips = self.stack
        new_chips = chips - amount
        self.stack = new_chips
        return self.stack

    def show_hand(self):
        print("{name}'s hand: {hand} ({value})".format(name = self.name,
                                               hand = self.hand,
                                               value = self.hand.best_hand))

dealer.py

代码语言:javascript
运行
复制
from hand import Hand
from player import Player

class Dealer():
    """The dealer of the blackjack game. The dealer doesn't actually deal
    cards, but holds a hand for the purpose of the game.

    Responsibilities:

    * Holds a Hand of Cards
    * Hits until 17 or more, if over 21 returns bust
    * Has facedown card

    Collaborators

    * Gets a hand of cards from the deck
    """

    def __init__(self, hand = None):
        if hand == None:
            hand = Hand([])
        self.name = "Dealer"
        self.hand = hand


    def hit(self, deck):
        self.hand.draw(deck)


    def play_out_hand(self, deck):
        while self.hand.soft_total < 17:
            if self.hand.hard_total >= 17 and self.hand.hard_total <= 21:
                return self.hand.hard_total
                break
            self.hand.draw(deck)
        return self.hand.soft_total

    def show_hand(self):
        print("{name}'s hand: XX {hand}".format(name = self.name, hand = self.hand.hand[1]))

    def reveal_hand(self):
        print("{name}'s hand: {hand} ({value})".format(name = self.name,
                                               hand = self.hand,
                                               value = self.hand.best_hand))

deck.py

代码语言:javascript
运行
复制
from card import Card
from random import shuffle


#assign unicode chararcters for each suit
Clubs, Diamonds, Hearts, Spades = u'\u2663', u'\u2666', u'\u2665', u'\u2660'
SUITS = (Clubs, Diamonds, Hearts, Spades)
RANKS = (2, 3, 4, 5, 6, 7, 8, 9, 10, 'J', 'Q', 'K', 'A')


class Deck:
    """A playing card deck.

    Responsibilities:

    * Can hold cards.
    * New deck should have all 52 cards.
    * Should allow others to draw cards.
    * Should be able to reshuffle itself
    * Should be able to report its current size

    Collaborators:

    * Can hold cards.
    * Can be put into shoe for dealing and shuffling
    """
    def __init__(self):
        self._cards = [Card(rank, suit)
                      for rank in RANKS
                      for suit in SUITS]


    def draw(self):
        """Take a card off the top of the deck and return it"""
        return self._cards.pop()


    def shuffle(self):
        """Shuffles cards in the deck"""
        shuffle(self._cards)
        return self


    def __eq__(self, other):
        return self._cards == other._cards

    def __len__(self):
        return len(self._cards)

    def __str__(self):
        deck_list = [str(card) for card in self._cards]
        return ", ".join(deck_list)

    def __repr__(self):
        return self.__str__()

hand.py

代码语言:javascript
运行
复制
class Hand:
"""An assortment of cards

Responsibilitites:

* Can hold x cards
* Has a hard or soft total for hand, aces depend on hand
* Can add cards to hand
* Check if hand is busted (over 21)

Collaborators:

* A Hand is made up of Cards
* A Player and Dealer can hold a hand
* The shoe can deal to the hand
"""

def __init__(self, hand):
    self.hand = hand


@property
def hard_total(self):
    hard_total = 0
    for card in self.hand:
        if type(card.rank) == str:
            if card.rank == 'A':
                hard_total += 11
            else:
                hard_total += 10
        else:
            hard_total += card.rank
    return hard_total


@property
def soft_total(self):
    soft_total = 0
    for card in self.hand:
        if type(card.rank) == str:
            if card.rank == 'A':
                soft_total += 1
            else:
                soft_total += 10
        else:
            soft_total += card.rank
    return soft_total

@property
def best_hand(self):
    if self.hard_total > 21:
        return int(self.soft_total)
    else:
        return int(self.hard_total)



def bust(self):
    if self.soft_total > 21:
        return True
    else:
        return False


def draw(self, deck):
    card = deck.draw()
    self.hand.append(card)


def new_hand(self, deck):
    self.draw(deck)
    self.draw(deck)


def reset_hand(self):
    self.hand = []
    print(self.hand)



def __str__(self):
    hand_list = [str(card) for card in self.hand]
    return str(', '.join(hand_list))


def __repr__(self):
    return self.__str__()

card.py

代码语言:javascript
运行
复制
from collections import namedtuple

"""A playing card.

Responsibilities:

* Has a rank and suit

Collaborators:

* Collected into a Deck
* Collected into a Hand for each player and a Hand for the dealer.
"""

class Card(namedtuple('card', ['rank', 'suit'])):

    __memory__ = () #assure instance is stored as a tuple in memory

    def __str__(self):
        return "{}{}".format(self.rank, self.suit)

    def __repr__(self):
        return self.__str__()
EN

回答 1

Code Review用户

发布于 2015-01-25 08:38:17

我还没有运行吡咯烷酮或PEP8检查,所以请记住这一点!

嗯,你为什么没有呢?这是个反问句。你应该运行这些程序,而你关于没有运行的声明无论如何也无助于评审者,除非有人认为你是故意的粗心。

Strange things

这有点奇怪:

if game.dealer.hand.best\_hand > 21: print("Dealer busts!, you win!") game.player.stack += game.pot \* 2 else: game.check\_for\_winner(game.dealer, game.player)

if分支打印一些东西,else分支不.快速查看一下game.check_for_winner

def check_for_winner(自我,经销商,玩家):如果self.player.hand.best_hand < self.dealer.hand.best_hand:返回(“你输了”) elif self.dealer.hand.best_hand < self.player.hand.best_hand:打印(“你赢了!”)self.player.stack += self.pot *2 elif self.dealer.hand.best_hand == self.player.hand.best_hand: print("Push!")self.player.stack += self.pot

该方法有时返回字符串,有时打印字符串。你应该让它表现得始终如一。这可能是一个错误,您的意思是print而不是return。但即使如此,这也不太好:游戏结果的打印分为两部分:maingame。最好让main完全负责这件事,把逻辑放在一个地方。

另外,最后一个elif应该是一个简单的else

game.place_bet中,这真的很奇怪:

try: int(amount) if int(amount) <= self.player.stack: self.player.stack -= int(amount) self.pot += int(amount) else: self.place\_bet(input("Not enough funds! You have {} dollars. " "Place a bet: ".format(self.player.stack))) except ValueError: self.place\_bet(input("Place a bet: "))

为什么多次调用int(amount),多次将字符串解析为整数?最好只做一次并保存在一个变量中。

命名

stack是一个奇怪的名字,一个锅或赌注。这尤其糟糕,因为在编程过程中,“堆栈”一词会产生特定的数据结构,从而使代码具有误导性和难以阅读的功能。即使“堆栈”在“黑杰克”(我不知道)中是正确且最明显的术语,我还是建议找一些其他的词。

这有点让人困惑:

game.dealer.reveal\_hand() game.player.show\_hand()

“显示”和“揭示”是同义词,这使这些陈述令人困惑。当我必须打开两个函数的实现来了解它们的不同之处时,这是不太好的。

new_turn in game可能会产生误导。这真的是个新游戏。但这也会误导人,因为以" new“开头的方法通常会返回某物的新实例。reset_game会更好。

其他事情

我知道这是黑杰克,目标必须是21,但有时候如果我们用一个不同的数字,比如31,扰乱系统,看看游戏动态如何变化,那就很有趣了。为了使将来的扩展更容易,我将21放入一个全局常量中,并将其命名为BLACKJACK。在任何情况下,我认为这是一个很好的自然反应,发展总是用常数变量代替重复的事物。

票数 4
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/78515

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档