Interagierende Funktionen? - Kartenspiel "love letter"

Du hast eine Idee für ein Projekt?
Antworten
steveO_O
User
Beiträge: 22
Registriert: Montag 23. März 2020, 20:08

Hallo zusammen,

ich bin als Übungsprojekt gerade dabei das Spiel "love letter" zu programmieren, um gegen einen Bot spielen zu können.

Wie wärt ihr eigentlich an eine solche Aufgabe herangegangen? Also wo fängt man an? Ich habe einfach mal drauf los getippt, was aber wohl nicht die intelligenteste Vorgehensweise ist. Vermutlich wäre es besser gewesen, sich zu überlegen was der schwierigste Teil des Codes sein wird, mit dem zu beginnen und alles andere drum herum zu coden. Gibts da eine allgemeine Anleitung?

Bin jetzt an der Stelle an der ich die Funktionen der einzelnen Karten coden möchte. In der Funktion "karte_ziehen_und_ausspielen" müsste dann die jeweile Funktion aufgerufen werden. Die Karten-Funktionen sind aber vom Zähler in der "karte_ziehen_und_ausspielen"-Funktion abhängig. Sollte das "i" dann eine globale Variable werden? Irgendwie habe ich das Gefühl, dass es da sicherlich eine bessere Möglichkeit gibt, die ich allerdings noch nicht kenne. :-)

Bin für hilfreiche Stichworte dankbar.
Viele Grüße
Stefan

Code: Alles auswählen

# Regeln: https://pegasusshop.de/media/pdf/e9/55/30/4250231705021_de.pdf

from random import shuffle
import random

karten = ( # Nr., Name, Anzahl, Beschreibung
[1,"Die Wächterin", 5, "Die Personenkarte eines Mitspielers darf erraten werden (außer Wächterin selber). Liegt man richtig, scheidet dieser Spieler aus."],
[2,"Der Priester", 2, "Erlaubt dem Spieler, die Handkarte eines Mitspielers anzuschauen."],
[3, "Der Baron", 2, "Erlaubt das Anschauen der Handkarte eines Mitspielers. Der Spieler, dessen Karte den niedrigeren Wert hat, scheidet aus dem Spiel aus."],
[4, "Die Zofe", 2, "Die Zofe schützt den Spieler eine Runde vor den Kartenfunktionen der Mitspieler."],
[5, "Der Prinz", 2, "Ein Mitspieler darf bestimmt werden. Dieser muss seine Handkarte ablegen und eine neue Personenkarte ziehen."],
[6, "Der König", 1, "Erlaubt den Tausch der verbliebenen Personenkarte mit der eines Mitspielers."],
[7,"Die Gräfin", 1, "Muss sofort abgelegt werden, wenn ein Spieler zusätzlich den König oder Prinzen auf der Hand hat."],
[8, "Die Prinzessin", 1, "Wer diese Karte ablegt, scheidet sofort aus der laufenden Runde aus."]
)

spieler = ["Du", "Kelly", "Angela", "Pam"]
ausgeschiedene_spieler = []
nachziehstapel = []
ablagestapel = []
handkarten = []

# Spielaufbau
def karten_mischen():
    #Nimm das volle Deck und mische es
    #Output: nachziehstapel -> Liste mit "Prinzessin", "König", etc.
    for karte in karten:
        i = karte[2]
        for j in range(i):
            nachziehstapel.append(karte[1])
    shuffle(nachziehstapel)

def reihenfolge():
    shuffle(spieler)

def karten_verteilen():
    # Ziehe für jeden Spieler eine zufällige Karte von "nachziehstapel"
    # output: handkarten = Liste mit "Spieler 1", Name1, aktuelle Karte
    # Eine Reservekarte für evtl. Prinzen im letzten Zug beiseite legen
    i = 0
    for gamer in spieler:
        a = random.choice(nachziehstapel)
        handkarten.append(["Spieler {} ".format(i+1), spieler[i], [a]])
        nachziehstapel.remove(a)
        i +=1
    # Reservekarte:
    b = random.choice(nachziehstapel)
    nachziehstapel.append(nachziehstapel.pop(nachziehstapel.index(b)))
    reserve = nachziehstapel.pop()
    print("Dies ist die Spielerreihenfolge:")
    for i, num in enumerate(handkarten):
        num = handkarten[i][1]
        print("Der {}. Spieler ist {}".format(i+1, num))


