2017-02-22 14 views
0

Я пытаюсь создать текстовую ориентированную карточную игру. Два игрока рисуют карту каждый из колоды карт, и игрок с самой сильной картой выигрывает. У меня есть четыре класса для этой игры: Card, Deck, Player, Game. Мой вопрос: как я могу сравнить каждую карту игроков друг с другом и определить самую сильную. Все другие предложения по поводу кода приветствуются. С наилучшими пожеланиями, HWG.Как сравнить значения двух игральных карт, когда они имеют значение и костюм? Python3

Вот мой код:

Card

class Card(): 

    values = [None, None, 2, 3, 4, 5, 6, 7, 8, 9, 10, "Jack", "Queen", "King", 
     "Ace"] 
    suits = ["hearts", "spades", "diamond", "clubs"] 

    def __init__(self, value, suit): 
     self.value = value 
     self.suit = suit 

    def __repr__(self): 
     return str(self.values[self.value]) + " of " + str(self.suits[self.suit]) 

Deck

from random import shuffle 
from card import Card 

class Deck(): 

    def __init__(self): 
     self.cards = [] 
     for v in range(2, 15): 
      for s in range(4): 
       self.cards.append(Card(v, s)) 
     shuffle(self.cards) 

Игрок

from deck import Deck 

class Player(): 

    def __init__(self, name): 
     self.name = name 
     self.card = None 
     self.wins = 0 

игры

from player import Player 
from deck import Deck 
import getch 

class Game(): 

    def __init__(self): 
     player1_name = input("Player One Name: ") 
     player2_name = input("Player Two Name: ") 
     self.deck = Deck() 
     self.player1 = Player(player1_name) 
     self.player2 = Player(player2_name) 
     self.cards = self.deck.cards 

    def game_loop(self): 
     while len(self.cards) >= 2: 
      print("\nPress enter to draw") 
      getch.getch() 
      player1_card = self.cards.pop() 
      player2_card = self.cards.pop() 
+0

Я думаю, вы должны тщательно рассмотреть ваши представления - значения представляют собой смесь «int» и «str» и подходят только «str» ... И фактически, сами фактические экземпляры имеют атрибуты, которые являются «ints», которые соответствуют индексам на уровне класса «Карта» переменные. Вы видите какие-то проблемы? Это своего рода канонический случай использования для 'enum' –

+0

Могу ли я каким-либо образом использовать индексы стоимости и костюма в списках (значения и костюмы) для сравнения двух карт? – HWG

+0

Да, конечно. Кажется грязным для меня. Я бы определенно использовал 'enum's. Ваш код будет намного читабельнее и красив и аккуратен. Но, конечно, вы можете использовать индексы. –

ответ

0

Вы могли бы реализовать оператор для вашего класса карты __gt__(), __lt__(), и т.д ...

, чем вы можете использовать несколько стандартных библиотечные функции, как максимум(), чтобы определить более высокую карту стоимости или палубу и даже можете использовать сорт(), чтобы просто отсортировать «руку», например, список [Карточка, Карточка, ...].

1

Вот эскиз подхода. Вы можете легко комбинировать это с вашим собственным подходом, самым большим изменением для класса Card. Здесь я использовал namedtuple сделать Card класс, но ваш текущий класс может просто обернуть значение tuple:

import enum 
from functools import total_ordering 
from collections import namedtuple 

@total_ordering 
class OrderedEnum(enum.Enum): 
    def __lt__(self, other): 
     if isinstance(other, type(self)): 
      return self.value < other.value 
     return NotImplemented 

Rank = OrderedEnum('Rank', ['one', 'two', 'three', 'four', 'five', 'six', 
        'seven', 'eight', 'nine', 'jack', 'queen','king', 'ace']) 

Suit = OrderedEnum('Suit', ['clubs', 'diamonds', 'hearts', 'spades']) 

Card = namedtuple('Card', ['rank', 'suit']) 

c1 = Card(Rank.four, Suit.clubs) 
c2 = Card(Rank.four, Suit.spades) 
c3 = Card(Rank.ace, Suit.diamonds) 

Теперь в действии: сортировка

>>> c1 
Card(rank=<Rank.four: 4>, suit=<Suit.clubs: 1>) 
>>> c2 
Card(rank=<Rank.four: 4>, suit=<Suit.spades: 4>) 
>>> c1 < c2 
True 
>>> c1 > c3 
False 

Кортеж лексикографический! Ницца!

