Caliban: Als erstes fällt die Namensgebung ins Auge die nicht dem Style-Guide entspricht.
Die `MasterMind`-Objekte hätte ich nicht wiederverwendbar entworfen. Neues Spiel -- neues Objekt. Bei Objekten die man "reset"ten kann, muss man einfach auf mehr aufpassen, wenn man sie irgendwann einmal erweitern möchte. Alles was neu dazu kommt, muss bei einem Rücksetzen potentiell auch berücksichtigt werden und kann vergessen werden. Farben und Länge könnte man als Argumente der `__init__()` übergeben. Mit Default-Werten damit man es nicht *muss*, aber die Möglichkeit wäre ganz nett und auch unkompliziert und einfach zu realisieren.
Der `random.seed()`-Aufruf ist überflüssig. Das wird schon beim importieren des `random`-Moduls gemacht, ein weiterer Aufruf hat "statistisch" keinen Effekt. Dafür bietet das `random`-Modul praktische Funktionen die den Code wesentlich vereinfachen können. Das Erzeugen des Geheimcodes lässt sich recht kompakt in einer Zeile ausdrücken:
Code: Alles auswählen
return ''.join(random.choice(self.farben) for _ in xrange(self.laenge))
Wobei das Längenattribut eigentlich unnötig sein sollte, denn spätestens wenn der Code festgelegt ist, kann man die Länge aus dem Code ermitteln -- die Information ist also redundant.
Die `_check()`-Methode liesse sich mit einem `set()` ausdrücken:
Code: Alles auswählen
return (len(code) == len(self.code)
and len(set(code).difference(self.farben)) != 0)
Bei `Raten()` sind die Namen nicht gut gewählt. Weder `Weisz`, `Schwarz` und noch weniger `List1`, `List2` sagen etwas über die Bedeutung der Objekte hinter den Namen aus. Der Code ist teilweise auch nicht so einfach zu durchschauen und verwendet mehr Indexe als er müsste. Die Anzahl der richtigen Farben auf der richtigen Position lässt sich zum Beispiel ganz einfach ausdrücken:
Code: Alles auswählen
schwarz = sum(a == b for a, b in zip(self.code, code))
Das Hauptprogramm auf Modulebene sollte noch in einer Funktion verschwinden und über folgendes Idiom aufgerufen werden, damit man das Modul für die verschiedensten Zwecke auch importieren kann, ohne dass das Programm gleich ausgeführt wird:
Warum heisst das Exemplar von `MasterMind` denn `KI`? Ich sehe da keine "Intelligenz"?
Statt des ``continue`` bei einer Fehleingabe in der inneren ``while``-Schleife hätte ich den folgenden Quelltext eher in einen ``else``-Zweig gesteckt. So ein ``continue`` ist eine "Sprunganweisung" die den Quelltext etwas schwerer durchschaubar macht.
Das Ergebnis von `raten()` hätte man dort auch an zwei sprechende Namen binden können statt im Weiteren auf ``ergebnis[0]`` und ``ergebnis[1]`` zuzugreifen.