# Spielablauf
def karte_ziehen_und_ausspielen():
    # Spieler X nimmt eine Karte vom Nachziehstapel auf die Hand und legt eine der beiden Karten wieder ab
    i = 0
    while handkarten:
        try:
            for gamer in handkarten:
                if handkarten[i][1] != "Du":
                    #Karte nehmen
                    a = random.choice(nachziehstapel)
                    handkarten[i][2].append(a)
                    nachziehstapel.remove(a)
                    #Karte ablegen
                    b = random.choice(handkarten[i][2])
                    handkarten[i][2].remove(b)
                    ablagestapel.append(b)
                elif handkarten[i][1] == "Du":
                    print("Du bist dran")
                i += 1
            if i == 4:
                i = 0
        except IndexError:
            print("Stapel ist leer")
            break

def waechterin_bot():
    a = random.choice(spieler)
    if handkarten[i][1] != "Du":
        print("asf")
    else:
        print("asf")

# Aufruf der Funktionen

reihenfolge()
karten_mischen()
karten_verteilen()
karte_ziehen_und_ausspielen()
nezzcarth
User
Beiträge: 1632
Registriert: Samstag 16. April 2011, 12:47

steveO_O hat geschrieben: Sonntag 26. April 2020, 10:56 Wie wärt ihr eigentlich an eine solche Aufgabe herangegangen? Also wo fängt man an? Ich habe einfach mal drauf los getippt, was aber wohl nicht die intelligenteste Vorgehensweise ist. Vermutlich wäre es besser gewesen, sich zu überlegen was der schwierigste Teil des Codes sein wird, mit dem zu beginnen und alles andere drum herum zu coden. Gibts da eine allgemeine Anleitung?
Es gibt in der Softwareentwicklung verschiedene Analyse- und Modelierungsmethoden, um an so etwas heranzugehen. Dazu kann vielleicht einer der Informatiker im Forum etwas sagen. Persönlich würde ich zunächst so an die Frage herangehen, dass ich mir überlege, welche Entitäten es im Spiel gibt, welche Eigenschaften sie haben, wie diese miteinander interagieren und wie man sie modelliert. Zum Beispiel gibt es 'Spieler', 'Karten', einen 'Nachziehstapel' und einen 'Ablegestapel', sowie möglicherweise etwas abstraktere Dinge wie 'Runden', 'Spiele' oder 'Aktionen'. Spieler können Herzen und Karten haben, sie können aktiv oder ausgeschieden sein, sie können Karten ziehen, Aktionen ausführen, usw. Karten können einen Namen, einen Wert, eine Aktion haben und ggf. eine Häufigkeit haben etc. Nun kann man sich überlegen, wie man das in Code abbildet (zum Beispiel mit Klassen, oder auch mit regulären Datentypen und Funktionen). Soweit ich das sehe, dürfte das Implementieren einer KI, gegen die es Spaß nach zu spielen, viel Ausprobieren erfordern. Daher ist eine gute Abstraktion, mit der man die konkrete Implementation des Bots leicht austauschen, aber auch auf alle notwendigen Mechaniken und Informationen im Spiel Zugriff hat, sicher vorteilhaft.
Benutzeravatar
__blackjack__
User
Beiträge: 13004
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@steveO_O: Auf Modulebene sollte nur Code stehen der Konstanten, Funktionen, und Klassen definiert. Also ganz bestimmt nicht `i` global machen, sondern das was da jetzt global steht sollte da verschwinden und man arbeitet mit richtigen Funktionen, und nicht Codeabschnitten denen man mit ``def`` einen Namen gegeben hat, die aber letztlich alle über globale Variablen undurchsichtig zusammenhängen. Funktionen sind in der Regel in sich geschlossene kleine Teilprogramme die Daten über Argumente rein bekommen und Ergebnisse als Rückgabwerte an den Aufrufer liefern. Wenn eine Funktion dagegen irgendetwas übergebenes verändert, sollte das aus dem Namen oder der Dokumentation klar werden, und nicht überraschend für den Leser sein.

Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst.

Konstanten werden KOMPLETT_GROSS geschrieben.

`karten_mischen()` sollte beispielsweise eine neue Liste mit den gemischten Karten als Rückgabewert liefern.

