DotComVersenken

Thoosequa

Mitglied
Ahoi,

Ich arbeite mich gerade durch das Buch Java von Kopf bis Fuß. Ich habe den Code für die Deluxe Variante des DotCom Spiels nach mehrmaligem Überarbeiten haargenau (bis auf kleine Abänderungen im System.out.println-Bereich) so wie im Buch. Der Code lässt sich auch brav komplieren aber irgendetwas stimmt trotzdem nicht. Sobald ich den Code ausführe fordert mich das Spiel wie erwartet auf eine Zelle auszuwählen. Sobald ich aber etwas eingebe springt der Code nur in die nächste Zeile ohne mir ein Ergebnis zu liefern, geschweige denn eine Fehlermeldung. Es sieht so aus als würde das Programm in irgendeiner Schleife feststecken.

Anbei meine 3 Klassen SpielHelfer, DotCom und DotComVersenken.

Java:
import java.io.*;
import java.util.*;

public class SpielHelfer {
	private static final String alphabet = "abcdefg";
	private int rasterLänge = 7;
	private int rasterGröße = 49;
	private int [] raster = new int[rasterGröße];
	private int dotComAnzahl = 0;
	
	public String getBenutzereingabe(String prompt){
		String eingabeZeile = null;
		System.out.println(prompt + " ");
		try{
			BufferedReader is = new BufferedReader(new InputStreamReader(System.in));
			eingabeZeile = is.readLine();
			
			if(eingabeZeile.length() == 0){
				return null;
			}
			
			}catch (IOException e) {
				System.out.println("IOException: " + e);
			
		}
		
		return eingabeZeile.toLowerCase();
	}
	
	public ArrayList<String> platziereDotCom(int dotComGröße){
		ArrayList<String> alphaZellen = new ArrayList<String>();
		String temp = null;
		int[] koordinaten = new int[dotComGröße];
		int versuche = 0;
		boolean erfolg = false;
		int ort = 0;
		
		dotComAnzahl++;
		int inkrement = 1;
		if((dotComAnzahl % 2) ==1){
			inkrement = rasterLänge;
		}
		while(!erfolg & versuche++ <200){
			ort = (int) (Math.random() * rasterGröße);
			int x = 0;
			erfolg = true;
			while (erfolg && x <dotComGröße){
				if (raster[ort] == 0){
					koordinaten[x++] = ort;
					ort += inkrement;
				if (ort >= rasterGröße){
					erfolg = false;
					}
				if (x>0 & (ort % rasterLänge == 0)){
						erfolg = false;
						
					}else{ erfolg = false; 
					
					}
				}
			}
		}
		
		int x = 0;
		int zeile = 0;
		int spalte = 0;
		
		while(x <dotComGröße){
			raster[koordinaten[x]] = 1;
			zeile = (int) (koordinaten[x] / rasterLänge);
			spalte = koordinaten[x] % rasterLänge;
			temp = String.valueOf(alphabet.charAt(spalte));
			
			alphaZellen.add(temp.concat(Integer.toString(zeile)));
			x++;
		}
		
		return alphaZellen;
		
	}
}

Java:
import java.util.ArrayList;

public class dotComVersenken {
	
	private SpielHelfer helfer = new SpielHelfer();
	private ArrayList<DotCom> dotComListe = new ArrayList<DotCom>();
	private int anzahlVersuche = 0;
	
	public void spielEinrichten(){
		DotCom eins = new DotCom();
		eins.setName("Haustiere.com");
		DotCom zwei = new DotCom();
		zwei.setName("BioWare.com");
		DotCom drei = new DotCom();
		drei.setName("FragMich.com");
		dotComListe.add(eins);
		dotComListe.add(zwei);
		dotComListe.add(drei);
		
		System.out.println("Ihre Aufgabe ist es 3 Dot-Coms zu versenken.");
		System.out.println("Haustiere.com, BioWare.comm FragMich.com");
		System.out.println("Versuchen Sie es mit so wenig Versuchen wie möglich, Viel Glück");
		
		for(DotCom aktuellesDotCom : dotComListe){
			ArrayList<String> neuerOrt = helfer.platziereDotCom(3);
			aktuellesDotCom.setZellorte(neuerOrt);
		}
		
	}
	
