Sequenzen und Sätze aus Kartenspiel herauslesen

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
kjd
User
Beiträge: 12
Registriert: Freitag 12. Juli 2019, 09:48

Hallo!

Für unsere Informatik Hausaufgabe müssen wir ein Kartenspiel erstellen. Jeder Spieler erhält in diesem Karten auf die Hand und muss anschließend aus diesen Karten auswählen bei welchen überprüft werden soll, ob es sich um eine Sequenz (z.B. "Herz, 7", "Herz, 8", "Herz, 9") oder um einen Satz (z.B. "Karo, 7", "Pik, 7", "Herz, 7") handelt.

Ich habe bis jetzt verschiedene Sachen probiert, aber es muss definitiv eine leichtere und vor allem bessere Methode geben..
Zum einen habe ich die ausgewählten Karten in eine eigene Liste getan und wollte diese dann mit meinen anderen Listen vergleichen. Die anderen Listen enthalten alle möglichen Kombinationen für Sequenzen. Das war eine nicht sehr gute Idee und nicht nur war es sehr umständlich sondern es hat noch nicht mal funktioniert :?

Hat jemand eine bessere Idee? Ich brauche keine Lösung, aber einen Ansatz, mit welchem Befehl o.ä. ich meine ausgewählten Karten auf Sätze und Sequenzen überprüfen kann.

Vielen Dank im Voraus
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

Prüf doch einfach, ob es sich um eine Sequenz handelt oder einen Satz.
Wenn Du wo nicht weiter kommst, zeig den Code, der den Fehler produziert, beschriebe, was genau nicht funktioniert und was Du statt dessen hättest.
Jankie
User
Beiträge: 592
Registriert: Mittwoch 26. September 2018, 14:06

Ich würde das so angehen:

eine Liste mit Tuples erstellen, wo alle Karten drin sind also [("Karo", "Ass"), ("Karo", "7"), ("Karo", "8"), ...]
dann würde ich eine Funktion schreiben, die einem dort x zufällige Tuples rausgibt, aber drauf achtet, dass kein Tuple doppelt genommen wird und das Tuple dann in eine Liste packt. Diese Tuples in der Liste sind dann quasi alle Karten die du auf der Hand hast.
Dann würde ich eine Funktion schreiben, die prüft ob es eine Sequenz ist. Dafür dann immer den ersten Wert jedes Tuples der Liste (Karten auf deiner Hand) mit dem anderen vergleichen, wenn alle gleich sind, ist es eine Sequenz. Das gleiche dann mit dem zweiten Wert des Tuples, dann ist es ein Satz.
__deets__
User
Beiträge: 14494
Registriert: Mittwoch 14. Oktober 2015, 14:29

Die Zahlen als Strings zu behandeln halte ich fuer einen Fehler, da man sich dadurch ihrer numerischen Eigenschaften beraubt. Besser ist es, sie ihrer Reihenfolge nach zu behandeln. Also zB 7, 8, 9, 10 (normale Zahlen) und dann 11, 12, 13, 14 fuer Bube, Dame, Koenig, Ass.

Denn dann kann man den Test auf Sequenz einfacher gestalten. Zuerst muessen alle Farben gleich sein. Der Test ist einfach und zB mit der all()-Funktion in Python zu machen.

Danach muessen alle zahlen sortiert immer eine Differenz von 1 zur naechsten Zahl haben. Das ist das Kriterium fuer Sequenz.

Ein Satz ist trivial - alle Zahlen gleich (wieder all()), und alle Farben unterschiedlich. Dazu gibt es die Datenstruktur "set".
Benutzeravatar
__blackjack__
User
Beiträge: 13004
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@kjd: Das hängt auch alles ein bisschen davon ab wie Du eine einzelne Karte repräsentierst. Da man so etwas wie einen numerischen Wert für den Kartenwert haben muss, was bei den Zahlwerten ja noch trival ist, aber bei den Bildkarten eben nicht mehr, würde sich mindestens für den Kartenwert ein `enum.Enum` anbieten. Und letztlich für die Farbe ebenfalls. Und solche Werte könnte man dann mit einem `collections.namedtuple`-Typ zu einer Karte zusammenfassen.

Ist beim Test auf Sequenz die Reihenfolge der Karten wichtig, oder nur das man eine Sequenz hat. Also wird Herz 9, Herz 7, Herz 8 als Sequenz angesehen, weil es die entsprechenden Karten enthält, oder soll hier die Testfunktion `False` liefern?
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Benutzeravatar
__blackjack__
User
Beiträge: 13004
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Code: Alles auswählen

#!/usr/bin/env python3
from enum import auto, Enum, unique
from functools import total_ordering
import random

from attr import attrib, attrs
from more_itertools import all_equal, consecutive_groups, ilen


@total_ordering
class OrderedEnum(Enum):
    
    def __lt__(self, other):
        if self.__class__ is other.__class__:
            return self.value < other.value
        return NotImplemented


@unique
class Value(OrderedEnum):
    ACE = 1
    TWO = 2
    THREE = 3
    FOUR = 4
    FIVE = 5
    SIX = 6
    SEVEN = 7
    EIGHT = 8
    NINE = 9
    TEN = 10
    JACK = 11
    QUEEN = 12
    KING = 13

    def __str__(self):
        return str(self.value) if 2 <= self.value <= 10 else self.name.lower()


class Suite(OrderedEnum):
    HEARTS = auto()
    DIAMONDS = auto()
    CLUBS = auto()
    SPADES = auto()
    
    def __str__(self):
        return self.name.lower()


@attrs(frozen=True)
class Card:
    value = attrib()
    suite = attrib()

    def __str__(self):
        return f'{self.value} of {self.suite}'

    def __int__(self):
        return self.value.value


@attrs
class Deck:
    cards = attrib(factory=list)
    
    def __len__(self):
        return len(self.cards)
    
    def shuffle(self):
        random.shuffle(self.cards)
    
    def take(self, number):
        if number > len(self):
            raise ValueError('not enough cards left')
        cards = self.cards[-number:]
        del self.cards[-number:]
        return cards
    
    @classmethod
    def create_standard(cls):
        return cls([Card(value, suite) for suite in Suite for value in Value])


def is_straight(cards):
    cards = sorted(cards)
    return (
        len(cards) >= 3
        and all_equal(card.suite for card in cards)
        and ilen(next(consecutive_groups(cards, int))) == len(cards)
    )


def is_set(cards):
    return (
        len(cards) >= 3
        and all_equal(card.value for card in cards)
        and len(set(card.suite for card in cards)) == len(cards)
    )


def main():
    deck = Deck.create_standard()
    deck.shuffle()
    while len(deck) >= 3:
        cards = deck.take(3)
        print(is_straight(cards) or is_set(cards), ', '.join(map(str, cards)))
                    
                    
if __name__ == '__main__':
    main()
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Antworten