Bei den Kartenkonstanten ist es nicht wirklich förderlich für die Lesbarkeit, das auf die Bestandteile per Index zugegriffen wird. `karte[1]` oder `karte[2]` sagt dem Leser nicht wirklich etwas über die Bedeutung der Werte. Dafür muss man immer erst bei dem Kommentar bei der Definition der Liste mit den Karten nachsehen. Und man kann sich bei solchen nichtssagenden Zahlen auch leicht verschreiben. Die Kartendefinition würde man deshalb besser mit einem eigenen Datentyp für die Karten machen, zum Beispiel mittels `collections.namedtuple()`, damit man den Bestandteilen verständliche Namen geben kann.

Bei `handkarten` wird das noch schlimmer weil man da aus dem Code rauslesen muss was `handkarten[x][y]` bedeuten könnte. `handkarten[x][0]` ist redundant, weil man den Wert aus der Position des Elements berechnen kann. `handkarten[x][1]` im Grunde auch, denn der Wert steht ja in `spieler`.

`karten_verteilen()` braucht den Kartenstapel aus dem verteilt wird als Argument und hat die Handkarten und die Reservekarte als Rückgabewert.

Die Funktion ist zu kompliziert geschrieben. Die Karten sind ja bereits gemischt, also braucht man da kein `random.choice()` mehr. Das macht nichts zufälliger, allerdings das `remove()` und `index()`/`pop()` womit dann die Karten aus dem Stapel entfernt werden sind fehlerhaft, weil die ja immer den ersten Fund entfernen, auch wenn man mit `random.choice()` die gleiche Karte aber weiter hinten im Stapel ausgewählt hat.

Das ermitteln der Reservekarte ist auch unnötig kompliziert.

`gamer` wird in `karten_verteilen()` nirgends benutzt. Man sieht hier warum Deutsch für Variablennamen nicht gut ist: es kommt recht häufig vor, dass Einzahl und Mehrzahl gleichgeschrieben werden, man also Probleme bekommt `spieler` (mehrere) und `spieler` (einer) sinnvoll zu benennen. Im Englischen ist es fast immer einfach beides auseinander zu halten (`player`/`players`).

Ausgaben für den Benutzer gehören nicht in das Kartenverteilen. Bei der Ausgabeschleife wird `num` an eine Liste mit drei Werten gebunden aber nicht benutzt und in der Schleife wird gleich als erstes `num` an den Namen des Spielers gebunden. Das ist sehr verwirrend. Zudem enthält die Ausgabe nichts was das Kartenverteilen benötigen würde, denn die Spielerreihenfolge wurde ja schon davor festgelegt.

Wenn man einen Namen beispielsweise aus syntaktischen Gründen braucht, den Wert dann aber gar nicht benutzt, ist `_` ein konventioneller Name dafür, damit der Leser weiss, dass das Absicht ist, das der Namen nicht verwendet wird.

Auch bei `karte_ziehen_und_ausspielen()` wird `gamer` als Schleifevariable definiert aber gar nicht verwendet‽ `i` wird stattdessen als Index verwendet und undurchsichtig manuell verwaltet. Zudem hart kodiert mit einer 4, die man wenn schon, dann aus den der Länge der Spieler oder `handkarten` ermitteln sollte.

Die äussere Schleife ``while handkarten:`` ist eine ``while True:``-Schleife, denn `handkarten` wird in der Schleife niemals so verändert, das diese Schleife dadurch abbrechen würde.

``if``/``elif`` mit genau entgegengesetzten Tests ist eigentlich ``if``/``else``.

Ja, der `IndexError` kommt wenn der Kartenstapel leer ist, aber da wird so viel mit Indexzugriffen gemacht im ``try``-Block, dass das auch von woanders kommen könnte, insbesondere wenn man einen Fehler gemacht hat.

Die Kommmentare an den Funktionsanfängen wären besser Docstrings.

Ungetestet und ich habe auch die Regeln nicht angeschaut, weiss also nicht ob das so alles wirklich Sinn macht:

Code: Alles auswählen

#!/usr/bin/env python3
# Regeln: https://pegasusshop.de/media/pdf/e9/55/30/4250231705021_de.pdf
import random
from collections import namedtuple
from itertools import cycle
from random import shuffle

Karte = namedtuple("Karte", "nummer name anzahl beschreibung")
Hand = namedtuple("Hand", "spielername karten")

