2016-07-18 13 views
0

Ich habe das folgende Stück Code in Python, es organisiert (Gruppierung) Spielkarten von ihren Reihen. Ich habe das auf alte Schule gemacht, aber ich bin mir sicher, dass es einen besseren Weg gibt, da Python tatsächlich für solche Dinge berühmt ist. Wie kann ich das gleiche auf kürzere und eleganter Weise machen? HierVerbessern Python-Code - wie Listenelemente durch ihre Eigenschaftswerte gruppieren

ist die Methode Code:

def gatherRanks(self, hand): 
     self.value1 = [] 
     self.value2 = [] 
     self.value3 = [] 
     self.value4 = [] 

     card1 = hand.cards[0] 
     self.value1.append(card1) 

     card2 = hand.cards[1] 
     if card2.rank == card1.rank: 
      self.value1.append(card2) 
     else: 
      self.value2.append(card2) 

     card3 = hand.cards[2] 
     if card3.rank == card1.rank: 
      self.value1.append(card3) 
     elif card3.rank == card2.rank: 
      self.value2.append(card3) 
     else: 
      self.value3.append(card3) 

     card4 = hand.cards[3] 
     if card4.rank == card1.rank: 
      self.value1.append(card4) 
     elif card4.rank == card2.rank: 
      self.value2.append(card4) 
     elif card4.rank == card3.rank: 
      self.value3.append(card4) 
     else: 
      self.value4.append(card4) 

     card5 = hand.cards[4] 
     if card5.rank == card1.rank: 
      self.value1.append(card5) 
     elif card5.rank == card2.rank: 
      self.value2.append(card5) 
     elif card5.rank == card3.rank: 
      self.value3.append(card5) 
     elif card5.rank == card4.rank: 
      self.value4.append(card5) 

Die Idee hinter dieser Methode ist es, Gruppenkarten von ihren Rängen (nicht passt). Ich entschied mich auch, 4 Selbstvariablen zu haben, weil es einfacher zu benutzen ist als die Liste. Der Grund ist ganz einfach: Hände später herausfinden. Mit Karten von Reihen gruppiert kann ich dann einfach die Figur überprüfen, zum Beispiel:

#(checking if hand is a Trip) 
def isThreeOfKind(self, hand): 
     self.gatherRanks(hand) 
     return len(self.value1)==3 or len(self.value2)==3 or len(self.value3)==3 

und so weiter, jede Kontrolle eine Frage der von 1 bis 3 Zeilen Code (außer Gerade die Schleife erfordert).

+2

Wenn Ihre aktuelle Version funktioniert und Sie wollen einfach, es zu verbessern, 'CodeReview' ist der richtige Ort für Sie. http://codereview.stackexchange.com/ –

+0

Wenn der Rang von card5 nicht dem Rang einer anderen Karte entspricht, wird er nicht an eine Ihrer 4 Listen angehängt, ist das beabsichtigt? –

+0

Im Anschluss an Rawings Kommentar vermute ich, dass Sie Karten nach ihrer Farbe und nicht nach ihrem Rang gruppieren sollten. Und ja, es gibt effizientere Möglichkeiten, so etwas zu tun. –

Antwort

0

Wirkliche Verbesserung ist nur hier möglich, wenn Sie Ihre self.value1, self.value2, etc. Listen loswerden. Wann immer Sie sehen, dass Sie solche Variablen erstellen, sollten Sie stattdessen eine Liste verwenden.

Der folgende Code tut, was Sie wollen (ich weggelassen, um die self, weil es auf den Code nicht relevant ist):

def gather(hand): 
    values= [] 

    for card in hand.cards: 
     #for each card, check if a list containing cards of the same rank already exists 
     for card_list in values: 
      if card_list[0].rank==card.rank: 
       #found one, add the card to this list 
       card_list.append(card) 
       break 
     else:#if no list with the same rank exists, create one 
      values.append([card]) 

    #and if you insist on having your 4 lists: 
    values1= values[0] if len(values)>0 else [] 
    values2= values[1] if len(values)>1 else [] 
    values3= values[2] if len(values)>2 else [] 
    values4= values[3] if len(values)>3 else [] 
+0

Ich kann die innere Schleife nicht wirklich verstehen, also ist es schwer zu kommentieren. Ihr Code funktioniert im Allgemeinen, aber leider sammelt nichts, die letzte Variable ist immer leer. – smoczyna

+0

@smoczyna Dieser Code funktioniert definitiv, ich habe eine 'Card'- und' Hand'-Klasse erstellt, nur um sie zu testen. Vielleicht sehen Sie sich die Variable 'self.values' anstelle von' values' an? In der Zeile 'if card_list [0] .rank == card.rank' ist' card_list' eine Liste von Karten mit demselben Rang. Wenn also 'card.rank' gleich ist, wird es auch hinzugefügt Liste. –

