5Danke
ERLEDIGT
JA
JA
ANTWORTEN
11
11
ZUGRIFFE
1250
1250
EMPFEHLEN
-
15.08.09 09:55 #1
- Registriert seit
- May 2009
- Beiträge
- 88
Hallo,
ich bin ein Neueinsteiger in Java und nach dem Lesen von 2 Büchern habe ich es geschafft, mit Anleitungen aus einem der Bücher, und viel Improvisation ein TicTacToe Spiel zu programmieren. Das Spiel funktioniert, aber die künstliche Intelligenz ist erstaunlich dumm. Die Züge des Computers basieren auf dem Bruteforce-Algorithmus und einer Bewertungsfunktion, eigentlich sollte der Computer in der Lage sein gegen jeden beliebigen Menschen unentschieden zu spielen, doch das tut er nicht.
Weiß jemand, wie ich ihn dazu bringen kann?
Der Quellcode liegt im Anhang
-
15.08.09 10:49 #2
Hi,
seit ner halben Stunde versuche ich nun schon, deinen Code zu verstehen. Ergebnislos. Und zwar aus folgenden Gründen:
1. gesamter Code ist unformatiert( gut, das habe ich mit Netbeans wieder hingebogen)
2. aussagelose Methoden und Variablen (z.B.: "k", "anzuege")
3. keine Kommentare außer denen von Netbeans
zu 1): Wenn man deine Datei mit den Editor öffnet, wird man erst mal von unformatierten Code erschlagen. Also muss man die txt-Datei umbennen und in eine IDE einfügen. Warum stellst du nicht gleich die *.java-Datei zu Verfügung?
zu 2) Wie schon in den Beispielen: Was soll game.k darstellen oder was macht value()? Irgendendeinen Wert zurückgeben? So wie ich das verstanden habe, prüft sie, ob jemand gewonnen hat. Ist das richtig oder habe ich deinen Code falsch interpretiert?
zu 3) Wenn du schon aussagelose Methoden hast, dann verwende doch bitte Kommentare.
Also, wenn du deinen Code nochmal überarbeitest, wird man dir auch bereitwilliger helfen.
Ciao
DosCoderMan kann mich für das verantwortlich machen, was ich hier schreibe, nicht für das, was andere verstehen.
Sollte ich mal Mist labern weist mich bitte darauf hin.
Ich freue mich über ein Danke, wenn ich helfen konnte!
-
15.08.09 13:00 #3
- Registriert seit
- May 2009
- Beiträge
- 88
Entschuldigung
, hier die neue, kommentierte Version.
Einen Java File kann ich leider nicht hochladen, es sollte aber reichen, den Text zu markieren und in die jeweilige IDE zu kopieren
quellcode.txt
-
15.08.09 21:47 #4
Hi,
irgendwie ist es entwedern zu heiß, zu spät oder ich bin einfach zu doof, aber selbst nach 2.5 Stunden habe ich das Problem nicht gepackt
. Ich wüde es ja morgen nochmal versuchen, aber da fahre ich 2 Wochen in Urlaub (zwar mit Notebook, aber ohne Netz). Sorry.
Ich muss aber dazu sagen, dass dein Quellcode ziehmlich vermurkst ist:
Beipsiel:
Zudem erschwert die fehlende OOP das ganze. Aber wie gesagt, es muss auch irgendwie an mir liegen. Tut mir echt leicht.Code java:1 2 3 4 5
int wert=0; [...] wert=value(); //das geht doch kürzer! [...] if(wert!=0){return wert;} wert=0; //ist das notwendig, nach der Abfrage?
*Sache an den nächsten weitergeb*
Ciao
DosCoderMan kann mich für das verantwortlich machen, was ich hier schreibe, nicht für das, was andere verstehen.
Sollte ich mal Mist labern weist mich bitte darauf hin.
Ich freue mich über ein Danke, wenn ich helfen konnte!
-
Hallo,
also ich denke, es geht hauptsächlich um diese mysteriöse Funktion namens x:
(Einrückungen sind von mir bzw. Eclipse - ansonsten kann man den Code ja nicht vernünftig lesen. Gewöhn dir am besten möglichst schnell an, deinen Code einzurücken.)Code java:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
public int x(int tiefe) { int wert = 0; int wertneu = 0; int anzzuege = 0; wert = value(); if (tiefe == 0) { return wert; } if (wert != 0) { return wert; } wert = 0; getzuege(); for (int i = 0; i < 9; i++) { anzzuege += zuege[i]; } if (anzzuege == 0) { return 0; } for (int n = 0; n < 9; n++) { if (zuege[n] == 1) { buttons.get(n).setText("X"); wertneu = o(tiefe - 1); if (wertneu >= wert) { wert = wertneu; k = n; } buttons.get(n).setText(" "); } } return wert; }
Meine Anmerkungen/Tipps hierzu (manche Sachen wurden schon erwähnt, aber ich will sie trotzdem nochmal nennen):- Deklariere lokale Variablen dort, wo du sie brauchst. Die Variable wertneu deklarierst du beispielsweise ganz am Anfang, und man hat keine Ahnung a) welchen Sinn die Variable erfüllt und b) warum sie auf 0 gesetzt wird. Wenn die Variable dann ziemlich zum Schluss der Funktion hin benutzt wird, muss man mit dem Blick erst wieder ganz nach oben wandern, um rauszufinden, wie sie denn jetzt initialisiert wurde.
- Ergebnisse einer Funktion "hintenrum", also über das Setzen von Membervariablen, zurückzugeben, ist auch erst mal verwirrend. Das kann in bestimmten Fällen schon Sinn ergeben, aber dann nennt man die Methode nicht getzuege, sondern eher updatezuege o.ä. (noch besser: updateMoves, ein Gemisch aus verschiedenen Sprachen bei der Benennung lenkt nur ab.)
- Womit wir schon bei der Benennung wären: die Benennung einer Funktion/Variable macht idealerweise Kommentare zu ihrem Verwendungszweck überflüssig. Namen wie x, o, k oder value sind daher tabu! Eine Ausnahme stellen höchstens Laufvariablen in Schleifen dar, aber nur wenn aus dem Kontext unmittelbar klar ist, wozu sie verwendet wird.
- Die Funktionen x und o sind bis auf 2 Zeilen absolut identisch. Code, der an mehreren Stellen steht, ist schlecht, da man bei einer Änderung an einer Stelle auch die andere Stelle ändern muss (und wehe man vergisst das mal...). Überleg dir mal, ob du die beiden Funktionen nicht zusammenfassen könntest.
- Trenne die grafische Oberfläche (View) von den Daten (Model) deines Programms! Die ständige Aktualisierung von zuege aus den Werten der Buttons ist durch die Brust ins Auge. Und ganz nebenbei auch der Grund, warum dein Algorithmus nicht funktioniert. Du setzt nämlich nach einem ausprobierten Zug und dem rekursiven Aufruf den jeweiligen Button wieder zurück, aber das Array zuege ist immer noch auf dem alten Stand. Mein Vorschlag: ersetze das Array zuege durch Dieses Array ist dann dein "Modell" des Spielfeldes. Eine 0 im Array steht für ein freies Feld, eine 1 für ein "X" und eine -1 für ein "O". Verwende dieses Array und nur dieses Array für alle Abfragen, die den Status des Spielfeldes betreffen (also z.B. auch zur Ermittlung, ob jemand gewonnen hat). Setze die Textwerte der Buttons nur dann, wenn tatsächlich ein Zug erfolgt, den der Benutzer auch mitbekommen soll. Wenn du dich daran hältst, sollte ein a) viel kürzerer b) leichter verständlicher und wartbarer und c) vor allem funktionierender Quellcode rauskommen.Code java:
1
int spielfeld[9];

