Seite 1 von 1

Tic Tac Toe

Verfasst: Freitag 7. September 2018, 17:21
von FroxGame
Hallo,
ich habe ein kleines Problem in meinem Tic Tac Toe, und zwar funktioniert der Zug des Computers nicht(Funktion: computer_move). Ich möchte aber schon, dass der Computerzug erstmal random ist. Die " richtige KI" möchte ich auch selber coden :) . Was habe ich falsch gemacht?
Vielen Dank für Antworten.

Code: Alles auswählen

import random
def draw_board(board):
    #Gibt das Spielfeld mit eingesetzten Zeichen wider
    print("   |   |   ")
    print(" " + board[7] + " | " + board[8] + " | " + board[9])
    print("   |   |   ")
    print("------------")
    print("   |   |   ")
    print(" " + board[4] + " | " + board[5] + " | " + board[6])
    print("   |   |   ")
    print("------------")
    print("   |   |   ")
    print(" " + board[1] + " | " + board[2] + " | " + board[3])
    print("   |   |   ")

def player_move(board, sign):
    #Lässt den Spieler/die Spieler den Zug bestimmen
    while True:
        try:  #Idiotensicher
            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
        except ValueError:
            player_move(board,sign)
    board[field] = sign
    draw_board(board)

def main_player(turn):
    #Leitet den Spieler richtig zur player_move Funktion
    if turn == 1:
        player_move(board, "X")
    elif turn == -1:
        player_move(board, "O")

def main_computer(turn):
    #Leitet den Computer richtig zur computer_move Funktion
    if turn == 1:
        computer_move(board, "X")
    elif turn == -1:
        computer_move(board, "O")

def is_winner(bo, le):
    #Checkt, ob jemand gewonnen hat
    if le == 1:
        le = "X"
    elif le == -1:
        le = "O"
    return ((bo[1] == le and bo[2] == le and bo[3] == le) or
    (bo[4] == le and bo[5] == le and bo[6] == le) or
    (bo[7] == le and bo[8] == le and bo[9] == le) or
    (bo[1] == le and bo[4] == le and bo[7] == le) or
    (bo[2] == le and bo[5] == le and bo[8] == le) or
    (bo[3] == le and bo[6] == le and bo[9] == le) or
    (bo[1] == le and bo[5] == le and bo[9] == le) or
    (bo[3] == le and bo[5] == le and bo[7] == le))

def play_again():
    #Fragt nach, ob nochmal gespielt werden soll
    print("Möchtest du nochmal spielen?(ja oder nein)")
    return input().lower().startswith("j" or "J")

def is_free(board, move):
    #Vielleicht unnötig??????????????????
    return board[move]==[" "]

def computer_move(board, letter):
    #Lässt den Computer seinen Zug bestimmen. Diese Funktion meinte ich in der Frage!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    print("Der Computer ist dran:")
    move = 1
    while board[move] != [" "]:
        move = random.randint(1,9)
    else:
        board[move] = letter
        draw_board(board)

sign = "O" and "X"

print("WIllkomen bei Tic Tac Toe!")
while True:
    counter = 0
    move = 1       						
    mode = 0						#Hier wird alles resettet
    board = [" "] * 10
    gameIsPlaying = True
    while mode != "PvP" and  mode != "PvE" and mode != "EvE":
        mode = input("Möchtest du PvP, PvE oder EvE spielen?")
    if mode == "PvP":
    #ES wird Spieler gegen Spieler gespielt
        while gameIsPlaying:
            if move == 1 or move == -1:
                main_player(move)
                counter = counter+1
                if is_winner(board, move):
                    if move == 1:
                        move = "X"
                    elif move == -1:
                        move = "O"
                    print("Super, Spieler {} hat gewonnen!".format(move))
                    gameIsPlaying = False
                elif counter == 9:
                    print("Unentschieden!")
                    gameIsPlaying = False
                move = move * -1

        if not play_again():
            break

    elif mode == "PvE":
    #Es wird Spieler gegen Computer gespielt
        while gameIsPlaying:
            if move == 1:
                main_player(1)
                move = -1
                counter = counter + 1
                if is_winner(board, "X"):
                    print("Super, du hast gewonnen!")
                    gameIsPlaying = False
                elif counter == 9:
                    print("Unentschieden")
                    gameIsPlaying = False
            elif move == -1:
                computer_move(board)
                move = 1
                counter = counter + 1
                if is_winner(board, "O"):
                    print("Schade, der Computer gewinnt!")
                    gameIsPlaying = False
                elif counter == 9:
                    print("Unentschieden")
                    gameIsPlaying = False

        if not play_again():
            break

    elif mode == "EvE":
    #ES wird Computer gegen Computer gespielt
        while gameIsPlaying:
            if move == 1 or move == -1:
                main_computer(move)
                counter = counter + 1
                if is_winner(board, move):
                    if move == 1:
                        move = "X"
                    elif move == -1:
                        move = "O"
                    print("Computer {} hat gewonnen!".format(move))
                    gameIsPlaying = False
                elif counter == 9:
                    print("Unentschieden!")
                    gameIsPlaying = False
                move = move * -1

            if not play_again():
                break