	public void beginneSpiel(){
		while(!dotComListe.isEmpty()){
			String rateversuch = helfer.getBenutzereingabe("Geben Sie einen Rateversuch ein");
			prüfeRateversuch(rateversuch);
		}
		
		beendeSpiel();
	}
	
	public void prüfeRateversuch(String rateversuch){
		anzahlVersuche++;
		String ergebnis = "Vorbei!";
		
		for(DotCom aktuellesDotCom: dotComListe){
			ergebnis = aktuellesDotCom.prüfDich(rateversuch);
			if(ergebnis.equals("Treffer")){ 
					break;
			}
			if(ergebnis.equals("Versenkt")){
				dotComListe.remove(aktuellesDotCom);
					break;
			}
		}
		System.out.println(ergebnis);
		
	}
	
	public void beendeSpiel(){
		System.out.println("Alle Dot-Coms sind versenkt!");
		if(anzahlVersuche <= 18){
			System.out.println("Sie haben nur "+ anzahlVersuche +" Versuche benötigt");
		}else{
			System.out.println("Hat ja lange gedauert."+"Nach "+anzahlVersuche+" haben Sie es geschafft.");
		}
	}
	
	public static void main(String args[]){
		dotComVersenken spiel = new dotComVersenken();
		spiel.spielEinrichten();
		spiel.beginneSpiel();
	}
}

Java:
import java.util.ArrayList;

public class DotCom {
		
	private ArrayList<String> zellorte;
	private String name;
	
	public void setZellorte(ArrayList<String> orte){
		zellorte = orte;
	}
	
	public void setName(String n){
		name = n;
	}
	
	public String prüfDich(String benutzereingabe){
		
		String ergebnis = "Vorbei";
		
		int index = zellorte.indexOf(benutzereingabe);
			
			if (index >= 0) {
				zellorte.remove(index);
		if(zellorte.isEmpty()){
		ergebnis = "Versenkt";
		System.out.println("Sie haben " + name + " versenkt.");
	} else { 
		ergebnis = "Treffer"; 
		} //if
	
	} //if
	
	return ergebnis;
	}
}

'Tschuldige für die lange Codewüste und damit den ellenlangen Post, gäbe es eine Möglichkeit das irgendwie zu kürzen hätt ich's getan :/

Danke für alle Antworten schonmal im Voraus! :)
 
Zuletzt bearbeitet von einem Moderator:

JCODA

Top Contributor
Eine Lösung kann ich dir nicht liefern, aber will ich auch garnicht, ich will dir aber eine Möglichkeit zeigen, wie du's selbst knacken kannst:

Du merkst, irgendwo hast dir ne endlosschleife eingefangen, also fang damit an, System.out.println zu "verteilen"

Java:
System.out.println("Ihre Aufgabe ist es 3 Dot-Coms zu versenken.");
		System.out.println("Haustiere.com, BioWare.comm FragMich.com");
		System.out
				.println("Versuchen Sie es mit so wenig Versuchen wie möglich, Viel Glück");
		System.out.println("eins");
		for (DotCom aktuellesDotCom : dotComListe) {
			System.out.println("zwei");
			ArrayList<String> neuerOrt = helfer.platziereDotCom(3);
			System.out.println("drei");
			aktuellesDotCom.setZellorte(neuerOrt);
			System.out.println("vier");
		}
		System.out.println("fünf");

Das machst du so lange bis du die endlosschleife findest, bzw ab und zu kannst dir auch Variablen so anzeigen lassen und debuggen ;)
 

Thoosequa

Mitglied
Danke für den Hinweis, das scheint mir eine ausgetüftelte Methode zu sein Bugs zu finden. Ich setz mich gleich ran und meld mich wieder wenn ich mehr rausgefunden hab :D
 
Zuletzt bearbeitet:

renwal

