TicTacToe: Spieler kann nicht gewinnen
-
Und ich soll mich jetzt mit deinem Sourcecode beschäftigen und den Fehler für dich eingrenzen, oder?
-
Lass dir in hasWon mal die Werte ausgeben, die du als Indices benutzt.
-
@all: Meine Frage ist ja, warum das Programm nicht immer auf ein gewonnenes Spiel reagiert, wenn er sollte, sondern nur manchmal.
Der wichtigste Code ist die Abspeicherung und Verwertung der Variablen, wo der Spieler gesetzt hat.
void drawToken(Graphics g, int pos_x, int pos_y, String token){ if(placeX(pos_x) && placeY(pos_y)){ // Wenn in ein gültiges Feld geklickt wurde... if (token.equals(Main.cross)) { drawCross(g); playedToken = Main.cross; playerOnField[lastPlaced] = Main.cross; //Speichern wo der Spieler gespielt hat playerCross.hasWon("Kreuz"); //Hat der Spieler gewonnen? } else if(token.equals(Main.circel)){ drawCircel(g); playedToken = Main.circel; playerOnField[lastPlaced] = Main.circel; playerCircel.hasWon("Kreis"); } } }
//Ist ein Feld schon besetzt? Falls ja, darf nicht gezeichnet werden boolean occupyField(int pos_x, int pos_y){ if(pos_x <=110 && pos_x >= 60 && pos_y <= 120 && pos_y >= 70 && !field[0]){ field[0] = true; //Als besetzt markieren lastPlaced = 0; //Speichern wo der Spieler gesetzt hat return false; //Feld nicht besetzt => Es kann gezeichnet werden } else if(pos_x <= 160 && pos_x >= 110 && pos_y <= 120 && pos_y >= 70 && !field[1]){ field[1] = true; lastPlaced = 1; return false; } else if(pos_x <= 210 && pos_x >= 160 && pos_y <= 120 && pos_y >= 70 && !field[2]){ field[2] = true; lastPlaced = 2; return false; } else if(pos_x <= 110 && pos_x >= 60 && pos_y <= 170 && pos_y >= 120 && !field[3]){ field[3] = true; lastPlaced = 3; return false; } else if(pos_x <= 160 && pos_x >= 110 && pos_y <= 170 && pos_y >= 120 && !field[4]){ field[4] = true; lastPlaced = 4; return false; } else if(pos_x <= 210 && pos_x >= 160 && pos_y <= 170 && pos_y >= 120 && !field[5]){ field[5] = true; lastPlaced = 5; return false; } else if(pos_x <= 110 && pos_x >= 60 && pos_y <= 220 && pos_y >= 170 && !field[6]){ field[6] = true; lastPlaced = 6; return false; } else if(pos_x <= 160 && pos_x >= 110 && pos_y <= 220 && pos_y >= 170 && !field[7]){ field[7] = true; lastPlaced = 7; return false; } else if(pos_x <= 210 && pos_x >= 160 && pos_y <= 220 && pos_y >= 170 && !field[8]){ field[8] = true; lastPlaced = 8; return false; } else return true; //Feld schon belegt oder nicht vorhanden }
import javax.swing.*; public class Player { void hasWon(String player){ System.out.println(Spielfeld.playerOnField[0].replaceAll("\\n", "")); for(int i=1; i <= Spielfeld.playerOnField.length/3; i+=3){ if(Spielfeld.playerOnField[i].equals(Main.circel) && Spielfeld.playerOnField[i+3].equals(Main.circel) && Spielfeld.playerOnField[i+6].equals(Main.circel)){ JOptionPane.showMessageDialog(Main.frame, player + " hat gewonnen"); } } for(int i=0; i < Spielfeld.playerOnField.length/3; i+=3){ if(Spielfeld.playerOnField[i].equals(Main.circel) && Spielfeld.playerOnField[i+1].equals(Main.circel) && Spielfeld.playerOnField[i+2].equals(Main.circel)){ JOptionPane.showMessageDialog(Main.frame, player + " hat gewonnen"); } } } }
MFK schrieb:
Lass dir in hasWon mal die Werte ausgeben, die du als Indices benutzt.
Das komische ist, wenn ich mir z.B. Spielfeld.playerOnField[0] per System.out.println ausgeben will in der Methode hasWon(), und zuvor z.B. in dem Feld 7 und 5 geklickt habe, dann erscheint die Ausgabe auch in der zweiten Zeile.
Ich habe auch schon trim() versucht, aber die Ausgabe ist immer
Ausgabenzeile = zuvor x mal geklickt
Kann es vielleicht daran liegen, dass die Verwertung oft nicht funktioniert?
Kompiliert das Spiel am Besten selbst, vielleicht fällt euch irgendetwas sonderbares auf.
Liebe Grüße
Real
-
Real schrieb:
Das komische ist, wenn ich mir z.B. Spielfeld.playerOnField[0] per System.out.println ausgeben will in der Methode hasWon(), und zuvor z.B. in dem Feld 7 und 5 geklickt habe, dann erscheint die Ausgabe auch in der zweiten Zeile.
Du hast mich nicht verstanden.
Gib in der ersten Schleife in hasWon i, i+3 und i+6 aus.
-
http://mitglied.lycos.de/masterchan/TicTacToe.PNG
Ausgabe der ersten Schleife:
cross
circel
crosscircel
crosscircel
crossLiebe Grüße
Real
-
Drücke ich mich irgendwie unklar aus? Du sollst i ausgeben, nicht Spielfeld.playerOnField[i].
-
MFK schrieb:
Drücke ich mich irgendwie unklar aus? Du sollst i ausgeben, nicht Spielfeld.playerOnField[i].
Achso, gab für mich irgendwie keinen Sinn, weil man das im Kopf ausrechnen kann, aber das Ergebnis ist trotzdem überraschend.
1
13
16
1
13
16
1
13
16
1
13
16
1
13
16
1
13
16Liebe Grüße
Real
-
Das ist immer noch nicht, was ich meinte. Kannst du mal den Code zeigen, den du für die Ausgabe benutzt?
-
import javax.swing.*; public class Player { void hasWon(String player){ for(int i=1; i <= Spielfeld.playerOnField.length/3; i+=3){ System.out.println(i+"\n"+ i+3+"\n"+ i+6); if(Spielfeld.playerOnField[i].equals(Main.circel) && Spielfeld.playerOnField[i+3].equals(Main.circel) && Spielfeld.playerOnField[i+6].equals(Main.circel)){ JOptionPane.showMessageDialog(Main.frame, player + " hat gewonnen"); } } for(int i=0; i < Spielfeld.playerOnField.length/3; i+=3){ if(Spielfeld.playerOnField[i].equals(Main.circel) && Spielfeld.playerOnField[i+1].equals(Main.circel) && Spielfeld.playerOnField[i+2].equals(Main.circel)){ JOptionPane.showMessageDialog(Main.frame, player + " hat gewonnen"); } } } }
Ich habe übrigens den kompletten Quellcode weiter oben gepostet, den du kompilieren kannst.
Liebe Grüße
Real
-
Ändere das mal in
Real schrieb:
System.out.println(i+"\n"+ (i+3)+"\n"+ (i+6));
Eigentlich solltest du 036, 147 und 258 testen. Du testest nur 147.
-
Von was redest du?
036, 147 und 258
-
Bitte hasWon() durch folgedes ersetzen:
void hasWon(String player, String playerName){ for(int i=1; i <= Spielfeld.playerOnField.length/3; i+=3){ System.out.println(i+"\n"+ i+3+"\n"+ i+6); if(Spielfeld.playerOnField[i].equals(player) && Spielfeld.playerOnField[i+3].equals(player) && Spielfeld.playerOnField[i+6].equals(player)){ JOptionPane.showMessageDialog(Main.frame, playerName + " hat gewonnen"); } } for(int i=0; i < Spielfeld.playerOnField.length/3; i+=3){ if(Spielfeld.playerOnField[i].equals(player) && Spielfeld.playerOnField[i+1].equals(player) && Spielfeld.playerOnField[i+2].equals(player)){ JOptionPane.showMessageDialog(Main.frame, playerName + " hat gewonnen"); } } }
drawToken durch das:
void drawToken(Graphics g, int pos_x, int pos_y, String token){ if(placeX(pos_x) && placeY(pos_y)){ // Wenn in ein gültiges Feld geklickt wurde... if (token.equals(Main.cross)) { drawCross(g); playedToken = Main.cross; playerOnField[lastPlaced] = Main.cross; playerCross.hasWon(Main.cross, "Kreuz"); } else if(token.equals(Main.circel)){ drawCircel(g); playedToken = Main.circel; playerOnField[lastPlaced] = Main.circel; playerCircel.hasWon(Main.circel, "Kreis"); } } }
Jetzt kann auch Kreuz ab und zu gewinnen. Ansonsten ist das Problem gleich. Man kann nicht immer gewinnen.
Wenn ich die Schleifen in hasWon() durch explizite if-Anweisungen ersetze, dann klappt das Bestens!
if(Spielfeld.playerOnField[3].equals(player) && Spielfeld.playerOnField[4].equals(player) && Spielfeld.playerOnField[5].equals(player)){ JOptionPane.showMessageDialog(Main.frame, playerName + " hat gewonnen"); } if(Spielfeld.playerOnField[6].equals(player) && Spielfeld.playerOnField[7].equals(player) && Spielfeld.playerOnField[8].equals(player)){ JOptionPane.showMessageDialog(Main.frame, playerName + " hat gewonnen"); }
Es muss also an der Schleife etwas falsch sein.
Liebe Grüße
Real
-
Real schrieb:
Es muss also an der Schleife etwas falsch sein.
Darauf will ich die ganze Zeit hinaus.
Wenn du die Ausgabe so machst, wie ich es geschrieben habe, siehst du auch die tatsächlichen Indices.
Real schrieb:
Von was redest du?
036, 147 und 258Die erste Schleife in hasWon hat die Aufgabe, die Spalten zu prüfen, oder etwa nicht? Also zuerst die Felder 0, 3 und 6, dann 1, 4 und 7, und schließlich 2, 5 und 8, denn die liegen jeweils untereinander.
Du hast erkannt, dass du das mit i, i+3 und i+6 erreichen kannst. Aber aus irgendeinem Grund fängt deine Schleife bei 1 an (sie müsste bei 0 anfangen) und zählt i immer um 3 hoch (richtig wäre 1).
-
Hey, danke!
Vertikal geht das jetzt wunderbar, nur horinzotal geht die letzte Zeile nicht!for(int i=0; i <= 3; i+=3){ System.out.println(i+"\n"+ (i+1)+"\n"+ (i+2)); if(Spielfeld.playerOnField[i].equals(player) && Spielfeld.playerOnField[(i+1)].equals(player) && Spielfeld.playerOnField[(i+2)].equals(player)){ JOptionPane.showMessageDialog(Main.frame, playerName + " hat gewonnen"); } }
Ausgabe:
0
1
23
4
5Selbst wenn ich i <= 4 hinschreibe, macht es nur 2 Durchgänge bzw. gibt dasselbe aus.
Liebe Grüße
Real
-
So muss es heißen:
void hasWon(String player, String playerName){ if(Spielfeld.playerOnField[0].equals(player) && Spielfeld.playerOnField[4].equals(player) && Spielfeld.playerOnField[8].equals(player)){ JOptionPane.showMessageDialog(Main.frame, playerName + " hat gewonnen"); } else if(Spielfeld.playerOnField[2].equals(player) && Spielfeld.playerOnField[4].equals(player) && Spielfeld.playerOnField[6].equals(player)){ JOptionPane.showMessageDialog(Main.frame, playerName + " hat gewonnen"); } for(int i=0; i <= Spielfeld.playerOnField.length/3; i++){ if(Spielfeld.playerOnField[i].equals(player) && Spielfeld.playerOnField[(i+3)].equals(player) && Spielfeld.playerOnField[(i+6)].equals(player)){ JOptionPane.showMessageDialog(Main.frame, playerName + " hat gewonnen"); } } for(int i=0; i < Spielfeld.playerOnField.length; i+=3){ System.out.println(i+"\n"+ (i+1)+"\n"+ (i+2)); if(Spielfeld.playerOnField[i].equals(player) && Spielfeld.playerOnField[(i+1)].equals(player) && Spielfeld.playerOnField[(i+2)].equals(player)){ JOptionPane.showMessageDialog(Main.frame, playerName + " hat gewonnen"); } } }
Jedoch bekomme ich einen Stackoverflow, wenn ich das hier spiele:
http://mitglied.lycos.de/masterchan/Stackoverflow.PNG
Grund: Es können beide Spieler in dieser Situation gewinnen, aber normalerweise dürften nicht beide Player-Instanzen "gleichzeitig" aufgerufen werden, da eine if-Anweisung dies verhindern (müsste).
void drawToken(Graphics g, int pos_x, int pos_y, String token){ if(placeX(pos_x) && placeY(pos_y)){ // Wenn in ein gültiges Feld geklickt wurde... if (token.equals(Main.cross)) { drawCross(g); playedToken = Main.cross; playerOnField[lastPlaced] = Main.cross; playerCross.hasWon(Main.cross, "Kreuz"); //Hat Kreuz gewonnen? } else if(token.equals(Main.circel)){ drawCircel(g); playedToken = Main.circel; playerOnField[lastPlaced] = Main.circel; playerCircel.hasWon(Main.circel, "Kreis"); //Hat Kreis gewonnen? } } }
Liebe Grüße
Real
-
Hast du ein wenig mehr Informationen zu dem Stapelüberlauf? Funktion? Stacktrace?
-
Öhm, hat sich irgendwie erledigt.
Liebe Grüße
Real