Re: Tic Tac Toe

Verfasst: Freitag 7. September 2018, 18:03
von Sirius3
@FroxGame: player_move ist fehlerhaft. Rekursion ist selten sinnvoll und hier falsch angewendet. Statt also player_move nochmal aufzurufen wäre ein `print('falsche Eingabe')` ausreichend.

Die Kommentare gleich anch den defs wären besser doc-Strings.

Warum bekommen main_player und main_computer `turn` als -1 und 1 und nicht gleich als X oder O? Dann sind die beiden Funktionen (bei denen das main für mich keinen Sinn macht) überflüssig.
Die Funktionen bekommen `board` aus dem nichts, das sollte ein Parameter sein.
Bei is_winner heißt turn sogar le, was ein völlig nichtssagender Name ist.

Mit `turn == bo[1] == bo[2] == bo[3]` kann man die Bedinung kürzer schreiben.

In `play_again` ist der Sinn von `'j' or 'J'` ziemlich fraglich, weil das einfach nur 'j' ist. Schau Dir nochmal die Funktionsweise von `or` und `and` als logische Operatoren an.

Da `is_free` nicht benutzt wird, ist es im Moment unnötig. Vor allem ist es aber falsch, weil ein String nie gleich einer Liste ist. In `computer_move` hast Du den selben Fehler nochmal gemacht.

Ein `else` bei einem `while` ohne `break` ist verwirrend. Es ist auch unzufällig, wenn der Computer immer als ersten Zug das erste Feld belegt.

Bei `sign = "O" and "X"` gilt das selbe wie bei `or`. Schau dir nochmal die Funktionsweise von logische Operatoren an.

Dreimal fast den selben Code für PvP PvE oder EvE zu schreiben, ist schlechter Stil; definier Dir zwei Variablen, welche main_-Funktion X und welche O aufruft und Du hast nur noch einen Fall.

Statt eines Flags `gameIsPlaying` (das übrigens nicht nach Konvention geschrieben ist) benutzt man eine Endlosschleife, die man mit break verläßt. Da man hier aber nur 9 Durchgänge hat, ist eine for-Schleife das beste.

Im PvP-Fall: Wäre die if-Abfrage für mode nicht erfüllt, hättest Du eine nie endende Schleife, da es aber immer erfüllt ist, ist sie einfach nur überflüssig.

Im EvE-Fall ist play_again falsch eingerückt.

`mode` wird für sehr viele verschiedene Dinge benutzt. Das führt nur zu fehlerhaften Programmen. Benutze für jeden Zweck eine eigene Variable.

die Hauptschleife könnte also so aussehen:

Code: Alles auswählen

from itertools import islice, cycle

for turn in islice(cycle('XO'), 9):
    if mode == "PVP" or (turn == "X" and mode == "PvE"):
        player_move(board, turn)
    else:
        computer_move(board, turn)
    if is_winner(board, turn):
        print("Spieler {} hat gewonnen!".format(turn))
        break
else:
    print("Unentschieden")

Re: Tic Tac Toe

Verfasst: Freitag 7. September 2018, 18:58
von FroxGame
@Sirius3: Vielen Dank für die vielen Tips, allerdings ist meine Hauptfrage noch nicht geklärt, und zwar wie ich den Zug vom Computer zum Laufen bekomme. Aber sonst vielen Dank!

Re: Tic Tac Toe

Verfasst: Freitag 7. September 2018, 19:40
von Sirius3
@FroxGame: den Fehler habe ich Dir genannt. Die Frage ist, was der richtige Vergleich ist.

Re: Tic Tac Toe

Verfasst: Freitag 7. September 2018, 19:45
von FroxGame
@Sirius3: Ich habe deine Hinweise verstanden, allerdings wird bei mir beim Zug des Computers nichts ausgegeben

Re: Tic Tac Toe

Verfasst: Freitag 7. September 2018, 20:09
von Sirius3
Wsa bedeutet, „Es wird nichts ausgegeben”?

Re: Tic Tac Toe

Verfasst: Freitag 7. September 2018, 20:13
von FroxGame
Naja das ist zum Beispiel die Ausgabe, wenn ich PvE nehme. Das Programm sagt einfach nix mehr und ich weiß nicht, warum.:

WIllkomen bei Tic Tac Toe!
Möchtest du PvP, PvE oder EvE spielen?PvE
Auf welchem Feld möchtest du X platzieren? (Zahl von 1 - 9)1
| |
| |
| |
------------
| |
| |
| |
------------
| |
X | |
| |
Der Computer ist dran:

Re: Tic Tac Toe

Verfasst: Freitag 7. September 2018, 20:17
von Sirius3
Es sagt nichts mehr, weil es in einer Endlosschleife hängt, weil die Abbruchbedingung nie erfüllt sein kann.

Re: Tic Tac Toe

Verfasst: Freitag 7. September 2018, 20:18
von FroxGame
Ok, vielen Dank. Ich kümmer mich drum.