Aktives Mitglied
Ich würde an deiner Stelle in den Debug-Modus gehen und das Programm unterbrechen, wenn du merkst, dass die Ausführung der Dauerschleife läuft. Dann siehst du, in welcher Zeile dein Programm hängt.

LG renwal
 

Jodo

Aktives Mitglied
System.out.println() is immer top um Bugs zu finden, grade wenn du denkst das Code übergangen oder gar nicht ausgeführt wird.
Ansonsten kannst du dich auch mal mit Debugging und Haltepunkten (breakpoints) auseinandersetzen.
Anfangs fand ich das schwer mich da zurecht zu finden, aber wenn man einmal weiß wie's funktioniert und paar mal damit gearbeitet hat hilft es sehr sehr gut :)
 

Thoosequa

Mitglied
Der Fehler steckt gleich am Anfang. Aus irgendeinem mir nicht bekannten Grund führt das spiel Objekt nicht die beginneSpiel(); Methode aus. Aber wieso, ist doch alles 1:1 wie im Buch. Genaugenommen hängt sich das Ding direkt nach der spielEinrichten(); Methode auf.

Randnotiz (vielleicht hängts damit zusammen) seit etwa einer Stunde wird Eclipse beim compilen schrecklich langsam und hängt sich sogar manchmal auf.
 

pl4gu33

Top Contributor
Randnotiz (vielleicht hängts damit zusammen) seit etwa einer Stunde wird Eclipse beim compilen schrecklich langsam und hängt sich sogar manchmal auf.

Beendest du dein Programm auch immer wieder oder hast du jetzt 1000 Programme laufen? :)

geh mal in den Task Manager und schau mal nach JAVAW.exe, hast du da welche drin beende die mal alle :)

bzw. Eclipse neustart sollte auch schon helfen :D
 

JCODA

Top Contributor
Der Fehler steckt gleich am Anfang. Aus irgendeinem mir nicht bekannten Grund führt das spiel Objekt nicht die beginneSpiel(); Methode aus. Aber wieso, ist doch alles 1:1 wie im Buch. Genaugenommen hängt sich das Ding direkt nach der spielEinrichten(); Methode auf.

Naja, bei mir sogar innerhalb dieser Spiel einrichten Methode, mit genau dem Code den ich oben gepostet hab, erhalte ich folgende Ausgabe:

Code:
Ihre Aufgabe ist es 3 Dot-Coms zu versenken.
Haustiere.com, BioWare.comm FragMich.com
Versuchen Sie es mit so wenig Versuchen wie möglich, Viel Glück
eins
zwei
drei
vier
zwei

Randnotiz (vielleicht hängts damit zusammen) seit etwa einer Stunde wird Eclipse beim compilen schrecklich langsam und hängt sich sogar manchmal auf.

Öffne deinen TaskManager und schau deine ProzessorAuslastung an, ich vermute du hast ein paar Instanzen des Programmes auf, die Endlosschleifen enthalten ... Dein Prozessor führt aber brav diese Endlosschleifen aus und führen so zu einer hohen CPU Last.
 

Thoosequa

Mitglied
Ju, ich hatte 4 javaw Prozesse offen mit jeweils 8000KB. CPU auf Konstanten 100%, sobald ich Eclipse zugemacht hatte fiel sofort alles wieder in den normalen Bereich.
Also ist der Hund doch im Buch begraben?
 

JCODA

Top Contributor
Ich tippe immernoch auf einen Tippfehler deinerseits ... finde einfach die Endlosschleife und vergleiche alles was im Schleifenkopf steht bzw welche Variablen in der Schleife benutzt werden.
 

Thoosequa

Mitglied
Jawoll. Ich war's. In der Spielhelfer Klasse hab ich eine Klammer falsch gesetzt. :oops: Offensichtlich reichte die aus um 4 Prozesse zu öffnen und mein Eclipse zu crashen, sowie 100% der CPU zu beanspruchen. Danke für den tollen Ratschlag mit System.out.print(); nochmal. Der hat mir sehr geholfen :D
 

Thoosequa

Mitglied
Aber natürlich hier die gesamte Klasse:

Java:
import java.io.*;
import java.util.*;