+0

Die einzige Möglichkeit, dass "Werte" leer sein können, ist, ob 'hand.cards' ebenfalls leer ist oder keine Iteration mit einer 'for ... in'-Schleife erlaubt. –

0
  • PEP8
    • gather_ranks anstelle von gatherRanks
    • Einrücken unter Verwendung von 4 Räumen anstelle von 8
  • Verwenden Listen/dicts und Schleifen, um es kompakter und damit besser lesbar (und weniger anfällig für einen Fehler)
  • Fügen Sie einen Docstring hinzu (ich mag Numpydoc)

So, hier ist der eingestellte Code:

def gather_ranks(self, hand): 
    self.value = [] 
    for i in range(4): 
     self.value.append([]) 

    # The first card always goes to the first hand 
    self.value[0].append(hand.cards[0]) 

    # Go through the next cards. Foreach card, check 
    # if the first hands card(s) has/have the same value. 
    # If so, add it there. Otherwiese go to the next hand. 
    # If none had the same, add it to the next players hand. 
    for card_index in [1, 2, 3, 4]: 
     for i in range(card_index): 
      if hand.cards[card_index].rank == hand.cards[i].rank: 
       self.value[i].append(hand.cards[card_index]) 
       break 
     else: 
      # loop fell through without break 
      # Card was not added to any player 
      if card_index < 5: 
       self.value[card_index].append(hand.cards[card_index]) 

Natürlich, ich kann nicht wirklich gut Bemerkungen machen, wie ich weiß nicht, was der Sinn dahinter ist. Du solltest das durch etwas ersetzen, das in diesem Spiel Sinn macht.

+0

Für was es wert ist, OP-Code war lesbarer als das. –

+0

@Rawing Ich habe ein paar Änderungen vorgenommen. Denkst du immer noch so? –

+0

Ja, definitiv. In der Tat ist Ihr Code so schwer zu lesen, dass Sie nicht bemerkt haben, dass er einen IndexError auslöst. –

0

Es ist wie die Anzahl der Reihen aussieht, ist vorbestimmt, die aus der Verwendung von Variablen zu urteilen self.value1 bis self.value4.

Wenn das tatsächlich der Fall ist, könnte Wörterbuch nützlich sein.

def gather_ranks(self, hand): 
    # initialize the dictionary with card ranks 
    # r1...r4 represents card ranks 
    self.ranked_cards = {"r1": [], "r2": [], "r3": [], "r4": []} 

    for card in hand.cards: 
     self.ranked_cards[card.rank].append(card) 
+0

Es ist eigentlich nicht, da es Poker-Spiel gibt es 5 Karten und jeder von ihnen hat seinen Rang (Wert) und Anzug (Farbe). Das Ziel ist es, Karten nach ihren Reihen zu gruppieren, um weitere Schätzungen leicht zu machen (chec kmy updated post oben). Um sich zu versammeln, müssen sie miteinander verglichen werden. – smoczyna

0

(Edited Beispiel)

ich defaultdict verwenden würde:

from collections import defaultdict 
from pprint import pprint 
import itertools 
import random 


class Card(object): 
    def __init__(self, rank_color): 
     self.rank, self.color = rank_color 
    def __repr__(self): 
     return '{} of {}'.format(self.rank, self.color) 

class Hand(object): 
    def __init__(self): 
     self.cards = [] 
     self.gathered_ranks = defaultdict(list) 
    def add_card(self, card): 
     self.cards.append(card) 
     self.gathered_ranks[card.rank].append(card) 
    def get_gathered_ranks(self): 
     return dict(self.gathered_ranks) 

if __name__ == '__main__': 
    hand = Hand() 

    colors = ['spade', 'club', 'heart', 'diamond'] 
    ranks = range(1, 15) 
    deck = [e for e in itertools.product(ranks, colors)] 
    random.shuffle(deck) 
    # We suppose players have 5 random cards 
    for i in range(5): 
     card = deck.pop() 
     hand.add_card(Card(card)) 
    pprint(hand.get_gathered_ranks()) 
+0

Ich denke, du hast den Punkt verpasst, die ganze Idee hier ist es, die Karte nach ihren Werten (Rängen) zu gruppieren und alle Karten sind bereits gemischt. Ich meine, alle Spielerhände wurden bereits serviert und jeder hat 5 Karten. – smoczyna

+0

@smoczyna Die Schlüssel des Diktats, die von 'gatherRanks' zurückgegeben werden, sind die Ränge, die Werte sind die Liste der Karten mit dem entsprechenden Rang. Die Zeilen im 'if __name__ == '__main __':' dienen nur dazu, die Funktion zu testen. – Frodon

+0

@smoczyna Ich habe das Beispiel geändert: Karten werden jedes Mal nach Rang gesammelt, wenn sie hinzugefügt werden – Frodon

Verwandte Themen