Tic Tac Toe mit Computergegner

Stellt hier eure Projekte vor.
Internetseiten, Skripte, und alles andere bzgl. Python.
Antworten
iceman21
User
Beiträge: 41
Registriert: Sonntag 25. März 2007, 20:45
Kontaktdaten:

Hi @ all

Ich habe ein einfaches TicTacToe oder auch XXO in Python programmiert. Die Ausgabe wird über den Browser geregelt (cgi) Ich würde von euch gerne wissen, wo ich den algorythmus noch verbessern könnte. D.h. kürzen oder effizienter machen. Der Computer gegner ist glaube cih unbesiegar. Zumindest habe ich schon eine wette damit gewonnen. ihr könnt es ja auch mal probieren. vor dieser datei , steht ein start script dass alle werte wieder resettet .. die daten werden über eine datei weitergegeben.
Viel spaß beim probiern.
Ich werde versuchen meinen server demnächst so oft wie möglich an zu haben, sodass ihr mein spiel ausprobieren könnt. gestartet wird es über folgenden link
http://schroeder88.dyndns.org/jens/ki/start.cgi

und hier der Code (ttt.cgi) :
http://paste.pocoo.org/show/1977/

Kritik erwünscht :wink:

MfG
Iceman21
Benutzeravatar
veers
User
Beiträge: 1219
Registriert: Mittwoch 28. Februar 2007, 20:01
Wohnort: Zürich (CH)
Kontaktdaten:

Code: Alles auswählen

# #################### =<beginn programm>= ###############################
# #     Jens Schroeder                                            
# #     TicTacToe - mit Computer Gegner (Unbesiegbar?)                                   
# #     Informatik 11
# #     17.07.2007

# importiert benötigte Module
>> mach daraus einen Docstring
Den letzten Kommentar kannst dir sparen ;)

Verschiebe die imports an den Anfang der Datei. Gib deinen Variablen englische Namen. Und Allgemein lies doch mal PEP8, das Python style guide.

Zu deinem Algorithmus, sieht für mich zu Aufwendig aus. Eine perfekt spielende TicTacToe KI müsste einfacher zu machen sein.

Ich hab mal TicTacToe mit einem (pseudo) MiniMax Algorithmus implementiert, ist zwar lustig aber langsam.

Grundsätzlich musst du ja bloss 3 Züge im Voraus berechnen und sehen ob der User bei einem bestimmten Zug die Chance hat zu gewinnen ;)
BlackJack

Erstes Problem ist so'n typisches Henne-Ei-Problem: Man braucht einen Spielstand um das Programm zu starten, der wird aber erst in dem Programm gespeichert, dass man nicht ohne starten kann. :-)

Es gibt Zeilen die länger als 80 Zeichen sind, eine ist sogar über 500 Zeichen lang. Da hätte sich zum Beispiel eine mehrzeilige Zeichenkette angeboten, vielleicht sogar mit ordentlicher Einrückung des HTML-Quelltextes.

Vor und nach Operatoren sollte ein Leerzeichen stehen und ``<>`` ist extrem ungebräuchlich, für "ungleich" wird üblicherweise ``!=`` verwendet.

Dann sollte man globale Variablen vermeiden. Auf Modulebene sollten möglichst nur Klassen, Funktionen und Konstanten stehen.

Pickle-Dateien müssen als Binärdateien geöffnet werden, sonst sind sie nicht portabel.

Die Namensgebung leidet manchmal an Abkürzungen, die man auch hätte ausschreiben können.

Warum wird `l[4]` in `load()` in `int` umgewandelt? Die Runde wird doch als ganze Zahl gespeichert, also wird sie auch wieder so geladen. `moegl` könnte `MOEGLICHKEITEN` heissen und eine programmweite Konstante sein und sollte nicht durch `load()` "geschleift" werden.

`formulare` wird im Programm immer von `tuple` nach `list` gewandelt, verändert, und dann wieder in ein `tuple` gewandelt. Das Programm wäre etwas effizienter und kürzer wenn es die ganze Zeit eine Liste wäre, die nur an der einen Stelle im Programm, wo man sie als Tupel braucht, in eines wandeln würde. Wobei man an der Stelle vielleicht die Ausgabe programmatischer erzeugen könnte, schliesslich wiederholt sich in der Zeichenkette eine ganze Menge.

`nichtgetippt` in `ki()` sieht von der Verwendung her nach einem guten Kandidaten für `set()` aus. Die beiden ``for``-Schleifen, die `nichtgetippt` berechnen würden zu dieser Zeile schrumpfen:

Code: Alles auswählen

    nichtgetippt = set(xrange(10)) - set(sp1 + sp2)
In `gewonnen()` wird `formulare` nicht benutzt. Die ``while``-Schleife ist eigentlich eine ``for``-Schleife über `moegl`, die verschachtelten ``if``\s kann man als eines mit ``and``-verknüpften Bedingungen schreiben oder mit einer Schleife. Die beiden Fälle unterscheiden sich nur durch `sp1`/`sp2` und welcher Wert an `b` zugewiesen wird. Und man sollte "magische" Literale vermeiden. Symbolische Konstanten sind viel aussagekräftiger. Ungetestet:

Code: Alles auswählen

NIEMAND, SPIELER_A, SPIELER_B, UNENTSCHIEDEN = xrange(4)

def gewonnen(spieler_a, spieler_b, runde):
    ergebnis = NIEMAND
    for moeglichkeit in MOEGLICHKEITEN:
        for gewinner, spieler in ((SPIELER_A, spieler_a),
                                  (SPIELER_B, spieler_b)):
            if all(feld in spieler for feld in moeglichkeit):
                ergebnis = gewinner
                break
        else:
            if ergebnis == NIEMAND and runde == 6:
                ergebnis = UNENTSCHIEDEN
    return ergebnis
In `loeschebut()` würde ich den Index entfernen oder zumindest mit `enumerate()` das "manuelle" hochzählen beseitigen.

Code: Alles auswählen

def loeschebut(formulare):
    result = list()
    for element in formulare:
        if 'input type' in element:
            result.append('')
        else:
            result.append(element)
    return result
In Python 2.5 könnte man das sogar in einer "list comprehension" lösen:

Code: Alles auswählen

    return [('' if 'input type' in element else element)
            for element in formulare]
Antworten