KARTEN = (
    Karte(
        1,
        "Die Wächterin",
        5,
        "Die Personenkarte eines Mitspielers darf erraten werden (außer"
        " Wächterin selber). Liegt man richtig, scheidet dieser Spieler aus.",
    ),
    Karte(
        2,
        "Der Priester",
        2,
        "Erlaubt dem Spieler, die Handkarte eines Mitspielers anzuschauen.",
    ),
    Karte(
        3,
        "Der Baron",
        2,
        "Erlaubt das Anschauen der Handkarte eines Mitspielers. Der Spieler,"
        " dessen Karte den niedrigeren Wert hat, scheidet aus dem Spiel aus.",
    ),
    Karte(
        4,
        "Die Zofe",
        2,
        "Die Zofe schützt den Spieler eine Runde vor den Kartenfunktionen der"
        " Mitspieler.",
    ),
    Karte(
        5,
        "Der Prinz",
        2,
        "Ein Mitspieler darf bestimmt werden. Dieser muss seine Handkarte"
        " ablegen und eine neue Personenkarte ziehen.",
    ),
    Karte(
        6,
        "Der König",
        1,
        "Erlaubt den Tausch der verbliebenen Personenkarte mit der eines"
        " Mitspielers.",
    ),
    Karte(
        7,
        "Die Gräfin",
        1,
        "Muss sofort abgelegt werden, wenn ein Spieler zusätzlich den König"
        " oder Prinzen auf der Hand hat.",
    ),
    Karte(
        8,
        "Die Prinzessin",
        1,
        "Wer diese Karte ablegt, scheidet sofort aus der laufenden Runde aus.",
    ),
)


def mische_spieler_reihenfolge(spielernamen):
    """
    Mischt die übergebenen Spielernamen „in place“.
    """
    shuffle(spielernamen)


def karten_mischen():
    """
    Gibt ein ein gemischtes Kartendeck zurück.
    """
    karten = list()
    for karte in KARTEN:
        for _ in range(karte.anzahl):
            karten.append(karte.name)
    shuffle(karten)
    return karten


def karten_verteilen(kartenstapel, spielernamen):
    """
    Gibt ein Tupel aus
    
    * `Hand`-Objekten pro Spielername,
    * und einer Reservekarte zurück.
    """
    return (
        [Hand(name, kartenstapel.pop()) for name in spielernamen],
        kartenstapel.pop(),
    )


def karten_ziehen_und_ausspielen(handkarten, nachziehstapel):
    """
    Lässt die Spieler reihum eine Karte vom Nachziehstapel nehmen und eine Karte
    auf dem Ablagestapel ablegen.
    
    Wenn alle Karten vom Nachziehstapel aufgebraucht sind, endet die Funktion
    und gibt den Ablagestapel zurück.
    """
    ablagestapel = list()
    for hand in cycle(handkarten):
        if hand.spielername == "Du":
            print("Du bist dran")
        else:
            try:
                hand.karten.append(nachziehstapel.pop())
            except IndexError:
                print("Stapel ist leer")
                break
            else:
                index = random.randrange(len(hand.karten))
                ablagestapel.append(hand.karten.pop(index))
    return ablagestapel


def main():
    spielernamen = ["Du", "Kelly", "Angela", "Pam"]
    mische_spieler_reihenfolge(spielernamen)
    print("Dies ist die Spielerreihenfolge:")
    for i, spielername in enumerate(spielernamen, 1):
        print(f"Der {i}. Spieler ist {spielername}.")

    nachziehstapel = karten_mischen()
    handkarten, reservekarte = karten_verteilen(nachziehstapel, spielernamen)
    ablagestapel = karten_ziehen_und_ausspielen(handkarten, nachziehstapel)


if __name__ == "__main__":
    main()
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
steveO_O
User
Beiträge: 22
Registriert: Montag 23. März 2020, 20:08

Vielen vielen Dank für die Mühe die ich gemacht habe :-). Da muss ich mich jetzt sobald ich mehr Zeit habe erstmal durchkämpfen. Aber wirklich toller input! Danke!
Benutzeravatar
__blackjack__
User
Beiträge: 13004
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Auch einfach mal drauf los programmiert bis zu einem Punkt wo dumme ”KI”-Spieler das ohne GUI/TUI gegeneinander spielen:

Code: Alles auswählen

#!/usr/bin/env python3
# Regeln: https://pegasusshop.de/media/pdf/e9/55/30/4250231705021_de.pdf
import random
from collections import namedtuple
from itertools import groupby
from operator import attrgetter