Grüße, Matthias„Gib einem Menschen einen Fisch, und er wird für einen Tag satt. Lehre ihn Fischen, und er wird ein Leben lang satt.“
“For every complex problem, there is an answer that is short, simple and wrong.”
“Pessimism is safe, but optimism is a lot faster!”
Aktuelles Coding Quiz: #17 - Wörter kreuz und quer
-
16.08.09 10:32 #6
- Registriert seit
- May 2009
- Beiträge
- 88
Habe versucht, deine Ratschläge so gut wie möglich zu befolgen und den Quellcode neu geschrieben. Ich meine bereits eine leicht Vebesserung zu spüren, aber der Rechner ist immer noch zu besiegen.
Der Quellcode ist im Anhang.
quellcode2.txt
-
Hallo,
das sieht doch schon mal viel besser aus! So lässt sich der Quellcode gleich besser verstehen. Noch ein paar Anmerkungen zum Programmierstil:- Das hier: ist unschön, da die Initialisierung mit 0 überhaupt keinen Sinn ergibt. Kürzer und klarer istCode java:
1 2
int wert=0; wert=bewerten();
Code java:1
int wert=bewerten();
- Mehrere Anweisungen in einer Zeile tragen nicht zur Lesbarkeit des Quellcodes bei. Zeilenumbrüche kosten nichts, ebenso wie Leerzeichen hie und da.
- Deine Art der Einrückung ist etwas unkonventionell. Benutzt du eine IDE wie Eclipse oder Netbeans? Diese können dir die Formatierungsarbeit größtenteils abnehmen. In Eclipse z.B. mit Strg+Umschalt+F.
Der Fehler ist nun folgender: überleg dir mal, was passiert, wenn sich der Computer in einer auswegslosen Situation befindet. anwender() gibt also bei jedem Schleifendurchlauf eine -1 zurück (egal wo der Computer sein X setzt, er verliert zwangsläufig in der Situation). Dann wirdCode java:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
public int computer() { int wert = bewerten(); if (wert != 0) return wert; if (zählefreieFelder() == 0) return wert; int wertneu = 0; for (int i = 0; i < 9; i++) { if (spielfeld[i] == 0) { spielfeld[i] = 1; wertneu = anwender(); if (wertneu >= wert) { errechneterZug = i; wert = wertneu; if (wert == 1) { spielfeld[i] = 0; // Es gibt nur -1,0,1-> 1 ist perfekt->sofort abbrechen // und Rechenzeit sparen return wert; } } spielfeld[i] = 0; } } return 0; }
- errechneterZug nie gesetzt
- am Ende eine 0 zurückgegeben, obwohl eigentlich -1 richtig wäre (es soll ja der bestmögliche Ausgang ermittelt werden, und der ist hier nun mal leider -1)
Dann ist mir grade noch ein Fehler aufgefallen. Angenommen der Computer kann bestenfalls ein Unentschieden erzielen, und zwar indem er auf Position 8 setzt. Dann wird errechneterZug auf 8 gesetzt und probiert dann noch aus, was passiert, wenn er auf Position 9 setzt. Angenommen er würde dann verlieren, wenn er das macht. Dann kann es vorkommen, dass beim Abarbeiten aller möglichen Spielausgänge errechneterZug zwischendrin auf einen ganz anderen Wert gesetzt wird. Dadurch ergibt sich am Schluss ein möglicherweise falscher Zug. Du darfst also errechneterZug nur setzen, wenn der Computer den Zug ermittelt hat, den er tatsächlich als nächstes ausführen soll.
Grüße, Matthias„Gib einem Menschen einen Fisch, und er wird für einen Tag satt. Lehre ihn Fischen, und er wird ein Leben lang satt.“
“For every complex problem, there is an answer that is short, simple and wrong.”
“Pessimism is safe, but optimism is a lot faster!”
Aktuelles Coding Quiz: #17 - Wörter kreuz und quer
- Das hier:
-
16.08.09 18:01 #8
- Registriert seit
- May 2009
- Beiträge
- 88
@Mathias Reitinger ich verwende NetBeans und habe den Quellcode erneut verbessert. Leider ist der Computer keine Spur schlauer

Hier der neue Quellcode.
tictactoe.txt
-
Hallo,
die Methode zahlefreieFelder gibt entgehen ihrer Benennung die Anzahl der belegten Felder zurück. Außerdem wird errechneterZug immer noch in jeder Rekursionstiefe gesetzt.
Grüße, Matthias„Gib einem Menschen einen Fisch, und er wird für einen Tag satt. Lehre ihn Fischen, und er wird ein Leben lang satt.“
“For every complex problem, there is an answer that is short, simple and wrong.”
“Pessimism is safe, but optimism is a lot faster!”
Aktuelles Coding Quiz: #17 - Wörter kreuz und quer
-
20.08.09 19:47 #10
- Registriert seit
- May 2009
- Beiträge
- 88
Ich könnte natürlich noch zahlefreiefelder in bestimmefelder umbenennen,
und versuchen errechneterZug nicht immer zu setzen. Aber ich glaube, dass würde keinen Unterschied machen. zahlefreiefelder tut ihre aufgabe und im Bezug auf den Wert von errechneterZug denke ich, ist die Hauptsache doch, dass er ganz am Ende korrekt gesetzt wird. Mein Problem liegt irgendwo im Algorithmus. Das Programm muss kein Musterbeispiel an Eleganz sein, aber es sollte seine Arbeit tun. Ich glaube nicht, dass diese Verbesserungen den Fehler zeigen würden. Weiß jemand, was an der Theorie falsch ist?
-
Glauben heißt nicht wissen. Hast du es denn schon mal ausprobiert?
Eben nicht! Die Methode gibt die Anzahl der belegten Felder zurück, nicht die Anzahl der freien. Verwenden tust du sie aber unter der Annahme, dass die Anzahl der freien Felder bestimmt wird.
Das war ja genau mein Einwand, dass am Ende eben nicht das korrekte Ergebnis rauskommt.
Die von mir aufgezeigten Fehler sind Fehler im Algorithmus (bzw. in dessen Implementierung). Das Vorgehen ist grundsätzlich richtig. Wenn du mir nicht glaubst, dass meine Aussagen richtig sind, dann kann ich dir leider auch nicht weiterhelfen.
Grüße, Matthias„Gib einem Menschen einen Fisch, und er wird für einen Tag satt. Lehre ihn Fischen, und er wird ein Leben lang satt.“
“For every complex problem, there is an answer that is short, simple and wrong.”
“Pessimism is safe, but optimism is a lot faster!”
Aktuelles Coding Quiz: #17 - Wörter kreuz und quer
-
21.08.09 19:10 #12
- Registriert seit
- May 2009
- Beiträge
- 88
@Mathias Reitinger: Du hattest Recht:
Habe erneut den Code überarbeitet und nun scheint das Programm zu funktionieren, habe noch kein einziges Mal gewonnen, bin aber momentan auch sehr müde
.
Vielen Dank.
Für alle die gerne das fertige, funktionierende Programm sehen würden, hier der Quellcode:
quellcode.txt
Ähnliche Themen
-
TicTacToe bauen
Von lisali im Forum JavaAntworten: 28Letzter Beitrag: 28.06.10, 18:45 -
TicTacToe / Netzwerk
Von Nehemia im Forum JavaAntworten: 5Letzter Beitrag: 27.01.10, 10:37 -
TicTacToe gewinnstellungen
Von seji im Forum Java GrundlagenAntworten: 6Letzter Beitrag: 05.01.09, 16:56 -
TicTacToe Strategie des Computers
Von sawamin im Forum C/C++Antworten: 6Letzter Beitrag: 16.02.05, 22:41 -
[C++] TicTacToe
Von js-mueller im Forum C/C++Antworten: 5Letzter Beitrag: 20.08.03, 14:24





Zitieren


Login