>>> hand = [c2, c1, c3] 
>>> hand 
[Card(rank=<Rank.four: 4>, suit=<Suit.spades: 4>), Card(rank=<Rank.four: 4>, suit=<Suit.clubs: 1>), Card(rank=<Rank.ace: 13>, suit=<Suit.diamonds: 2>)] 
>>> sorted(hand) 
[Card(rank=<Rank.four: 4>, suit=<Suit.clubs: 1>), Card(rank=<Rank.four: 4>, suit=<Suit.spades: 4>), Card(rank=<Rank.ace: 13>, suit=<Suit.diamonds: 2>)] 
>>> 

Обратите внимание, я использовал total_ordering декоратора, который просто ярлык, а на самом деле, я думаю, что это могло бы быть лучше просто сделать весь класс вручную. Here's рецепт.

EDIT Таким образом, разработка, вот как я бы реализовать свои Card и Deck классы. Обратите внимание, насколько более читаемым будет ваш код, когда вы используете enum и namedtuple.

import enum 
from functools import total_ordering 
from collections import namedtuple 
from random import shuffle 

@total_ordering 
class OrderedEnum(enum.Enum): 
    def __lt__(self, other): 
     if isinstance(other, type(self)): 
      return self.value < other.value 
     return NotImplemented 

Rank = OrderedEnum('Rank', ['one', 'two', 'three', 'four', 'five', 'six', 
        'seven', 'eight', 'nine', 'jack', 'queen','king', 'ace']) 
Suit = OrderedEnum('Suit', ['clubs', 'diamonds', 'hearts', 'spades']) 
CardValue = namedtuple('CardValue', ['rank', 'suit']) 

@total_ordering 
class Card(object): 
    def __init__(self, rank, suit): 
     self.value = CardValue(rank, suit) 
    def __repr__(self): 
     return "Card({:s}, {:s})".format(self.value.rank, self.value.suit) 
    def __lt__(self, other): 
     if isinstance(other, type(self)): 
      return self.value < other.value 
     return NotImplemented 
    def __eq__(self, other): 
     if isinstance(other, type(self)): 
      return self.value == other.value 
     return NotImplemented 

class Deck(object): 
    def __init__(self): 
     self.cards = [] 
     for rank in Rank: 
      for suit in Suit: 
       self.cards.append(Card(rank, suit)) 
     shuffle(self.cards) 

Теперь в действии:

>>> deck = Deck() 
>>> c1 = deck.cards.pop() 
>>> c2 = deck.cards.pop() 
>>> c1 
Card(Rank.queen, Suit.hearts) 
>>> c2 
Card(Rank.king, Suit.clubs) 
>>> c1 == c2 
False 
>>> c1 > c2 
False 
>>> c1 < c2 
True 
>>> c1.value 
CardValue(rank=<Rank.queen: 11>, suit=<Suit.hearts: 3>) 
>>> c2.value 
CardValue(rank=<Rank.king: 12>, suit=<Suit.clubs: 1>) 

Кроме того, обратите внимание, что __repr__ должны попытаться представлять объект, если вы хотите красивое сообщение, используйте __str__. См. this question

0

Я бы рекомендовал вам хранить значение каждой карты как int, поэтому вы можете сравнивать их, а не использовать строки, такие как «Король» или «Туз». Вы можете сделать это и изменить repr(), чтобы напечатать человеческую удобочитаемую версию, используя эти строки.

Класс карты может выглядеть следующим образом:

class Card(object): 
    suits = ["Clubs", "Diamonds", "Hearts", "Spades"] #list of suits 
    values = [None, "Ace", "2", "3", "4", "5", "6", "7", "8", "9", "10", "Jack", "Queen", "King"] #list of card values 

    def __init__(self, suit= 0, value= 2): 
     """ 
     Initializes card 
     :param suit: Suit of card int value 0-3 
     :param value: Value of card int value 0-13 
     """ 
     self.suit = suit 
     self.value = value 

    def __str__(self): 
     """ 
     Returns a readable format of the card 
     """ 
     return "%s of %s" %(Card.values[self.value], 
          Card.suits[self.suit]) 

Обратите внимание, как стоимость карты хранится как межд все время.

В классе игры вы могли бы иметь функцию, которая сравнивает две карты, я не знаю, как вы хотите это сделать, но это может выглядеть примерно так:

def compare(card1, card2): 
    """ 
    Compares the value of two cards and returns the greater of the two 
    :param card1: A card object 
    :param card2: A second card object 
    :return: The higher value card, if tie returns 0 
    """ 
    if card1.value > card2.value: 
     return card1 
    elif card2.value == card1.value: 
     return 0 
    else: 
     return card2 
+0

Да, но теперь 'card1.value> 48' будет фактически оценено. Нехорошо. Это прототипный случай для 'enum'. И ваша функция 'compare' - это не то, что вы сделали бы, если бы у вас уже был класс, вместо этого вы бы использовали богатые операторы сравнения. –