from attr import attrib, attrs

# PLAYER_COUNT_TO_TOKEN_COUNT = {2: 7, 3: 5, 4: 4}  # Original rules.
PLAYER_COUNT_TO_TOKEN_COUNT = {2: 5, 3: 4, 4: 3}

Card = namedtuple("Card", "value name count description affects_other_player")

GUARD = Card(
    1,
    "Die Wächterin",
    5,
    "Die Personenkarte eines Mitspielers darf erraten werden (außer"
    " Wächterin selber). Liegt man richtig, scheidet dieser Spieler aus.",
    True,
)
PRIEST = Card(
    2,
    "Der Priester",
    2,
    "Erlaubt dem Spieler, die Handkarte eines Mitspielers anzuschauen.",
    True,
)
BARON = Card(
    3,
    "Der Baron",
    2,
    "Erlaubt das Anschauen der Handkarte eines Mitspielers. Der Spieler,"
    " dessen Karte den niedrigeren Wert hat, scheidet aus dem Spiel aus.",
    True,
)
HANDMAID = Card(
    4,
    "Die Zofe",
    2,
    "Die Zofe schützt den Spieler eine Runde vor den Kartenfunktionen der"
    " Mitspieler.",
    False,
)
PRINCE = Card(
    5,
    "Der Prinz",
    2,
    "Ein Mitspieler darf bestimmt werden. Dieser muss seine Handkarte"
    " ablegen und eine neue Personenkarte ziehen.",
    True,
)
KING = Card(
    6,
    "Der König",
    1,
    "Erlaubt den Tausch der verbliebenen Personenkarte mit der eines"
    " Mitspielers.",
    True,
)
COUNTESS = Card(
    7,
    "Die Gräfin",
    1,
    "Muss sofort abgelegt werden, wenn ein Spieler zusätzlich den König"
    " oder Prinzen auf der Hand hat.",
    False,
)
PRINCESS = Card(
    8,
    "Die Prinzessin",
    1,
    "Wer diese Karte ablegt, scheidet sofort aus der laufenden Runde aus.",
    False,
)

CARDS = [PRINCESS, COUNTESS, KING, PRINCE, HANDMAID, BARON, PRIEST, GUARD]
assert sum(card.count for card in CARDS) == 16


@attrs
class PlayerBase:
    name = attrib()
    tokens = attrib(default=0)
    card = attrib(default=None)
    discarded_cards = attrib(factory=list)

    @property
    def is_active(self):
        return self.card is not None

    @property
    def discarded_card(self):
        return self.discarded_cards[-1] if self.discarded_cards else None

    @property
    def is_protected(self):
        return self.discarded_card == HANDMAID

    def discard_hand(self):
        self.discarded_cards.append(self.card)
        self.card = None

    def start_new_round(self, card):
        self.card = card
        self.discarded_cards = list()

    def start_turn(self, round_, new_card):
        raise NotImplementedError

    def choose_other_player(self, round_, others):
        raise NotImplementedError

    def look_at_card(self, other):
        raise NotImplementedError

    def guess_card(self, round_, other):
        raise NotImplementedError


@attrs
class DumbPlayer(PlayerBase):
    def start_turn(self, _round, new_card):
        #
        # According to the rules the countess must be discarded if the other
        # card is `PRINCE` or `KING`.
        #
        cards = sorted([self.card, new_card], reverse=True)
        if cards in [[COUNTESS, PRINCE], [COUNTESS, KING]]:
            cards.reverse()
        self.card, discarded_card = cards
        self.discarded_cards.append(discarded_card)

    @staticmethod
    def choose_other_player(_round, others):
        return random.choice(others) if others else None

    @staticmethod
    def look_at_card(_other):
        pass

    @staticmethod
    def guess_card(_round, _other):
        cards = [card for card in CARDS if card != GUARD]
        return random.choice(cards)


def create_shuffled_deck():
    deck = list()
    for card in CARDS:
        deck.extend(card for _ in range(card.count))
    random.shuffle(deck)
    return deck


