TicTacToe

Stellt hier eure Projekte vor.
Internetseiten, Skripte, und alles andere bzgl. Python.
Antworten
jngr
User
Beiträge: 2
Registriert: Mittwoch 15. Juni 2011, 13:27
Kontaktdaten:

Ich programmier erst seit ein paar Wochen mit Python und hatte mir jetzt ein TicTacToe programmiert(2-Spieler).
Nur beim überprüfen, ob jemand gewonnen hat bzw. ob unentschieden ist, sieht mein Code ein bisschen komisch aus.
Gibt es eine kürzere oder übersichtlichere Möglichkeit? :D (ich hab nicht den kompletten Code gepostet ^^)

Code: Alles auswählen

def whowins(who):
  if(who == "X"):
    who = "Spieler1"
  else:
    who = "Spieler2"
  return who

def finish():
  unentschieden = (feld[0]+feld[1]+feld[2]+feld[3]+feld[4]+feld[5]+feld[6]+feld[7]+feld[8]).replace("-", "")
  if(feld[0].replace("-", "") == feld[1] and feld[0] == feld[2]):
    winner = whowins(feld[0])
    print(winner + " gewinnt.")
    return True
  elif(feld[0].replace("-", "") == feld[3] and feld[0] == feld[6]):
    winner = whowins(feld[0])
    print(winner + " gewinnt.")
    return True
  elif(feld[0].replace("-", "") == feld[4] and feld[0] == feld[8]):
    winner = whowins(feld[0])
    print(winner + " gewinnt.")
    return True
  elif(feld[1].replace("-", "") == feld[4] and feld[1] == feld[7]):
    winner = whowins(feld[1])
    print(winner + " gewinnt.")
    return True
  elif(feld[3].replace("-", "") == feld[4] and feld[3] == feld[5]):
    winner = whowins(feld[3])
    print(winner + " gewinnt.")
    return True
  elif(feld[2].replace("-", "") == feld[4] and feld[2] == feld[6]):
    winner = whowins(feld[2])
    print(winner + " gewinnt.")
    return True
  elif(feld[2].replace("-", "") == feld[5] and feld[2] == feld[8]):
    winner = whowins(feld[2])
    print(winner + " gewinnt.")
    return True
  elif(feld[6].replace("-", "") == feld[7] and feld[6] == feld[8]):
    winner = whowins(feld[6])
    print(winner + " gewinnt.")
    return True
  elif(len(unentschieden) == 9):
    print("Unentschieden.")
    return True
Es gibt 10 Arten von Menschen. Die, die das Binärsystem(auch Dualsystem genannt ;)) verstehen und die, die es nicht verstehen..
Benutzeravatar
naeg
User
Beiträge: 33
Registriert: Dienstag 27. April 2010, 11:53

Das ist tatsächlich sehr unschön.

Es gibt ja insgesamt 8 verschieden Situationen in denen einer gewinnt (3 mal senkrecht, 3 mal horizontal, 2 mal diagonal). Jeweils senkrecht, horizontal und diagonal könntest du zusammen (z.b. in einer Funktion) überprüfen. Ist zwar nicht viel schöner, dennoch ist es aus meiner Sicht um einiges leichter zu verstehen.

Außerdem könnte man die Abfrage einfacher gestalten, und zwar mit [0]*3 == [0] + [1] + [2], usw.

Für horizontal könnte das z.B. so aussehen:

Code: Alles auswählen

# ...
for i in range(0, 7, 3):
    if feld[i]*3 == feld[i] + feld[i+1] + feld[i+2]:
        return feld[i] # feld[i] gewinnt
# ...
Ich dachte zuerst an eine Lösung mit einem dict wie in in diesem Fall: http://www.python-forum.de/viewtopic.php?f=11&t=26624
Aber schien mir dann doch nicht so sinnvoll (soll nicht heißen das meine Lösung die beste ist ;)).
mfg naeg
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Naja, im Falle von TicTacToe gibt es ja nur eine endliche (und zudem überschaubare) Anzahl an Kombinationen des Spielfeldes, die man prüfen muss, um einen möglichen Sieger zu ermitteln.

Daher würde ich vorschlagen, man definiert diese Kombinationen an Feldern zu Beginn und prüft nach jedem Setzen eines Spielers, ob eine Kombination ggf. zu einem Sieg geführt hat:

Code: Alles auswählen

In [128]: check_fields = (                               
(0, 1, 2),
(3, 4, 5),
(6, 7, 8),
(0, 3, 6),
(1, 4, 7),
(2, 5, 8),
(0, 4, 8),
(2, 4, 6)
)

In [138]: checks = [itemgetter(*_) for _ in check_fields]

In [139]: field
Out[139]: [1, 1, 4, 1, 4, 1, 4, 4, 0]

In [140]: checks[0](field)                               
Out[140]: (1, 1, 4)

In [141]: checks[7](field)
Out[141]: (4, 4, 4)

In [142]: sums = [sum(check(field)) for check in checks]

In [143]: sums
Out[143]: [6, 6, 8, 6, 9, 5, 5, 12]
In [138] sind die zu prüfenden Felder als Liste von `itemgetttern` verfügbar. Damit kann man nun sehr einfach alle Inhalte von zu prüfenden Feldern in einer Schleife holen. Ich nehme zum Modellieren einfach die Werte 1 und 4 als Einträge und bilde die Summe über jedes Tripel.

Spieler 1 gewinnt bei einer Summe von 3 (kann nur durch Einsen in einer Prüfkombination erzielt werden), Spieler 2 bei einer Summe von 12 (3*4). Nicht belegte Felder enthalten 0.

Letztlich beschränkt sich eine Funktion, die einen möglichen Sieger ermittelt darauf, anhand des aktuellen Spielfeldes und der "checks" die Summen zu ermitteln [142] und diese dann auf 12 oder 3 zu testen:

Code: Alles auswählen

def check_win(field, checks):
    for check in checks:
        if sum(check(field)) == 3:
            return True, 1
        elif(sum(check(field)) == 12:
            return True, 2
    return False, None
Da es einen Sieger nach jedem Zug geben kann, könnte man das ganze noch vereinfachen, indem man den Spieler (bzw. seinen "Wert") an die Check-Funktion übergibt:

Code: Alles auswählen

def check_win(field, value, checks):
    return any([sum(check(field)) == value for check in checks])
Imho ist das schon recht übersichtlich :-)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
jngr
User
Beiträge: 2
Registriert: Mittwoch 15. Juni 2011, 13:27
Kontaktdaten:

Erstmal danke für eure Antworten ;)
Ich guck mir mal eure Varianten an. Danach werde ich mich mal an Minimax rantasten :)
Es gibt 10 Arten von Menschen. Die, die das Binärsystem(auch Dualsystem genannt ;)) verstehen und die, die es nicht verstehen..
Antworten