public class SpielHelfer {
	private static final String alphabet = "abcdefg";
	private int rasterLänge = 7;
	private int rasterGröße = 49;
	private int [] raster = new int[rasterGröße];
	private int dotComAnzahl = 0;
	
	public String getBenutzereingabe(String prompt){
		String eingabeZeile = null;
		System.out.println(prompt + " ");
		try{
			BufferedReader is = new BufferedReader(new InputStreamReader(System.in));
			eingabeZeile = is.readLine();
			
			if(eingabeZeile.length() == 0){
				return null;
			}
			
			}catch (IOException e) {
				System.out.println("IOException: " + e);
			
		}
		
		return eingabeZeile.toLowerCase();
	}
	
	public ArrayList<String> platziereDotCom(int dotComGröße){
		ArrayList<String> alphaZellen = new ArrayList<String>();
		String temp = null;
		int[] koordinaten = new int[dotComGröße];
		int versuche = 0;
		boolean erfolg = false;
		int ort = 0;
		
		dotComAnzahl++;
		int inkrement = 1;
		if((dotComAnzahl % 2) == 1){
			inkrement = rasterLänge;
		}
		while(!erfolg & versuche++ < 200){
			ort = (int) (Math.random() * rasterGröße);
			int x = 0;
			erfolg = true;
			while (erfolg && x < dotComGröße){
				if (raster[ort] == 0){
					koordinaten[x++] = ort;
					ort += inkrement;
				if (ort >= rasterGröße){
					erfolg = false;
					}
				if (x>0 & (ort % rasterLänge == 0)){
						erfolg = false;
						
					}
				
				}else{ erfolg = false; 
					
					}
				}
			}
		
		
		int x = 0;
		int zeile = 0;
		int spalte = 0;
		
		while(x <dotComGröße){
			raster[koordinaten[x]] = 1;
			zeile = (int) (koordinaten[x] / rasterLänge);
			spalte = koordinaten[x] % rasterLänge;
			temp = String.valueOf(alphabet.charAt(spalte));
			
			alphaZellen.add(temp.concat(Integer.toString(zeile)));
			x++;
		}
		
		return alphaZellen;
		
	}
}

Hier der editierte Teil:

Im original sahs so aus:

Java:
 //schrecklich viel code     
           if (x>0 & (ort % rasterLänge == 0)){
                        erfolg = false;
                        
                    }else{ erfolg = false; 
                    
                    }
                }
            }
        }

Nach der Schönheits Kur:

Java:
 //schrecklich viel Code
if (x>0 & (ort % rasterLänge == 0)){
						erfolg = false;
						
					}
				
				}else{ erfolg = false; 
					
					}
				}
			}
 

Mujahiddin

Top Contributor
Ich würde übrigens empfehlen, bei ausführlichem Debuggen auf Logger umzusteigen. Ich habe dafür einen Logger geschrieben, der ziemlich nützlich ist. Damit kann man sehr gut debuggen. Man kann ihn natürlich konfigurieren. Ich würde diese Methode irgendwo in die Applikation schreiben und jeder Klasse einen [c]static[/c] (wichtig!) Logger zuweisen. Bei jeder logbaren Sache dann einfach mit dem Level, den man für passend erachtet, loggen. Der momentane Thread wird erwähnt, weil das manchmal auch wichtig ist (z.B. Swing, EDT etc.):

Java:
private static final SimpleDateFormat	extended	= new SimpleDateFormat( "dd MMM yyyy (HH:mm:ss) zz" );

