Tic Tac Toe game

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
FroxGame
User
Beiträge: 12
Registriert: Samstag 1. September 2018, 11:35

Ich habe eine Frage! Ich möchte ein Tic Tac Toe Spiel mit einem Liste, genannt board, welche für jedes Feld eine 0 hat.0 bedeutet freises Feld, 1 bedeutet X und -1 bedeutet O! Wie kann ich aus den Zahlen in der Liste board die Buchstaben X und O auf dem Spielfeld(Funktion drawBoard) anzeigen lassen?

Code: Alles auswählen

board = [0,0,0,0,0,0,0,0,0,0]
field1= 0



def player1Move():
    field1= 0
    while field1 not in range(1, 10):
        field1 = int(input("Auf welchem Feld möchtest du O platzieren?(Zahl von 1 - 9)"))
    checkForFree1()


def checkForFree1():
    if board[field1] == 0:
        board[field1] = int(-1)
        drawBoard()
    else:
        print("Das Feld ist schon belegt, nimm ein anderes Feld!")
        player1Move()
    



def drawBoard():
    print("   |   |   ")
    print(" " + board[1] + " | " + board[2] + " | " + board[3])
    print("   |   |   ")
    print("------------")
    print("   |   |   ")
    print(" " + board[4] + " | " + board[5] + " | " + board[6])
    print("   |   |   ")
    print("------------")
    print("   |   |   ")
    print(" " + board[7] + " | " + board[8] + " | " + board[9])
    print("   |   |   ")
    field1 = ""

player1Move()
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

Es ist schlecht, wenn eine Funktion ›player1Move‹ die nächste ›checkForFree1‹ aufruft und diese wiederum die erste. Soll etwas wiederholt werden, benutz man Schleifen.

Funktionen bekommen alles, was sie brauchen, über ihre Argumente, und man benutzt keine globalen Variablen. Laut Namenskonvention schreibt man Funktionen, wie Variablen, klein_mit_unterstrich.

Statt 0, 1 und -1 benutze doch einfach ' ', 'x' und 'o'.

Code: Alles auswählen

def draw_board():
    print("   |   |   ")
    print(" " + board[1] + " | " + board[2] + " | " + board[3])
    print("   |   |   ")
    print("------------")
    print("   |   |   ")
    print(" " + board[4] + " | " + board[5] + " | " + board[6])
    print("   |   |   ")
    print("------------")
    print("   |   |   ")
    print(" " + board[7] + " | " + board[8] + " | " + board[9])
    print("   |   |   ")

def player_move(board, sign):
    while True:
        field = int(input("Auf welchem Feld möchtest du {} platzieren? (Zahl von 1 - 9)".format(sign)))
        if field < 1 or field > 9:
            print("Gib Zahl von 1 -9 ein.")
        elif board[field] != ' ':
            print("Das Feld ist schon belegt, nimm ein anderes Feld!")
        else:
            break
    board[field] = sign
    draw_board(board)

def main():
    board = [' '] * 9
    player_move(board, 'x')

if __name__ == '__main__':
    main()
Benutzeravatar
__blackjack__
User
Beiträge: 13103
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@FroxGame: Du könntest ein Wörterbuch (`dict`) anlegen das die Zahlen auf die entsprechenden Zeichen abbildet und das dann in der Ausgabefunktion verwenden.

Gibt es einen Grund warum Du diese Zahlen speicherst und nicht einfach gleich die Zeichen die ausgegeben werden sollen?

Insbesondere wenn Du bei den Zahlen bleibst, würde ich da Konstanten für definieren, damit der Leser den Code besser versteht und sich nicht fragen muss was die Zahlen bedeuten.

Apropos Zahlen: Die Zahlen in den Funktionsnamen solltest Du entfernen. Der Code für Spieler 1 und Spieler 2 wird sehr ähnlich sein und sich nur durch eine Konstante unterscheiden, das sind also keine verschiedenen Funktionen, sondern nur eine, die mit dem entsprechenden Argument aufgerufen wird.

Der Programmablauf ist falsch gelöst weil Du Funktionen nicht richtig verwendest. Funktionen sind keine benannten Sprungmarken, sondern in sich geschlossene Codeeinheiten die alles was sie benötigen, ausser Konstanten, als Argumente übergeben bekommen, und die man so verwendet, das man auch erwartet das sie zum Aufrufer zurückkehren. Und dabei gegebenenfalls ein Ergebnis an den Aufrufer zurückgeben.

Du dagegen lässt Deine ”Funktionen” auf magische Weise auf globalen Zustand zugreifen, und die rufen sich ”endlos” gegenseitig auf, was den Aufrufstapel immer weiter anwachsen lässt, bis das Programm irgendwann mit einer Ausnahme abbrechen wird. Auch wenn dieses Programm das Rekursionslimit (noch) nicht erreichen wird, ist es abzusehen das es Probleme geben wird, wenn Du diese Art der Strukturierung beibehältst. Es gibt Programmiersprachen die Endrekursion wegoptimieren, Python ist keine solche Sprache. Du willst da einfach eine Schleife verwenden die abgebrochen wird wenn der Benutzer ein freies Feld ausgewählt hat.

-1 ist bereits eine ganze Zahl. Es macht keinen Sinn dafür ``int(-1)`` zu schreiben.

Namenskonvention in Python ist klein_mit_unterstrichen für alles ausser Konstanten (KOMPLETT_GROSS) und Klassen (MixedCase). Also beispielsweise `draw_board()` anstatt `drawBoard()`.

Die Funktion enthält übrigens ziemlich viel regelmässigen Code denn man vereinfachen bzw. verallgemeinern kann. Das würde noch einfacher gehen, wenn man das `board` nicht als Flache Liste sondern als verschachtelte 2D-Liste anlegen würde. Also eine Liste mit einer Liste pro Zeile die dann die Werte für die jeweilige Zeile enthält.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
FroxGame
User
Beiträge: 12
Registriert: Samstag 1. September 2018, 11:35

Vielen Dank für die Antworten.
Antworten