@attrs
class Round:
    players = attrib()
    deck = attrib(factory=create_shuffled_deck)
    removed_card = attrib(default=None)
    open_removed_cards = attrib(factory=list)
    _card_to_effect = attrib(default=None)

    def __attrs_post_init__(self):
        self.removed_card = self.deck.pop()
        if len(self.players) == 2:
            self.open_removed_cards.extend(self.deck.pop() for _ in range(3))

        for player in self.players:
            player.start_new_round(self.deck.pop())

        no_effect = lambda player, other_player: None
        self._card_to_effect = {
            PRINCESS: lambda player, other_player: player.discard_hand(),
            COUNTESS: no_effect,
            KING: self.on_king,
            PRINCE: self.on_prince,
            HANDMAID: no_effect,
            BARON: self.on_baron,
            PRIEST: self.on_priest,
            GUARD: self.on_guard,
        }

    @property
    def active_player_count(self):
        return sum(1 for _ in self.iter_active_players())

    def iter_active_players(self):
        return (player for player in self.players if player.is_active)

    def has_ended(self):
        return not self.deck or self.active_player_count == 1

    def get_unprotected_active_players(self):
        return [
            player
            for player in self.iter_active_players()
            if not player.is_protected
        ]

    @staticmethod
    def on_king(player, other_player):
        if other_player:
            player.card, other_player.card = (other_player.card, player.card)

    def on_prince(self, player, other_player):
        if not other_player:
            other_player = player
        other_player.discard_hand()
        if self.deck:
            other_player.card = self.deck.pop()
        else:
            other_player.card = self.removed_card
            self.removed_card = None

    @staticmethod
    def on_baron(player, other_player):
        if other_player:
            player_a, player_b = sorted(
                [player, other_player], key=attrgetter("card")
            )
            if player_a.card.value != player_b.card.value:
                player_a.discard_hand()

    @staticmethod
    def on_priest(player, other_player):
        if other_player:
            player.look_at_card(other_player)

    def on_guard(self, player, other_player):
        if other_player:
            guessed_card = player.guess_card(self, other_player)
            if other_player.card == guessed_card:
                other_player.discard_hand()

    def play_turn(self, player):
        player.start_turn(self, self.deck.pop())
        card = player.discarded_card
        other_player = (
            player.choose_other_player(
                self, self.get_unprotected_active_players()
            )
            if card.affects_other_player
            else None
        )
        self._card_to_effect[player.discarded_card](player, other_player)

    def get_and_award_winners(self):
        if not self.has_ended():
            raise RuntimeError("round hasn't ended yet")
        #
        # Original rules break ties by highest total of discarded cards.
        #
        get_card = attrgetter("card")
        _, winners = next(
            groupby(sorted(self.iter_active_players(), key=get_card), get_card)
        )
        winners = list(winners)
        for winner in winners:
            winner.tokens += 1
        return winners

    def play(self):
        while not self.has_ended():
            for player in self.iter_active_players():
                self.play_turn(player)
                if not self.deck:
                    break

        return self.get_and_award_winners()


def main():
    player_names = ["Du", "Kelly", "Angela", "Pam"]
    players = [DumbPlayer(name) for name in player_names]
    random.shuffle(players)

    needed_token_count = PLAYER_COUNT_TO_TOKEN_COUNT[len(players)]
    round_winners = players
    while all(player.tokens < needed_token_count for player in players):
        #
        # Rules say youngest player here.  Original rules just have one winner
        # per round, so youngest only applies to very first round.
        #
        starting_player = random.choice(round_winners)
        index = players.index(starting_player)
        players = players[index:] + players[:index]

        round_winners = Round(players).play()

    for i, player in enumerate(
        sorted(players, key=attrgetter("tokens"), reverse=True), 1
    ):
        print(f"{i}. {player.name} ({player.tokens})")


if __name__ == "__main__":
    main()
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
steveO_O
User
Beiträge: 22
Registriert: Montag 23. März 2020, 20:08

__blackjack__ hat geschrieben: Dienstag 28. April 2020, 10:49 Auch einfach mal drauf los programmiert bis zu einem Punkt wo dumme ”KI”-Spieler das ohne GUI/TUI gegeneinander spielen:
...
Hi blackjack,

nimms mir bitte nicht übel, aber den post werde ich ignorieren. 1. will ich mir die Lösung ja selber erarbeiten bzw. mich der "optimalen" Lösung zumindest annähern. 2. ist steckt da derzeit noch zuviel neues für mich drin, sodass ich den Überblick verliere.

Trotzdem danke! Wie weiter oben beschrieben arbeite ich gerade noch an deinem vorletzten Post :-)
Antworten