public static java.util.logging.Logger initLogger(final String name) {
	final java.util.logging.Logger logger = java.util.logging.Logger.getLogger( name );
	try {
		
		Handler ch = new ConsoleHandler();
		logger.addHandler( ch );
		
		logger.setLevel( Level.ALL ); // Level selbst setzen
		
		logger.setUseParentHandlers( false );
		
		final java.util.logging.SimpleFormatter formatter = new SimpleFormatter() {
			
			@Override
			public synchronized String format(final LogRecord record) {
				StackTraceElement[] trace = new Throwable().getStackTrace();
				String clickable = "(" + trace[ 7 ].getFileName() + ":" + trace[ 7 ].getLineNumber() + ") "; // Clickable text in Console.
				for( int i = 8; i < trace.length; i++ ) // 0 - 6 is the logging trace, 7 - x is the trace until log method was called
					if( trace[ i ].getFileName() == null )
						continue;
					else
						clickable = "(" + trace[ i ].getFileName() + ":" + trace[ i ].getLineNumber() + ") -> " + clickable;
				
				final String time = "<" + extended.format( new Date( record.getMillis() ) ) + "> ";
				
				StringBuilder level = new StringBuilder("[" + record.getLevel() + "] ");
				while( level.length() < 15 ) // extend for tabby display
					level.append(" ");
				
				StringBuilder name = new StringBuilder(record.getLoggerName()).append(": ");
				while( name.length() < 15 ) // extend for tabby display
					name.append(" ");
				
				String thread = Thread.currentThread().getName();
				if( thread.length() > 18 ) // trim if too long
					thread = thread.substring( 0, 16 ) + "..."; 
				else {
					StringBuilder sb = new StringBuilder(thread);
					while( sb.length() < 18 ) // extend for tabby display
						sb.append(" ");
					thread = sb.insert( 0, "Thread " ).toString();
				}
				
				final String message = "\"" + record.getMessage() + "\" ";
				
				return level + time + thread + name + clickable + message + "\n";
			}
		};
		ch.setFormatter( formatter );
		ch.setLevel( Level.ALL );
	} catch( final SecurityException e ) {
		e.printStackTrace();
	}
	return logger;
}

Der StackTrace sollte in Eclipse klickbar sein. Man kann die einzelnen Variablen in der return-Anweisung untereinander vertauschen. Übrigens sollte die Logger-Namen kompakt halten.

Liebe Grüße!
 
Zuletzt bearbeitet:
B

bone2

Gast
Java:
        while (erfolg && x <dotComGröße){
            if (raster[ort] == 0){
                koordinaten[x++] = ort;
                ort += inkrement;
                
                if (ort >= rasterGröße){
                    erfolg = false;
                }
                
                if (x>0 & (ort % rasterLänge == 0)){
                    erfolg = false;
                }
                else{
                    erfolg = false; 
                }
            }
        }
Java:
        while (erfolg && x < dotComGröße){
            if (raster[ort] == 0){
                koordinaten[x++] = ort;
                ort += inkrement;

                if (ort >= rasterGröße){
                    erfolg = false;
                }
                
                if (x>0 & (ort % rasterLänge == 0)){
                    erfolg = false;
                }
            }
            else{
                erfolg = false; 
            }
        }

formatieren die in dem buch auch so grausam uneinheitlich und falsch eingerückt?
wenn nicht: formatiere vernünftig, der unterschied fällt sofort ins auge
 

Thoosequa

Mitglied
"Formatiere vernünftig". Hm naja, Formatierungskonventionen kamen mir in keinem Kapitel bisher unter. Ich formatier halt so, wie es für mich am angenehmsten zum Lesen ist. Falls es da irgendwelche Richtlinien oder Konventionen gibt bitte mir dies mitzuteilen :)
 
I

Italostylo

Gast
Du hast eine } falsch gesetzt in der spielhelfer klasse!


Java:
while(!erfolg & versuche++ <200){
            ort = (int) (Math.random() * rasterGröße);
            int x = 0;
            erfolg = true;
            while (erfolg && x <dotComGröße){
                if (raster[ort] == 0){
                    koordinaten[x++] = ort;
                    ort += inkrement;
                
                    if (ort >= rasterGröße){
                          erfolg = false;
                    }
                
                    if (x>0 & (ort % rasterLänge == 0)){
                        erfolg = false;    
                    }
                 } // Hier vor dem else muss noch eine klammer hin! Kontrolliere einfach noch einmal den teil vom quelltext dann wirst du den fehler schon selbst bemerken
                else{ erfolg = false; 
                    
                    }
                }
            }
        }
 

Oben