# Boulder Dash nachbauen



## babuschka (21. Dez 2011)

Hallo, liebe Leute!


Ihr wundert Euch bestimmt, wieso ich diese Frage als Anfängerthema einordne, aber ich bin tatsächlich Java-Anfänger (erst sei ca. 2,5 Monaten mit Java beschäftigt) und wurde gleich mit dieser Aufgabe konfrontiert, die mir sehr schwer erscheint, darum hoffe ich auf Eure Hilfe:



> "In der folgenden Aufgabe sollt Ihr das Spiel Boulder Dash nachbauen. Boulder Dash ist ein Klassiker aus den 80-er Jahren. [...] Das Ziel des Spiels ist es, unter der Erde nach Diamanten zu suchen. Dazu muss der Spieler sich durch die Erde graben und dabei Monstern und fallenden Steinen ausweichen.
> 
> Es gibt folgende Spielelemente:
> 
> ...




Hier das Interface Element, das uns bereitgestellt ist:


```
/**
 *
 */
public interface Element {

    /**
     * Every Element is identified by a special char.
     * E.g. If this Element is Monster the method would return 'M'
     *
     * Valid return values are:
     * 'P' Player
     *
     * ' ' Blank (empty cell)
     *
     * 'W' Wall
     *
     * 'S' Soil
     *
     * 'B' Boulder
     *
     * 'M' Monster
     *
     * 'D' Diamond
     *
     * 'G' Goal
     *
     * @return The char that identifies this Element.
     */
    public char getChar();

    /**
     * Perform one turn.
     */
    public void performTurn();

}
```


So, das ist die Aufgabe (die erste von dreien, aber die anderen beiden Aufgaben lasse ich weg, denn es erscheint mir an dieser Stelle utopisch, die restlichen Aufgaben auch noch hinzubekommen).


Edit1:

Was die Hierachie angeht, so wäre meine Idee, daß man eine Superklasse für Spielfigur und Monster schreibt (die kann man vielleicht "Teilnehmer" nennen) und eine Superklasse für Stein, Erde, Wand und Diamant (die kann man vielleicht "Hindernis" nennen).

Aber wie die konkreten Implementierungen aussehen, da habe ich noch keine wirkliche Idee.


----------



## SlaterB (21. Dez 2011)

verschoben nach Hausaufgaben, extra erwähnt da du von 'wieso ich diese Frage als Anfängerthema einordne' sprichst,



> wo ich anfangen könnte. 

erstelle eine Klasse Wand


----------



## Gast2 (21. Dez 2011)

Naja, anfangen solltest du mit:


> Implementiert die oben beschriebenen Spielelemente als Klassen. Alle Elemente sollten das Interface Element, welches vorgegeben ist (s.u.), implementieren.


Was die zwei Methoden in den jeweiligen Klassen machen ist doch sehr gut beschrieben.


----------



## babuschka (21. Dez 2011)

Zunächst soll man sich ja Gedanken über die Hierarchie machen.

(Da habe ich in meinem ersten Beitrag (s. Edit1) meine Idee gepostet.)


Ansonsten beherzige ich mal die Tipps und beginne jetzt einfach mal mit der Implementierung der Klasse Wand:


```
public class Wand implements Element{
public char getChar(){
return 'W';
}
public void performTurn(){
}
}
```

Also das ist meine erste Idee.


----------



## stikio (21. Dez 2011)

:toll:


----------



## Gast2 (21. Dez 2011)

> Was die Hierachie angeht, so wäre meine Idee, daß man eine Superklasse für Spielfigur und Monster schreibt (die kann man vielleicht "Teilnehmer" nennen) und eine Superklasse für Stein, Erde, Wand und Diamant (die kann man vielleicht "Hindernis" nennen).


Klingt doch gut.


----------



## babuschka (21. Dez 2011)

Wie könnte denn die Superklasse "Hindernis" aussehen?

Dafür müsste ich mir irgendwie überlegen, was alle Hindernisse (Stein, Diamant, Wand, Erde) gemeinsam haben (und was speziell in den Subklassen dann spezialisiert/ ergänzt werden muss). Soweit ist mir das klar.

Aber ich sehe keine Attribute oder Methoden, die allen gemeinsam wären und die man in eine Superklasse packen könnte.




Edit2:

Was sind überhaupt die Attribute der Hindernisse?

x- und y-Koordinaten?

(Die hätten natürlich alle Hindernisse und ließen sich in die Superklasse packen.)


----------



## Gast2 (21. Dez 2011)

Alle Hindernisse haben eine Position und können nicht bewegt werden.


----------



## babuschka (21. Dez 2011)

Okay, dann wäre meine Superklasse "Hindernis":


```
public class Hindernis implements Element{

double x_position;
double y_position;

public Hindernis(double x_position, double y_position){

this.x_position=x_position;
this.y_position=y_position;
}

public void performTurn(){
}

}
```

Und meine Subklasse "Wand" sieht dann so aus:


```
public class Wand extends Hindernis implements Element{

public Wand(double x_position, double y_position){

super(x_position, y_position);
}

public char getChar(){
return 'W';
}

}
```

Was sagt ihr dazu?


----------



## langhaar! (21. Dez 2011)

Aus der Augabe geht es meines Erachtens nicht wirklich hervor, aber wenn du dir Boulder Dash mal angesehen hast, stellst du fest, dass alle Spielelemente so in einem Raster angeordnet sind, dass sie sich nicht überlappen können und alle die gleiche Größe haben.

Einfacher gesagt: die Position ist nicht double sondern int.


----------



## babuschka (21. Dez 2011)

Sind die Subklassen Erde, Diamant und Stein dann analog?

Oder muss man da Extra-Dinge noch berücksichtigen, also z.B. zusätzliche Methoden einbauen?


----------



## langhaar! (21. Dez 2011)

Natürlich haben die Elemente verschiedenen Möglichkeiten. Z.B. kann ein Stein fallen.
Jetzt ist eine Frage der Modellierung, ob du sagst, Erde kann verschwinden oder die Spielfigur entfernt die Erde. Mit dem Fallen analog. Ist das Fallen eine Tätigkeit des Steins oder lässt die Spielumgebung die Steine fallen? Demensprechend kommst du auf verschiedene Modellierungen (unterschiedliche Klassen, bzw. andere Verteilung der Methoden).

Ob du also bei den Elementen noch Methoden ergänzen musst, kann nicht so pauschal beantwortet werden.


----------



## babuschka (21. Dez 2011)

Ich würde es so verstehen, daß ich in die Klasse Erde eine Methode schreiben, die dafür sorgt, daß die Erde verschwindet. Ist die Erde dann wirklich weg oder wird sie woanders hin verschoben?


Wie könnte man das Verschwinden der Erde denn umsetzen?


Wie sind die Koordinaten einer verschwunden Erde?---



Meine Idee wäre sowas:


```
public class Erde extends Hindernis implements Element{

public Erde(int x_position, int y_position){
super(x_position, y_position);
}

public char getChar(){
return 'E';
}

public void performTurn(){
this.x_position=0;
this.y_position=0;

}

}
```



Aber das hieße ja, daß man jeder entfernten Erde die Koordninaten (0,0) zuodnet und das kann's ja auch irgendwied nicht sein...


----------



## langhaar! (21. Dez 2011)

java_ hat gesagt.:


> Aber das hieße ja, daß man jeder entfernten Erde die Koordninaten (0,0) zuodnet und das kann's ja auch irgendwied nicht sein...



Sehr guter Einwand. Wäre möglich (wobei -1,-1 besser wäre) aber unschön.

Die Erde muss irgendwo enthalten sein.
Da bietet sich eine Klasse 'Spielfeld' an.
Diese Klasse enthält sämtliche Elemente und ist auch dafür zuständig, ihre Elemente zu setzen oder zu entfernen bzw. darauf zu reagieren, was passiert, wenn der Spieler an Position x,y ist.


----------



## babuschka (21. Dez 2011)

Diese Klasse "Spielfeld" muss in Aufgabe 2 geschrieben werden.


Man würde also in der Klasse "Spielfeld" eine ArrayList elemente mit allen Elementen anlegen (von daher muss man wohl noch eine Superklasse "Elemente" für alle Elemente schreiben).

Für das Entfernen eines Elements würde ich eine Methode in die (noch zu erstellende) Super-Klasse "Elemente" einbauen, die sowas macht:


```
public void deleteElement(Element element){

element.getElement(indexOf(element)).remove(element);
}
```

In die Klasse Spielfeld:


```
public Element getElement(int i){

return elemente.get(i);

}
```


Und dann in der Klasse "Erde":


```
public void performTurn(){
this.deleteElement(this);
}
```


Hm, vielleicht kann man sich die Superklasse "Elemente" auch sparen.. :reflect:



Edit3:

Klar kann ich mir das sparen, das Interface "Element" kann ich ja als gemeinsamen Typ für die ArrayList nehmen!


----------



## babuschka (21. Dez 2011)

Hier meine bisherigen Ideen:


```
//Superklasse für die Hindernisse Stein, Erde, Wand, Diamant

public class Hindernis implements Element{

int x_position;
int y_position;

public Hindernis(int x_position, int y_position){

this.x_position=x_position;
this.y_position=y_position;
}

public void performTurn(){
}

public char getChar(){
return 'H';
}
}
```


```
//Die Klasse Wand

public class Wand extends Hindernis implements Element{

public Wand(int x_position, int y_position){

super(x_position, y_position);

}

public char getChar(){

 return 'W';

}

}
```


```
//Die Klasse Stein

public class Stein extends Hindernis implements Element{

public Stein(int x_position, int y_position){

super(x_position, y_position);

}

public char getChar(){
  
   return 'S';

}

//getSpielfeld(int i, int j) soll die Methode sein, die die Spielfeld-Felder zurückgibt.
//setSpielfeld(int i, int j) soll die Methode sein, die die Spielfeld-Felder setzt (nach einem Zug)
public void performTurn(){

if(spielfeld.getSpielfeld(this. x_position,this. y_position-1)==' '){
       this.y_position=this.y_position-1;
      spielfeld.setSpielfeld(this.x_position,this.y_position)=this;
}
if( (spielfeld.getSpielfeld(this.x_position-1,this.y_position)== ' ') && (spielfeld.getSpielfeld(this.x_position-1,this.y_position-1)==' ') ){
     this.x_position=this.x_position-1;
     this.y_position=this.y_position-1;

     spielfeld.setSpielfeld(this.x_position, y_position)=this;
  }
}

}
```


```
//Die Klasse LeeresFeld

public class LeeresFeld implements Element{

int x_position;
int y_position;

public LeeresFeld(int x_position, int y_position){

this.x_position=x_position;
this.y_position=y_position;
}

public char getChar(){

   return ' ';

}

}
```


```
//Die Klasse Erde

Spielfeld spielfeld;

public class Erde extends Hindernis implements Element{

public Erde(int x_position, int y_position){

super(x_position, y_position);

}

public char getChar(){

   return 'E';

}

public void performTurn(){

spielfeld.deleteElement(this);

}

}
```


```
//Die Klasse Diamant

Spielfeld spielfeld;

public class Diamant extends Hindernis implements Element{

public Diamant(int x_position, int y_position){

   super(x_position,y_position);

}


public char getChar(){

   return 'D';

}

//deleteElement(Element) soll die Methode sein, die ein Element von seinem Spielfeld-Feld entfernt.

public void performTurn(){

spielfeld.deleteElement(this);

}

}
```


Würde mich sehr freuen, wenn Ihr Euch das mal ansehen würdet.


----------



## babuschka (21. Dez 2011)

Hier meine weiteren Ideen:


```
//Die Superklasse Teilnehmer für Spieler und Monster

public class Teilnehmer implements Element{

Spielfeld spielfeld;
int x_position;
int y_position;

public Teilnehmer{

x_position=1;
y_position=1;
}

abstract public char getChar();

abstract public void performTurn;

}
```


```
//Die Klasse Spieler

public class Spieler extends Teilnehmer implements Element{

char ElementSymbol1;
char ElementSymbol2;
char ElementSymbol3;
char ElementSymbol4;

public Spieler(int x_position, int y_position){

   super(x_position, y_position);

}

public char getChar(){

   return 'P';
}

public void performTurn(char Char){

ElementSymbol1=spielfeld.getElement(this.x_position+1,this.y_position).getChar();
ElementSymbol2=spielfeld.getElement(this.x_position-1,this.y_position).getChar();
ElementSymbol3=spielfeld.getElement(this.x_position,this.y_position+1).getChar();
ElementSymbol4=spielfeld.getElement(this.x_position,this.y_position-1).getChar();

  switch(char){

case 'right':           if(ElementSymbol1==' '){
                                      this.x_position=this.x_position+1;
                                      spielfeld.setElement(this.x_position,this.y_position);
                                      break;
                               }
                                if(ElementSymbol1=='S'){
                                break;
                               }
                                 if(ElementSymbol1=='E'){
                                  spielfeld.getElement(this.x_position+1,this.y_position).performTurn();
                                  this.x_position=this.x_position+1;
                                  spielfeld.setElement(this.x_position,this.y_position);
                                  break;
                             }
                               if(ElementSymbol1=='M'){
                               System.out.println('Game Over');
                               break;
                             }

case 'left':   if(ElementSymbol2==' '){
                       this.x_position=this.x_position-1;
                       spielfeld.setElement(this.x_position, this.y_position);
                       break;
                  }
                    if(ElementSymbol2=='S'){
                        break;
                 }
                    
                      }
                        if(ElementSymbol2=='E'){
                       spielfeld.getElement(this.x_position-1,this.y_position).performTurn();
                         this.x_position=this.x_position-1;
                       spielfeld.setElement(this.x_position,this.y_position);
                        break;
                      }
                   if(ElementSymbol2=='M'){
                  System.out.println('Game Over');
                   break;
                  }

case 'up': if(ElementSymbol3==' '){
                       this.y_position=this.y_position+1;
                       spielfeld.setElement(this.x_position,this.y_position);
                       break;
                  }
                  if(ElementSymbol3=='S'){
                       break;
                 }
                 if(ElementSymbol3=='E'){
                      spielfeld.getElement(this.x_position,this.y_position+1).performTurn();
                      this.y_position=this.y_position+1;
                      spielfeld.setElement(this.x_position,this.y_position);
                      break;
                }
                 if(ElementSymbol3=='M'){
                    System.out.println('Game Over');
                    break;
               }

case 'down': if(ElementSymbol4==' '){
                             this.y_position=this.y_position-1;
                             spielfeld.setElement(this.x_position,this.y_position);
                             break;
                         }
                       if(ElementSymbol4=='S'){
                           break;
                        }
                       if(ElementSymbol4=='E'){
                           spielfeld.getElement(this.x_position,this.y_position-1).performTurn();
                           this.y_position=this.y_position-1;
                           spielfeld.setElement(this.x_position,this.y_position);
                           break;
                       }
                     if(ElementSymbol4=='M'){
                          System.out.println('Game Over');
                          break;
                      }
}

}


}
```


Also sicher bin ich mir nicht, aber toootal verkehrt wird es wohl auch nicht sein. Hoffe ich.


----------



## babuschka (22. Dez 2011)

Ich möchte nicht drängeln, aber heute Mittag wollte ich gerne hieran weiterarbeiten und ich wüsste wirklich sehr gerne, was Ihr von meinen bisherigen Ideen so haltet, damit ich sinnvoll weiterarbeiten kann.


----------



## stikio (22. Dez 2011)

ich weiss ja nicht was du erwartest, aber hier wird sich niemand seitenweise code durchlesen um danach zu sagen, dass es ok ist ^^

probier den code aus, entwickel deine ideen weiter und wenn was nicht so funktioniert wie es sollte und du es nicht hinbekommst, dann solltest du nochmal ein konkretes problem posten.


----------



## Sonecc (22. Dez 2011)

Der code sollte erstmal von syntaktischen Fehlern befreit werden. Schon die Klasse Teilnehmer ist komplett nicht kompilierbar.
Desweiteren wird das Feld spielfeld nie gesetzt, das Switch-Statement in der Klasse Spieler ist nicht kompilierbar.
So könnte man das beliebig weiterführen wenn ich mir die vorherigen codebeispiele anschaue

Naming Conventions solltest du auch mal googlen


----------



## langhaar! (22. Dez 2011)

Es gäbe einiges zu sagen, aber dazu fehlt mir die Zeit und auch Lust.

Was mir spontan aufgefallen ist:

In welcher Beziehung stehen Spielfeld und Erde bzw. Diamant?
Die Klasse Spielfeld wird alle Elemente enthalten müssen.
Bei dir enthält aber auch jeder Diamant und jedes Erdfeld wiederum ein Spielfeld.
Das ist unnötig und ganz schlechtes Design.
Verabschiede dich von dem Gedanken, dass sich Erde selbst entfernt.
Das ist Aufgabe des Spielfelds.

Wenn du Codeblöcke in fast identischer Form mehrfach benötigst, dann machst du Methoden daraus.
So etwas:
	
	
	
	





```
this.y_position=this.y_position-1;
                             spielfeld.setElement(this.x_position,this.y_position);
                             break;
                         }
                       if(ElementSymbol4=='S'){
                           break;
                        }
                       if(ElementSymbol4=='E'){
                           spielfeld.getElement(this.x_position,this.y_position-1).performTurn();
                           this.y_position=this.y_position-1;
                           spielfeld.setElement(this.x_position,this.y_position);
                           break;
                       }
                     if(ElementSymbol4=='M'){
                          System.out.println('Game Over');
                          break;
                      }
```
muss man nicht 4 Mal progammieren. Mach ElementSymbolX zum Parameter


----------



## babuschka (22. Dez 2011)

Okay, dann habe ich das für die Klasse Erde (Diamant analog):


```
//Die Klasse Erde

public class Erde extends Hindernis implements Element{

public Erde(int x_position, int y_position){

super(x_position, y_position);

}

public char getChar(){

   return 'E';

}

}
```

Bei Spieler muss ich doch aber als Attribut ein Spielfeld haben, oder?


In der Aufgabe steht ja, daß das Monster sich zufällig bewegen soll und nicht unbedingt auf den Spieler zu. Wie realisiert man das denn? Mit Math.random()?


----------



## babuschka (22. Dez 2011)

langhaar! hat gesagt.:


> Es gäbe einiges zu sagen, aber dazu fehlt mir die Zeit und auch Lust.



Das ist schade.


----------



## babuschka (22. Dez 2011)

Hier ist meine Idee zur Klasse Monster.
Ich weiß, daß man Vieles sicherlich schöner und kürzer machen könnte.
Aber das ist mir erstmal nicht so wichtig, ich möchte einfach nur gerne wissen, ob es so okay ist.
Trotzdem freue ich mich natürlich über Verbesserungstipps, keine Frage.


```
//Die Klasse Monster

public class Monster extends Teilnehmer implements Element{

Spielfeld spielfeld;

char ElementSymbol5;
char ElementSymbol6;
char ElementSymbol7;
char ElementSymbol8;

double a;

public Monster(int x_position,int y_position){

   super(x_position,y_position);

}

public char getChar(){

    return 'M';
}

public performTurn(){

ElementSymbol5=spielfeld.getElement(this.x_position+1,this.y_position).getChar();
ElementSymbol6=spielfeld.getElement(this.x_position-1,this.y_position).getChar();
ElementSymbol7=spielfeld.getElement(this.x_position,this.y_position+1).getChar();
ElementSymbol8=spielfeld.getElement(this.x_position,this.y_position-1).getChar();


a=Math.random();

if( (a<=0.25) && (ElementSymbol5==' ') || (a<=0.25) && (ElementSymbol=='D')  ){
                this.x_position=this.x_position+1;
                spielfeld.setElement(this.x_position,this.y_position);
          }
      if( (a<=0.25) && (ElementSymbol5=='P') ){
                this.x_position=this.x_position+1;
                spielfeld.setElement(this.x_position,this.y_position);
                System.out.println('Game Over');
          }

if( (0.25<a && a<=0.5 && ElementSymbol6==' ' ) || (0.25<a && a<=0.5 && ElementSymbol6=='D') ){
               this.x_position=this.x_position-1;
               spielfeld.setElement(this.x_position,this.y_position);
         }
        if( (0.25<a && a<=0.5 && ElementSymbol6=='P') ){
               this.x_position=this.x_position-1;
               spielfeld.setElement(this.x_position,this.y_position);
               System.out.println('Game Over');

if ( (0.5<a && a<=0.75 && ElementSymbol7==' ') || (0.5<a && a<=0.75 && ElementSymbol=='D') ){
              this.y_position=this.y_position+1;
              spielfeld(this.x_position,this.y_position);
        }
       if( (0.5<a && a<=0.75 && ElementSymbol7=='P') ){
              this.y_position=this.y_position+1;
              spielfeld(this.x_position,this.y_position);
              System.out.println('Game Over');
         }

if( (0.75<a && a<=1 && ElementSymbol8==' ') || (0.75<a && a<=1 && ElementSymbol8=='D') ) {
             this.y_position=this.y_position-1;
             spielfeld.setElement(this.x_position, this.y_position);
        }
        if( (0.75<a && a<=1 && ElementSymbol8=='P') ){
              this.y_position=this.y_position-1;
             spielfeld.setElement(this.x_position, this.y_position);
             System.out.println('Game Over');
        }
     
}
```


:rtfm:


----------



## Gast2 (22. Dez 2011)

Dann mach ichs kurz: Nein, denn du hast immernoch Code Duplication ohne Ende. So schau ich jedenfall nicht näher rein.

Der Tipp inklusive Beispiel kam schon von einem Vorposter. Lagere gleichen Code in Methoden aus.


----------



## babuschka (22. Dez 2011)

Ich weiß nicht genau, was mit dem Tipp gemeint war.

Könntest Du es mir vielleicht nochmal erklären?


----------



## Gast2 (22. Dez 2011)

Folgende 2 Codeschnipsel kommen z.B. mehrfach vor: 


```
this.x_position=this.x_position+1;
spielfeld.setElement(this.x_position,this.y_position);
```


```
System.out.println('Game Over');
```

Für diese sollte man eigene Methoden schreiben. 

Sinn ist, dass man dann nur noch den Methodeaufruf gameOver(); hat. Im Moment bestünde dieser zwar nur aus einer Knsolenausgabe aber das kann sich ja ändern! Im Quelltext musst du dann nur noch an einer Stelle, nämlich in der Methode den Code ändern. Außerdem wird das ganze lesbarer.


----------



## Sonecc (22. Dez 2011)

Und es bleibt dabei, dass dir bei diesen Klassen fehler um die Ohren fliegen. 
So erhält spielfeld nie einen Wert und wird daher bei aufruf von performTurn eine NullPointerException auslösen

Desweiteren ist deine Klasse Teilnehmer schon vom Typ Element, deine Klassen Monster, Spieler und Co. müssen also das Interface nicht mehr explizit implementieren. (wird ja schon von Teilnehmer gemacht)

Und immer noch hälst du dich an keiner Naming Conventions, geschweige denn, dass du eine einheitliche Namensgebung nutzt.

Das ganze ist dir aber schon mehrfach gesagt worden, du scheinst aber so beratungsresistent zu sein, dass ich das nun ein letztes mal erwähne.


----------



## babuschka (22. Dez 2011)

Ich habe mir was überlegt.

Würde das gehen:


```
//Die Klasse Monster

public class Monster extends Teilnehmer implements Element{

Spielfeld spielfeld;

char ElementSymbol5;
char ElementSymbol6;
char ElementSymbol7;
char ElementSymbol8;


public Monster(int x_position,int y_position){

   super(x_position,y_position);

}

public char getChar(){

    return 'M';
}

public void BewegeMonster(double a, double b, char c, int d, int e){

if( (a<=b && c==' ') || (a<=b && c=='D') ){

    this.x_position=this.x_position+d;
    this.y_position=this.y_position+e; 
    spielfeld.setElement(this.x_position,this.y_position);
  }

     if( a<=b && c=='P') {
        this.x_position=this.x_position+d;
        this.y_position=this.y_position+e; 
        spielfeld.setElement(this.x_position,this.y_position);
        System.out.println('Game Over');
   }

}

public performTurn(){

ElementSymbol5=spielfeld.getElement(this.x_position+1,this.y_position).getChar();
ElementSymbol6=spielfeld.getElement(this.x_position-1,this.y_position).getChar();
ElementSymbol7=spielfeld.getElement(this.x_position,this.y_position+1).getChar();
ElementSymbol8=spielfeld.getElement(this.x_position,this.y_position-1).getChar();

double a=Math.random();

BewegeMonster(a, 0.25, ElementSymbol5,1,0);

BewegeMonster(a,0.5, ElementSymbol6,-1,0);

BewegeMonster(a,0.75, ElementSymbol7,0,1);

Bewege Monster(a,1, ElementSymbol8,0,-1);

}


}
```


----------



## Gast2 (22. Dez 2011)

> Und immer noch hälst du dich an keiner Naming Conventions, geschweige denn, dass du eine einheitliche Namensgebung nutzt.
> 
> Das ganze ist dir aber schon mehrfach gesagt worden, du scheinst aber so beratungsresistent zu sein, dass ich das nun ein letztes mal erwähne.



Da stimme ich zu, in deinem neuen Beispiel sind nach wie vor KEINE der konkreten Hinweise umgesetzt. Noch immer stimmt das was ich oben zitiere, und meine Hinweise hast du auch ignoriert. 

I'm out...


----------



## babuschka (22. Dez 2011)

Sonecc hat gesagt.:


> Und es bleibt dabei, dass dir bei diesen Klassen fehler um die Ohren fliegen.
> So erhält spielfeld nie einen Wert und wird daher bei aufruf von performTurn eine NullPointerException auslösen



Wieso erhält Spielfeld nie einen Wert?

Also ich habe die Klasse Spielfeld noch nicht geschrieben, meinst Du das?


----------



## babuschka (22. Dez 2011)

kappesf hat gesagt.:


> Da stimme ich zu, in deinem neuen Beispiel sind nach wie vor KEINE der konkreten Hinweise umgesetzt. Noch immer stimmt das was ich oben zitiere, und meine Hinweise hast du auch ignoriert.
> 
> I'm out...




Du hast gesagt, daß ich gleiche Code Teile in Methoden packen kann.

Das habe ich versucht, was habe ich falsch gemacht?



[Irgendwie seid ihr so abweisend, ich gebe mir doch Mühe und versuche es, ich kann es aber nicht besser, ich meine es doch nicht böse, wenn ich Eure Tipps nicht umsetzen kann.]


----------



## Gast2 (22. Dez 2011)

Hast du Glück, dass ich nen guten Tag hab weil nachher Urlaub! 
*
<VORKAU_MODUS>*

1) Naming Conventions: Methoden klein schreiben und außerdem ist Englisch üblich! (Google nach Naming Conventions JAva und guck was da noch so alles gilt!). Benne vor allem auch die Parameter sinnvoll, dass mache ich jetzt nicht für dich

Aus 

```
public void BewegeMonster(double a, double b, char c, int d, int e)
```
wird dann 

```
public void moveMonster(double a, double b, char c, int d, int e)
```

2) Fass gleichen Code zusammen! 

Dann wird aus: 


```
if( (a<=b && c==' ') || (a<=b && c=='D') ){
 
    this.x_position=this.x_position+d;
    this.y_position=this.y_position+e; 
    spielfeld.setElement(this.x_position,this.y_position);
  }
 
if( a<=b && c=='P') {
    this.x_position=this.x_position+d;
    this.y_position=this.y_position+e; 
    spielfeld.setElement(this.x_position,this.y_position);
    System.out.println('Game Over');
}
```

nämlich 


```
if( (a<=b && c==' ') || (a<=b && c=='D') ){       
            setPosition(spielfeld, d, e);
         }
         
        if( a<=b && c=='P') {
            setPosition(spielfeld, d, e);
            gameOver();
        } 
    }
    
    private void setPosition(final Spielfeld spielfeld, final int d, final int e) {
        this.x_position=this.x_position+d;
        this.y_position=this.y_position+e; 
        spielfeld.setElement(this.x_position,this.y_position);
    }
    
    private void gameOver() {
        System.out.println('Game Over');
    }
```

*
</VORKAU_MODUS>*

Ungetestet ect. Ich hoffe jetzt verstehst du was wir meinen. Falls nicht rate ich dir dringend zu weiterer Lektüre!


----------



## Sonecc (22. Dez 2011)

In Zeile 5 deines Codes steht:


```
Spielfeld spielfeld;
```

Dies ist allerdings bei dir immer null.
Weder im Konstruktor noch sonst irgendwo wird für spielfeld ein Wert eingesetzt.
spielfeld ist daher immer null und damit läuft deine Methode performTurn nicht, weil auf ein null objekt zugegriffen wird.

Ob die klasse nun schon geschrieben wurde oder nicht ist irrelevant. Der Variablen (genauer dem Feld) wird niemals ein Wert zugewiesen, was ich aber schon 2 mal beschrieben habe.


Wenn du spielfeld unbedingt in deiner klasse haben willst, wirst du dieser eine instanz zuweisen müssen, z.B. im Konstruktor deiner klassen.


----------



## babuschka (22. Dez 2011)

Dankeschön für die Erklärungen.

Damit arbeite ich jetzt erstmal weiter.





[Ich will wirklich nicht unhöflich sein, aber wieso müssen solche Kommentare wie <vorkaumodus> sein? Ich bin doch hier, weil ich absoluter Anfänger bin und das hier ist doch eine freiwillige Veranstaltung; ich kann es ja verstehen, wenn Experten von solchen Anfängerfragen genervt sind oder sich ärgern, wenn Tipps nicht umgesetzt werden (können), aber es ist doch keiner gezwungen hier mitzumachen. Und wenn man sich anmeldet, dann kann man doch in einem normal respektvollen Ton helfen, finde ich. Ich stelle meine Fragen ja auch ganz normal. Vielleicht blöde, aber normal höflich.]


----------



## Gast2 (22. Dez 2011)

java_ hat gesagt.:


> Dankeschön für die Erklärungen.
> [Ich will wirklich nicht unhöflich sein, aber wieso müssen solche Kommentare wie <vorkaumodus> sein? Ich bin doch hier, weil ich absoluter Anfänger bin und das hier ist doch eine freiwillige Veranstaltung; ich kann es ja verstehen, wenn Experten von solchen Anfängerfragen genervt sind oder sich ärgern, wenn Tipps nicht umgesetzt werden (können), aber es ist doch keiner gezwungen hier mitzumachen. Und wenn man sich anmeldet, dann kann man doch in einem normal respektvollen Ton helfen, finde ich. Ich stelle meine Fragen ja auch ganz normal. Vielleicht blöde, aber normal höflich.]



Das muss sein, da du schon darauf hingewiesen wurdest. Wenn man dann z.B. nach Naming Conventions sucht findet man diese. 

Es kann zudem einfach nicht sein, dass man einem Informatikstudent ein CodeBeispiel posten muss, damit er kapiert was Code Redundanz vermeiden in Code bedeutet. 

Zu dem höflich: Es ist ebenso unhöflich über Tips hinwegzugehen und eine bereits gestellt Frage einfach zu wiederholen. Und das tust du sehr häufig. 

Im übrigen wurde dir das vorgekaut...


----------



## babuschka (22. Dez 2011)

Vielleicht darf ich anmerken, daß ich nicht Informatik, sondern Mathematik studiere und im Rahmen dieses Studiums diese Veranstaltung besuchen muss.

Zudem: Wieso kann es nicht angehen, daß ein Anfänger mit diesen Dingen nichts anzufangen weiß und sie ja deswegen nachfragt und erlernen möchte?
Die Logik verstehe ich nicht recht.

Und daß ich Fragen mehrfach stelle bzw. Tipps übergehe, ist, wie gesagt, keine böswillige Absicht; es kommt dann die Message nicht bei mir an. Nur helfen Kommentare wie "DRINGEND weitere Lektüre" oder "Da fliegen einem Fehler um die Ohren" rein gar nichts weiter; ich möchte ja wissen, was ich falsch mache und was konkret zu lernen ist.


Demotivierende Anmerkungen sind keine Hilfe.


Zurechtweisungen, wo sie angebracht sind, sind natürlich etwas Anderes.
Aber auch die kann man sachlicher vortragen, finde ich.
Ein Hinweis, daß ich die Notationskonventionen nicht beachte, hätte vollkommen ausgereicht. Selbst ich hätte das dann verstanden.



Die Folge ist nun vermutlich, daß man mir gar nicht mehr antwortet.
Aber ich musste das einfach mal aussprechen, weil mir das von Beginn an aufgefallen ist.


----------



## Sonecc (22. Dez 2011)

> Ein Hinweis, daß ich die Notationskonventionen nicht beachte, hätte vollkommen ausgereicht. Selbst ich hätte das dann verstanden.





Sonecc hat gesagt.:


> (...) Naming Conventions solltest du auch mal googlen





Sonecc hat gesagt.:


> (...)
> Und immer noch hälst du dich an keiner Naming Conventions, geschweige denn, dass du eine einheitliche Namensgebung nutzt.
> (...)



Wie oft sollte ich dir das noch sagen?

Das Problem warum wir so reagieren ist, dass wir dir sagen was du falsch machst und du es einfach ignorierst. Du fragst nich nach oder zeigst, dass du wenigstens versucht hast etwas davon zu machen, sondern du ignorierst es und machst die gleichen Fehler weiterhin.

Da verliert man die Geduld und auch die Lust dir zu helfen.

Bezüglich der Aussage dass du Anfänger bist.
Das glaube ich dir gerne, aber dann lass dir folgendes gesagt sein:

Wenn ihr in der Vorlesung schon bei solchen Dingen angekommen seid, dann solltest du wissen worüber wir reden.
Das erste was man in einer Informatikvorlesung lernt ist nämlich Namenskonvention & das sinnvolle Nutzen von Methoden. (zumindest in meinem Studium war das so und selbst im Abi war es so)

Es mag sein, dass deine Motivation das vernünftig zu lernen nicht genauso hoch ist wie in deinen Mathevorlesungen, das hatte ich bei meinen Mathevorlesungen auch. Dennoch sollten die Grundlagen inzwischen verstanden worden sein, sonst hast du Probleme. Genau das scheint bei dir leider nicht der Fall zu sein.
Es tut mir Leid, auch wenn du das nicht hören magst, aber eventuell wäre weiterführende Hilfe in Form eines guten Buches oder einer Person die in deiner Umgebung ist hiflreich. Du hast doch sicherlich Kommolitonen die das können und die dir vielleicht helfen die Wissenlücken zu füllen, die dich daran hindern solche Grundlegenden Begriffe wie die hier genannten zu verstehen.


Verstehe mich nicht falsch. Ich wollte nie gemein sein oder einen unpassenden Ton an den Tag legen. Aber ich sehe keinen Sinn darin jemandem zu helfen, der die Hilfestellungen ignoriert. Das war bei dir nunmal leider der Fall, bzw. den Eindruck bekam man.


----------



## babuschka (22. Dez 2011)

Du hattest oben geschrieben, daß ich das Spielfeld in den Klassen nirgends fülle.

Wäre es eine Lösung zum Beispiel in der Klasse Monster zu schreiben:


```
spielfeld= new Spielfeld(10,20)
```
,

wobei ich das so meine, daß ich später in der noch zu schreibenden Klasse Spielfeld den Konstruktor dementsprechend schreibe, daß die erste Zahl die Breite und die zweite Zahl die Länge des Feldes angeben soll.






PS. Die letzten Antworten habe ich gelesen, aber ich möchte gerne zurück zur Aufgabe kommen.


----------



## Gast2 (22. Dez 2011)

java_ hat gesagt.:


> Vielleicht darf ich anmerken, daß ich nicht Informatik, sondern Mathematik studiere und im Rahmen dieses Studiums diese Veranstaltung besuchen muss.



Das macht keinen Unterschied, denn von einem Studenten muss man mehr eigenverantwortlichkeit erwarten können. Das ist unabhängig vom Studienfach.



java_ hat gesagt.:


> Ein Hinweis, daß ich die Notationskonventionen nicht beachte, hätte vollkommen ausgereicht. Selbst ich hätte das dann verstanden.



Wie Sonecc bereits gesagt hat wurde das vorher schon mindestens 2 mal gesagt. Daraus kann man auch schließen, dass du die Antworten nicht gründlich liest. 

Beim wiederverwenden von Code genauso. Ich hatte dir konkret gepostet welchen Code du in ne Methode packen sollst. z.B. die GameOver Ausgabe. Mit Erklärung warum. Im nächsten Beispiel wars nicht gemacht. 

Pack dir mal an die eigene Nase. Vielleicht solltest du den ganzen Thread nochmal selber lesen, dann fällt dir vielleicht selber mal auf wie oft du solche Hinweise (von mir aus unwissentlich) übergehst. 

Wir sehen nur was du postest, und da ignorierst du halt vieles. 

PS: Wir meinen das nicht böse, denn dann würden wir dich einfach machen lassen...


----------



## Sonecc (22. Dez 2011)

java_ hat gesagt.:


> Du hattest oben geschrieben, daß ich das Spielfeld in den Klassen nirgends fülle.
> 
> Wäre es eine Lösung zum Beispiel in der Klasse Monster zu schreiben:
> 
> ...



Denk mal darüber nach.
Wenn du jedem Monster und jedem Spieler usw. ein eigenes Spielfeld gibst, wird das nix.
Stell dir vor du willst Schach programmieren.
Eine Schachfigur sähe bei dir dann so aus:


```
public class SchachFigur {

private Schachfeld schachfeld = new Schachfeld();

(...)

}
```

Nun stell dir vor, du würdest ein richtiges Schachspiel so aufbauen.
Du müsstest dann also für jede Figur ein neues Schachbrett nehmen.

Ich hoffe du verstehst was ich dir sagen will...

Mach es besser so:


```
public class SchachFigur {

private Schachfeld schachfeld;

public SchachFigur(Schachfeld feld) {
     this.schachfeld = feld
}
```

So kannst du jeder Figur das Feld zuweisen, zu dem es gehört


----------



## babuschka (22. Dez 2011)

Das habe ich verstanden, danke.


Jetzt stehe ich noch vor diesem Berg:

Danke!

Jetzt habe ich noch eine andere Frage.

Aus der Aufgabenstellung:

Ein Spielfeld ist 10x10 bis 20x20 Felder groß und immer rechteckig.

Es wird in einer einfachen
.txt Datei definiert.


Zum Einlesen der Datei haben wir die Klasse MapProvider entwickelt:


```
import javax.swing.*;
import javax.swing.filechooser.FileNameExtensionFilter;
import java.io.*;
import java.util.ArrayList;
import java.util.List;

/**
 * Provides a method to read several .txt files.
 */
public class MapProvider {

    /**
     * Displays a File-Open Dialog to load 1 to n .txt files.
     * The content of the selected files will be returned.
     *
     * Example:
     * <pre>
     * List<List<String>> maps = MapProvider.loadMaps();
     * for (List<String> level : maps)
     * { //for each level
     *    for(String line : level)
     *    {  //for each line in each level
     *       //do some super cool stuff :)
     *    }
     * }
     * </pre>
     *
     * @return a list of 1 to n file-contents. Each file content is a list of strings representing the lines of the file.
     * If an error occurred while getting the content null will be returned. If the user pressed cancel the size of the list
	 * will be 0.
     *
     */
    public static List<List<String>> loadMaps()
    {

        List<List<String>> files = new ArrayList<List<String>>();

        final JFileChooser fc = new JFileChooser();
        fc.setFileFilter(new FileNameExtensionFilter("Text file","txt"));
        fc.setDialogTitle("Select multiple boulder dash maps");
        fc.setMultiSelectionEnabled(true);

        if (fc.showOpenDialog(null) == JFileChooser.APPROVE_OPTION)
        {
            for (File f : fc.getSelectedFiles())
            {
                try {
                    files.add(loadFile(f));
                } catch (IOException e) {
                    return null;
                }
            }
        }

        return files;
    }

    /**
     * Wrapper method for loadMaps(). Will be used to load the content of one file to a String-List
     * @param file The file to load the content from
     * @return A list of Strings. Each element of the list represents one line of file (exclusive \n - linux, \r\n -windows, or \r - some older mac-systems)
     * @throws IOException If an error occurred while parsing parameter file
     */
    private static List<String> loadFile(File file) throws IOException {
        List<String> lines = new ArrayList<String>();

        BufferedReader reader = new BufferedReader(new FileReader(file));
        String line;
        try {
            while ((line = reader.readLine()) != null) {
                lines.add(line);
            }
        } finally {
            reader.close();
        }

        return lines;
    }

}
```


Schreibt eine Klasse MapParser, die eine Methode Element[][] parseMap(List<String> map)
enthält. Die Methode soll ein zweidimensionales Array vom Typ Element (das Spielfeld) erzeugen
und füllen. Um das Feld zu füllen müsst ihr die Spielfeldzeichenketten Zeichen für Zeichen
durchgehen und entsprechende Elemente erzeugen.

Während der Erzeugung muss geprüft werden, ob das Spielfeld valide ist. Das Spielfeld ist valide
wenn:

 es komplett von Wänden umgeben ist.
 genau eine Spielfigur existiert.
 mindestens ein Ausgang existiert.
 es rechteckig ist.


Ich verstehe die Klasse MapProvider nicht.
Aber ich befürchte leider, das ist zu umfangreich um es mir zu erklären.


----------



## Sonecc (22. Dez 2011)

...

In den Kommentaren steht außerordentlich detailliert was die Klasse macht


Was verstehst du daran denn nicht?

Alles? Selbst nach lesen der Kommentare?


----------



## babuschka (22. Dez 2011)

Zeile 18 bis 26 verstehe ich nicht.


----------



## Sonecc (22. Dez 2011)

```
List<List<String>> maps = MapProvider.loadMaps(); //Lade die Spielfelder für das Spiel
 for (List<String> level : maps) //Durchlaufe alle Spielfelder die geladen wurden
 { //for each level
    for(String line : level) //Durchlaufe alle Linien der eingelesenen Datei (entspricht einer Reihe im Spielfeld)
    {  //for each line in each level
       //do some super cool stuff :)
    }
}
```

Hab noch einige Deutsche Kommentare zu den schon vorhandenen (meiner Meinung nach ausführlichen) Kommentaren hinzugefügt.

Anzumerken ist noch, dass dies ein Beispiel ist, wie man die Klasse nutzen kann. Der Code der dort steht ist auskommentiert, würde also nicht ausgeführt werden, sondern soll nur zeigen, wie man die Methode nutzen sollte


----------



## babuschka (22. Dez 2011)

Was ist List<List<String>>?

Und muss ich mir die Spielfelder selbst ausdenken?


Also Du schreibst: Lade Spielfelder.. aber welche Spielfelder denn? Wo wurden die festgelegt? In einer txt.-Datei?


Ich verstehe das Vorgehen nicht.


----------



## langhaar! (22. Dez 2011)

Natürlich sollst du selber die Textdateien mit den Spielfeldern bestücken.

Das sähe ungefähr so aus:


```
wwwwwwwwww
weeeeeeeeeeew
weeeeeeeeeeew
weeeeeedeeeew
weeeeesseeeew
weeeeeeeeeeew
weeeeeeeeeeew
weeeedeeeeeew
weeeeeeeeeeew
wwwwwwwwww
```

Du erstellst dir selber die Dateien und dann liest du sie zeilenweise ein und füllst dein Spielfeld mit Elementen, die in der Textdatei vorgegeben sind.


----------



## Sonecc (22. Dez 2011)

> Was ist List<List<String>>?



Auch das ist etwas, dass du inzwischen kennen solltest.
Galileo Computing :: Java ist auch eine Insel - 3 Klassen und Objekte

List ist selbsterklärend, nämlich eine Liste (ansammlung) von Objekten...




> Also Du schreibst: Lade Spielfelder.. aber welche Spielfelder denn? Wo wurden die festgelegt? In einer txt.-Datei?


Liest du überhaupt die Aufgabenstellung???


java_ hat gesagt.:


> Aus der Aufgabenstellung:
> 
> Ein Spielfeld ist 10x10 bis 20x20 Felder groß und immer rechteckig.
> 
> ...


----------



## babuschka (22. Dez 2011)

Welche Textdateien denn?

Also ich soll ja eine Klasse schreiben, wo ich eine Methode habe, die die Spielfelder als zweidimensionale Matrix erzeugt.

Und diese Matrizen werden dann von der bereitgestellten Klasse in txt-Dateien umgewandelt?


Aber wo gebe ich denn die Spielfelder ein, die ich erstellt habe in der Klasse MapParser?


----------



## langhaar! (22. Dez 2011)

java_ hat gesagt.:


> Welche Textdateien denn?



Die, die du dir selbst erstellst. Wie ich bereits geschrieben hatte. Wieder ein Beispiel dafür, dass du nicht aufmerksam liest. Für einen Mathematiker reichlich merkwürdig ???:L


----------



## babuschka (22. Dez 2011)

langhaar! hat gesagt.:


> Natürlich sollst du selber die Textdateien mit den Spielfeldern bestücken.
> 
> Das sähe ungefähr so aus:
> 
> ...




Okay, aber wo übergebe ich die von mir erstellten txt.Dateien an die Methode?


----------



## langhaar! (22. Dez 2011)

Gar nicht. Die Methode loadMaps() liest sie von Festplatte.

Geht aber aus der Beschreibung hervor: :rtfm: 


> Displays a File-Open Dialog to load 1 to n .txt files.


Du musst dir deine Aufgabe schon anschauen.
Klar, dass irgendwann gehässige oder genervte Kommentare kommen.
Man kann dir nur helfen, wenn du auch mitmachst.


----------



## babuschka (22. Dez 2011)

Also, ich muss nachhaken, sorry.

Ich schreibe (zum Beispiel in Notepad) sowas auf, wie Du es eben getan hast.

Ich speichere es  - unter welchem Namen? Wo?

Und dann?



Sorry, ich verstehe nicht, wie das funktioniert.

Das grobe Vorgehen ist doch:


1. txt.-Datei erstellen

2. Mit MapProvider einlesen

3. damit Matrix füllen


Aber den Schritt von 1 nach 2 verstehe ich nicht.


----------



## langhaar! (22. Dez 2011)

Geht alles aus dem Zitat in #52 hervor.
Du weisst, was ein File-Open Dialog ist und was er macht?


----------



## babuschka (22. Dez 2011)

Nein, das weiß ich nicht.


----------



## langhaar! (22. Dez 2011)

Geh in einen Editor deiner Wahl und geh auf Datei -> Öffnen.
Das ist ein File Open Dialog.


----------



## babuschka (22. Dez 2011)

Das heißt, ich kann also dann auswählen, welche txt-Dateien ich öffnen möchte.

Und in Zeile 22 kann ich das mit dem Matrix-Füllen machen, also mit der Methode aus der Klasse MapParser?


----------



## Sonecc (22. Dez 2011)

Ok, ab jetzt klinke ich mich aus.
Du liest die Hilfe nicht, die Aufgabe nicht und du scheinst nichtmal mit den grundlegendsten Grundlagen von Computern vertraut.
Das ganze macht so leider keinen Sinn und ist für mich reine Zeitverschwendung.
Such dir jemanden der dir direkt helfen kann. Am besten solltest du dabei nochmal ganz von vorne anfangen


----------



## babuschka (22. Dez 2011)

Ich sage doch, ich verstehe die zeilen 18-26 nicht.

Schreibe ich erst die txt.-Dateien und benutze dann die Klasse MapProvider

oder

benutze ich erst die Methode aus der Klasse MapProvider und erstelle dann die txt.-Datei?


----------



## langhaar! (22. Dez 2011)

java_ hat gesagt.:


> Das heißt, ich kann also dann auswählen, welche txt-Dateien ich öffnen möchte.


 Ja



> Und in Zeile 22 kann ich das mit dem Matrix-Füllen machen, also mit der Methode aus der Klasse MapParser?



Du benutzt den dortigen Beispiel Code und fügst den z.B. in eine Klasse Spiel ein, die den ganzen Ablauf steuert.



java_ hat gesagt.:


> benutze ich erst die Methode aus der Klasse MapProvider und erstelle dann die txt.-Datei?


Wie willst du eine Datei laden, die es nicht gibt?
Ich bin auch raus hier.

Vergiss die Aufgabe und lies dir ein Einsteiger Java Buch durch.


----------



## babuschka (22. Dez 2011)

Muss ich

```
//for each level
     *    for(String line : level)
     *    {  //for each line in each level
     *       //do some super cool stuff :)
```

nicht durch irgendwelche Anweisungen ersetzen?...


----------



## babuschka (22. Dez 2011)

Ich verstehe nicht, an welcher Stelle ich dann MapParser brauche.

Wo baue ich das ein?


----------



## Gast2 (22. Dez 2011)

Sonecc hat gesagt.:


> Ok, ab jetzt klinke ich mich aus.
> Du liest die Hilfe nicht, die Aufgabe nicht und du scheinst nichtmal mit den grundlegendsten Grundlagen von Computern vertraut.
> Das ganze macht so leider keinen Sinn und ist für mich reine Zeitverschwendung.
> Such dir jemanden der dir direkt helfen kann. Am besten solltest du dabei nochmal ganz von vorne anfangen



Ich schließe mich dem an... 

Egal was man dir erklärt du verstehst nichts davon, da dir sämtliche Grundlagen fehlen. Entweder kannst du das alles einfach nicht oder du warst übers Semester einfach zu faul. Ich kann das nicht beurteilen, da wir dir aber auch nicht alles vorkauen können (doch das ist absolut das richtige Wort dafür!) musst du dir ernsthaft Gedanken machen wie das bei dir weitergehen soll. 

Mein Tipp ebenfalls: Such dir dringend einen Kommilliton der das mit dir en Persona macht! 

Ich hab jetzt Urlaub, daher Adé und viel Glück!


----------



## babuschka (22. Dez 2011)

Wieder so eine tolle Hilfe...


Ich habe doch eine normale Frage gestellt:

Wo kommt die Klasse MapParser ins Spiel?

Meine Vermutung: In Zeile 22/23 (also in dem Beispiel)


----------



## Firephoenix (22. Dez 2011)

Nochmal als Zusammenfassung zu dem parser (falls der Begriff unklar ist: http://de.wikipedia.org/wiki/Parser):

Du hast Maps in Form einer .txt-Datei. In der ist das Level in der Form beschrieben die schon genannt wurde (Felder bzw Elemente werden durch ihren buchstaben representiert).
Ein Level ist also erstmal nichts anderes als eine Liste aus Textzeilen, also eine Liste aus String, genauer eine List<String>.

Zum merken: List<String> ist hier eine Liste die die Zeilen deiner Datei enthält.
Jetzt willst du aber nicht nur ein Level sondern gleich mehrere auf einmal laden.
Du kriegst also eine Liste von Leveln, genauer eine Liste von Listen von Zeilen = List<List<String>>

Jetzt zum Zugriff darauf:
Angenommen du hast die Level geladen und irgendwo abgelegt.
Jetzt musst du diese überprüfen.
Da du den Code vermutlich öfters benötigen wirst lohnt es sich wohl die prüfung eines Levels als eigene Methode zu schreiben.
ein Möglicher methodenkopf wäre

```
public boolean validateLevel(List<String> level){

//Implementierung

}
```
Die Methode bekommt das Level als Liste aus Strings und prüft es nach den von dir genannten Kriterien:


>  es komplett von Wänden umgeben ist.
>  genau eine Spielfigur existiert.
>  mindestens ein Ausgang existiert.
>  es rechteckig ist.


Und jetzt gehst du mal in die Java-Api Java Platform SE 6
und schaust dir dort mal die Klassen String und List an.
Dann überlegst du dir was du in deiner Liste aus zeilen genau prüfen willst, suchst in den entsprechenden Klassen nach Methoden die dir helfen können und versucht das ganze einmal.

Gruß


----------



## babuschka (22. Dez 2011)

Damit nicht wieder der Eindruck entsteht, dass ich diese Antwort ignoriere:

Ich komme darauf zurück!!


Aber zuerst nochmal: Wo kommt MapParse denn eigentlich dann ins Spiel?...

Also wo im Code?



Ich muss ja die Klasse MapParse schreiben.

Da brauche ich doch die Methode charAt?

Um die Zeilen durchzugehen und damit das Spielfeld zu beschgreiben?


----------



## Firephoenix (22. Dez 2011)

An deinem Code ist das schwer zu sagen, fehlt evtl noch etwas von der Aufgabenstellung oder vorgegebenem Code?

An sich kannst du dir den MapParser aber vorstellen wie eine Schnittstelle die benutzt wird um Level von der Festplatte zu laden.

Benutzt werden könnte er in einem Menü das sich in der Applikation befindet "Load Level..."
Oder auch beim Programmstart um direkt ein Level zu laden das vorgegeben ist.
Das hängt aber davon ab, wie eure Vorgaben sind, bzw wie du selbst dein Programm gestalten willst.

Gruß


----------



## babuschka (22. Dez 2011)

Habe ich es denn jetzt richtig verstanden, dass ein Element für eine ganze Zeile des Spielfelds steht und dass ich in der Klasse MapParse dann wiederum jede Zeile durchgehen muss und damit das zweidimensionale Arry füllen muss?



Und dass ich dann die Methode aus MapParse dort verwende bei Zeile 22-23?


Edit:

Achso, das ist die ganze Aufgabe 2.

Aber hier noch Aufgabe 3:
Damit das Spiel spielbar wird benotigt ihr noch eine Klasse, die alles zusammenhalt. Entwickelt
dazu die Klasse BoulderDash.
Die Klasse soll zunachst drei Spielwelten von der Festplatte laden. Nehmt dazu Euren MapParser
zur Hilfe. Sind die Welten geladen, soll die erste Welt in der GUI angezeigt werden. Die Benutzung
der Gui lasst sich aus der Doxygen-Dokumentation entnehmen.
Anschlieend werden so lange Spielzuge ausgefuhrt bis die Spielgur entweder zermalmt ist oder
gefressen wurde oder auf den Ausgang bewegt wurde. Im letzteren Fall geht es weiter zum
nachsten Level. Die Punkte bleiben naturlich erhalten.
Ein Spielzug lauft dabei wie folgt ab:
1. frage die Benutzereingabe aus der Gui ab und teile sie dem Spieler-Objekt mit
2. rufe auf dem Spieler-Objekt performTurn() auf
3. rufe auf allen anderen Elementen performTurn() auf
4. Aktualisiere die Gui


----------



## babuschka (22. Dez 2011)

Das ist meine Idee zu der Klasse MapParser:


```
import java.util.List;

//Die Klasse MapParser

public class MapParser{
	
	
	
	Element[][] parseMap(List<String> map){
		
                           Element[][]spielfeld=new Element[map.size()][map.get(1).length()];                          

		for(int i=0; i<=map.size(), i++){
			
			for(int j=0; j<=map.get(i).length(); j++){
			spielfeld[i][j]=map.get(i).charAt(i);
		}
	}
                    return spielfeld;
}
	
}
```


----------



## Firephoenix (22. Dez 2011)

```
spielfeld[i][j]=map.get(i).charAt(i);
```
spielfeld_[j] ist vom Typ Element
map.get(i).charAt(i) enthält zwar semantisch für dich die Information welches Feld das ist,
für Java ist das allerdings nicht zuweisungskompatibel.
Du musst überprüfen welcher Char genau das ist und basierend darauf ein neues Element-Objekt erzeugen (z.B. einen Diamanten)
Gruß_


----------



## babuschka (22. Dez 2011)

Dankesehr.

Morgen poste ich meine veränderten Ideen.

Vielleicht schaust Du es Dir ja an.


----------



## R3van (28. Dez 2011)

Hallo java_,

Da in der Lehrveranstaltung Praktische Informatik I an der Universität Bremen genau die selbe Aufgabe gestellt wurde (Wortgleich ), gehe ich davon aus, dass du ein Teilnehmer dieser Veranstaltung bist. 
Ich finde es ein bisschen schade, dass du deine Fragen zu erst in diesem Forum und nicht an uns (die Tutoren) stellst. Erwecken wir den Eindruck, dass wir dir/euch nicht helfen würden?? Es ist unsere Aufgabe euch bei Problemen jeder Art zu helfen (und wenn es die Frage ist, was ein JFileChooser ist). Bei der Aufgabe mit der Kneipe hast du dich auch erst an das Forum gewendet http://www.java-forum.org/java-basics-anfaenger-themen/128437-modellierung-kneipe.html ... 

Wenn du weiterhin noch Fragen hast, stehe(n) ich/wir dir gerne zur Verfügung. Du kannst im StudIP einfach ins Forum schreiben, oder dich an einen(oder deinem) Tutor wenden.

Grüße


----------



## babuschka (1. Jan 2012)

R3van hat gesagt.:


> Hallo java_,
> 
> Da in der Lehrveranstaltung Praktische Informatik I an der Universität Bremen genau die selbe Aufgabe gestellt wurde (Wortgleich ), gehe ich davon aus, dass du ein Teilnehmer dieser Veranstaltung bist.



Das ist der Fall.



Ich habe nicht den Eindruck, daß mir nicht geholfen würde; im Gegenteil, mir wurde schon oft geduldig geholfen.


Ich scheue mich auch nicht, meine Fragen an den Tutor zu stellen, nur kann ich wohl kaum Fragen stellen wie "Wie geht das?" - wenn ich mir nicht vorher den Hauch einer Ahnung verschafft habe. Daher stelle ich meine Fragen zuerst hier.


----------



## babuschka (1. Jan 2012)

*Erstmal wünsche ich ein gutes Jahr 2012!*

Und dann habe ich meine Klasse "MapParser" ein bisschen weiterentwickelt. Dabei habe ich versucht, mich an die Tipps von Firephoenix zu halten:


```
import java.util.List;
 
//Die Klasse MapParser
 
public class MapParser{
	List<String> map;
	Element[][]spielfeld=new Element[map.size()][map.get(1).length()];
    
    Element[][] parseMap(List<String> map){
        
    	   
                           char certainchar;
                           Element newElement;
 
        for(int i=0; i<=map.size(); i++){
            
            for(int j=0; j<=map.get(i).length(); j++){
            certainchar=map.get(i).charAt(i);
            switch(certainchar){
            
            case'P': newElement=new Player(i,j,this); spielfeld[i][j]=newElement; break;
            case'E': newElement=new Erde(i,j,this); spielfeld[i][j]=newElement;break; 
            case'S': newElement=new Stein(i,j,this); spielfeld[i][j]=newElement;break;
            case'M': newElement=new Monster(i,j,this); spielfeld[i][j]=newElement;break;
            case'D': newElement=new Diamant(i,j,this); spielfeld[i][j]=newElement;break;
            case'G': newElement=new Ausgang(i,j,this); spielfeld[i][j]=newElement;break;
            case' ': newElement=new LeeresFeld(i,j,this); spielfeld[i][j]=newElement;break;
            }
            
            
            }
        }
    
                    return spielfeld;
    }       


public char getSpielfeld(int i, int j){
	return spielfeld[i][j].getChar();
}

public void setSpielfeld(int i, int j, char k){
	
	Element newElement2;
	switch(k){
    
    case'P': newElement2=new Player(i,j,this); spielfeld[i][j]=newElement2; break;
    case'E': newElement2=new Erde(i,j,this); spielfeld[i][j]=newElement2;break; 
    case'S': newElement2=new Stein(i,j,this); spielfeld[i][j]=newElement2;break;
    case'M': newElement2=new Monster(i,j,this); spielfeld[i][j]=newElement2;break;
    case'D': newElement2=new Diamant(i,j,this); spielfeld[i][j]=newElement2;break;
    case'G': newElement2=new Ausgang(i,j,this); spielfeld[i][j]=newElement2;break;
    case' ': newElement2=new LeeresFeld(i,j,this); spielfeld[i][j]=newElement2;break;
    }
	
}

}
```

Wäre das so besser?


Jetzt fehlt noch der Test, ob das Spielfeld valide ist.
Darum kümmere ich mich als nächstes.


----------



## R3van (1. Jan 2012)

Versuche etwas mehr in Komponenten zu denken. Du solltest zunächst eine Klasse haben, welche das Spielfeld repräsentiert und nichts anderes. Sie könnte weiterhin Methoden anbieten, welche dir Zugriff auf die Elemente der Spielwelt gewährt. Eine solche Methode könnte zB. sein:


```
public Element getElementAt(int x, int y)
```
Ich nenne diese Klasse einfach mal World (Map wäre eine ungute Wahl, da es in Java bereits ein solches Interface gibt, welches in einem völlig anderen Kontext steht)

Als nächstes benötigst du eine Komponente, welche dir es ermöglicht Spielfelder anhand einer String-Liste zu erzeugen. Eine, in meinen Augen, gut geeignete Methode könnte doch sein:


```
public static World createWorld(List<String> list)
```
Diese Methode erzeugt nun, so wie du es zB. gemacht hast, die Elemente und schreibt sie in das Array rein. Sinnig wäre es bestimmt einem Element die Referenz auf das jeweilige Array im Konstruktor mitzugeben.


----------



## babuschka (1. Jan 2012)

Danke, ich versuche es noch besser zu strukturieren nach Deinen Tipps.


Jetzt nochmal eine Frage zur Klasse "Player". Die sieht bei mir sehr länglich aus, ich muss da noch besser zusammenfassen. Im Moment geht es mir aber um die Zeile 31, wo ich versuche, das Drücken der Pfeiltasten einzubauen. Da kommen die Fehlermeldungen:

1. illegal start of expression
2. ; expected

Doch ich weiß nicht, wieso.




```
//Die Klasse Spieler

public class Player extends Teilnehmer implements Element, KeyListener{

char ElementSymbol1;
char ElementSymbol2;
char ElementSymbol3;
char ElementSymbol4;


public Player(int x_position, int y_position, MapParser map){

   super(x_position, y_position, map);

}

public char getChar(){

   return 'P';
}

public void performTurn(){
	
	

ElementSymbol1=spielfeld.getSpielfeld(this.x_position+1,this.y_position);
ElementSymbol2=spielfeld.getSpielfeld(this.x_position-1,this.y_position);
ElementSymbol3=spielfeld.getSpielfeld(this.x_position,this.y_position+1);
ElementSymbol4=spielfeld.getSpielfeld(this.x_position,this.y_position-1);

  public void keyPressed(KeyEvent e){
	  
	  if(keyEvent.getKeyChar()==KeyEvent.Char_UNDEFINED){
		  if(keyEvent.getKeyCode()==KeyEvent.VK_RIGHT){

                                if(ElementSymbol1==' '){
                                      this.x_position=this.x_position+1;
                                      spielfeld.setSpielfeld(this.x_position,this.y_position, this.getChar());
                                      
                               }
                                if(ElementSymbol1=='S'){
                                
                               }
                                 if(ElementSymbol1=='E'){
                                  
                                  this.x_position=this.x_position+1;
                                  spielfeld.setSpielfeld(this.x_position,this.y_position, this.getChar());
                                  
                             }
                               if(ElementSymbol1=='M'){
                               this.x_position=this.x_position+1;
                               spielfeld.setSpielfeld(this.x_position,this.y_position, this.getChar()); 
                               System.out.println("GameOver");
                               
                             }
                              if(ElementSymbol1=='G'){
                                this.x_position=this.x_position+1;
                                spielfeld.setSpielfeld(this.x_position,this.y_position, this.getChar());
                               System.out.println("LevelFinished");
                               
                             }
                              break;
                              
	  }
	  }

		  if(keyEvent.getKeyChar()==KeyEvent.Char_UNDEFINED){
			  if(keyEvent.getKeyCode()==KeyEvent.VK_LEFT){
	  
	                   if(ElementSymbol2==' '){
                       this.x_position=this.x_position-1;
                       spielfeld.setSpielfeld(this.x_position, this.y_position, this.getChar());
                       
                  }
                    if(ElementSymbol2=='S'){
                        
                 }
                    
  
                        if(ElementSymbol2=='E'){
                       
                         this.x_position=this.x_position-1;
                       spielfeld.setSpielfeld(this.x_position,this.y_position, this.getChar());
                        
                      }
                   if(ElementSymbol2=='M'){
                   this.x_position=this.x_position-1;
                   spielfeld.setSpielfeld(this.x_position,this.y_position, this.getChar());
                  System.out.println("GameOver");
                   
                  }
                 if(ElementSymbol2=='G'){
                 this.x_position=this.x_position-1;
                 spielfeld.setSpielfeld(this.x_position,this.y_position, this.getChar());
                 System.out.println("LevelFinished");
                 
              }
                 break;
	  }
		  }
	  
	  
			  if(keyEvent.getKeyChar()==KeyEvent.Char_UNDEFINED){
				  if(keyEvent.getKeyCode()==KeyEvent.VK_UP){
                       
		               if(ElementSymbol3==' '){
                       this.y_position=this.y_position+1;
                       spielfeld.setSpielfeld(this.x_position,this.y_position, this.getChar());
                       break;
                  }
                  if(ElementSymbol3=='S'){
                       break;
                 }
                 if(ElementSymbol3=='E'){
                      
                      this.y_position=this.y_position+1;
                      spielfeld.setSpielfeld(this.x_position,this.y_position, this.getChar());
                      break;
                }
                 if(ElementSymbol3=='M'){
                    this.y_position=this.y_position+1;
                    spielfeld.setSpielfeld(this.x_position,this.y_position, this.getChar());
                    System.out.println("GameOver");
                    break;
               }
                if(ElementSymbol3=='G'){
                  this.y_position=this.y_position+1;
                  spielfeld.setSpielfeld(this.x_position, this.y_position, this.getChar());
                  System.out.println("LevelFinished");
                  break;
                }
	  }
			  }
	  
	  

				  if(keyEvent.getKeyChar()==KeyEvent.Char_UNDEFINED){
					  if(keyEvent.getKeyCode()==KeyEvent.VK_DOWN){
	  
	                         if(ElementSymbol4==' '){
                             this.y_position=this.y_position-1;
                             spielfeld.setSpielfeld(this.x_position,this.y_position, this.getChar());
                             break;
                         }
                       if(ElementSymbol4=='S'){
                           break;
                        }
                       if(ElementSymbol4=='E'){
                           
                           this.y_position=this.y_position-1;
                           spielfeld.setSpielfeld(this.x_position,this.y_position, this.getChar());
                           break;
                       }
                     if(ElementSymbol4=='M'){
                          this.y_position=this.y_position-1;
                          spielfeld.setSpielfeld(this.x_position, this.y_position, this.getChar());
                          System.out.println("GameOver");
                          break;
                      }
                    if(ElementSymbol4=='G'){
                         this.y_position=this.y_position-1;
                         spielfeld.setSpielfeld(this.x_position, this.y_position, this.getChar());
                         System.out.println("LevelFinished");
                         break;
                      }
					  }
				  }
	 
  }
}

}
```


----------



## R3van (1. Jan 2012)

Schau mal in Zeile 22, dort steht:

```
public void performTurn(){
```
Dh. du definierst hier eine neue Methode mit dem Namen performTurn()
In Zeile 33 steht dann:

```
public void keyPressed(KeyEvent e){
```
Dh. du definierst eine weitere Methode, jedoch im Methodenrumpf der Methode performTurn(), und das geht natürlich nicht... Dieses Konstrukt erscheint mir auch etwas komisch, da auf dem Aufgabenzettel steht, dass die GUI benutzt werden soll um die gedrückte Taste zu ermitteln. Was du hier, so glaube ich jetzt erst mal, gemacht hast, ist den Code der Methode step() aus GUI.java kopiert. Dies war aber nicht Sinn der Übung. Lies doch bitte nochmal den Zettel und vor allem die Doku zu GUI.java (Doxygen), dort erfährst du, wie du diese Klasse zu verwenden hast.


----------



## babuschka (1. Jan 2012)

Das mit der GUI habe ich gelesen.

Zu meiner Schande muss ich aber gestehen, dass ich nichtmal weiß, was das ist.

Deswegen habe ich versucht, das Ermitteln der gedrückten Taste so hinzubekommen.


----------



## R3van (1. Jan 2012)

GUI ist ein Akronym für *G*raphical *u*ser *i*nterface und bezeichnet halt eben eine grafische Schnittstelle für den Benutzer eines Programms. Der Editor in dem du zB. die Texte schreibst für dieses Forum ist auch nur eine GUI um komfortabel Nachricht in diesem Forum zu verfassen.

Also, im Sinne der Aufgabe haben wir euch die Arbeit zum Entwickeln einer GUI abgenommen und liefern diese halt eben in der Datei GUI.java mit. Praktischer Weise hat die Klasse GUI eine Methode step(), welche eine ganz nützliche Funktion bereitstellt. Um dir diese Funktion anzeigen zu lassen generiere doch erst mal die Doxygen-Doku zu dieser Datei. Dann sollte dir einiges klarer werden


----------



## babuschka (1. Jan 2012)

Ah, danke!

Ich habe dann dies mit folgender Fehlermeldung:

Player.java:39 cannot find symbol
symbol: method step()
location: class Player
stepcontrol=step();




```
//Die Klasse Spieler





public class Player extends Teilnehmer implements Element{

char ElementSymbol1;
char ElementSymbol2;
char ElementSymbol3;
char ElementSymbol4;



public Player(int x_position, int y_position, MapParser map){

   super(x_position, y_position, map);

}

public char getChar(){

   return 'P';
}

public void performTurn(){
	
	

ElementSymbol1=spielfeld.getSpielfeld(this.x_position+1,this.y_position);
ElementSymbol2=spielfeld.getSpielfeld(this.x_position-1,this.y_position);
ElementSymbol3=spielfeld.getSpielfeld(this.x_position,this.y_position+1);
ElementSymbol4=spielfeld.getSpielfeld(this.x_position,this.y_position-1);

  
	  String stepcontrol;
	  
	  stepcontrol=step();
	  
	  if(stepcontrol=="RIGHT"){

                                if(ElementSymbol1==' '){
                                      this.x_position=this.x_position+1;
                                      spielfeld.setSpielfeld(this.x_position,this.y_position, this.getChar());
                                      
                               }
                                if(ElementSymbol1=='S'){
                                
                               }
                                 if(ElementSymbol1=='E'){
                                  
                                  this.x_position=this.x_position+1;
                                  spielfeld.setSpielfeld(this.x_position,this.y_position, this.getChar());
                                  
                             }
                               if(ElementSymbol1=='M'){
                               this.x_position=this.x_position+1;
                               spielfeld.setSpielfeld(this.x_position,this.y_position, this.getChar()); 
                               System.out.println("GameOver");
                               
                             }
                              if(ElementSymbol1=='G'){
                                this.x_position=this.x_position+1;
                                spielfeld.setSpielfeld(this.x_position,this.y_position, this.getChar());
                               System.out.println("LevelFinished");
                               
                             }
                              
                              
	  }
	  

		  if(stepcontrol=="LEFT"){
	  
	                   if(ElementSymbol2==' '){
                       this.x_position=this.x_position-1;
                       spielfeld.setSpielfeld(this.x_position, this.y_position, this.getChar());
                       
                  }
                    if(ElementSymbol2=='S'){
                        
                 }
                    
  
                        if(ElementSymbol2=='E'){
                       
                         this.x_position=this.x_position-1;
                       spielfeld.setSpielfeld(this.x_position,this.y_position, this.getChar());
                        
                      }
                   if(ElementSymbol2=='M'){
                   this.x_position=this.x_position-1;
                   spielfeld.setSpielfeld(this.x_position,this.y_position, this.getChar());
                  System.out.println("GameOver");
                   
                  }
                 if(ElementSymbol2=='G'){
                 this.x_position=this.x_position-1;
                 spielfeld.setSpielfeld(this.x_position,this.y_position, this.getChar());
                 System.out.println("LevelFinished");
                 
              }
                 
	  }
		  
	  
	  
			  if(stepcontrol=="UP"){
                       
		               if(ElementSymbol3==' '){
                       this.y_position=this.y_position+1;
                       spielfeld.setSpielfeld(this.x_position,this.y_position, this.getChar());
                       
                  }
                  if(ElementSymbol3=='S'){
                       
                 }
                 if(ElementSymbol3=='E'){
                      
                      this.y_position=this.y_position+1;
                      spielfeld.setSpielfeld(this.x_position,this.y_position, this.getChar());
                      
                }
                 if(ElementSymbol3=='M'){
                    this.y_position=this.y_position+1;
                    spielfeld.setSpielfeld(this.x_position,this.y_position, this.getChar());
                    System.out.println("GameOver");
                    
               }
                if(ElementSymbol3=='G'){
                  this.y_position=this.y_position+1;
                  spielfeld.setSpielfeld(this.x_position, this.y_position, this.getChar());
                  System.out.println("LevelFinished");
                  
                }
	  }
			  
	  
	  

				  if(stepcontrol=="DOWN"){
	  
	                         if(ElementSymbol4==' '){
                             this.y_position=this.y_position-1;
                             spielfeld.setSpielfeld(this.x_position,this.y_position, this.getChar());
                             
                         }
                       if(ElementSymbol4=='S'){
                           
                        }
                       if(ElementSymbol4=='E'){
                           
                           this.y_position=this.y_position-1;
                           spielfeld.setSpielfeld(this.x_position,this.y_position, this.getChar());
                           
                       }
                     if(ElementSymbol4=='M'){
                          this.y_position=this.y_position-1;
                          spielfeld.setSpielfeld(this.x_position, this.y_position, this.getChar());
                          System.out.println("GameOver");
                          
                      }
                    if(ElementSymbol4=='G'){
                         this.y_position=this.y_position-1;
                         spielfeld.setSpielfeld(this.x_position, this.y_position, this.getChar());
                         System.out.println("LevelFinished");
                         
                      }
					  }
				  
	 
  
}

}
```







Und noch eine Frage:

Ich muss nur in der Klasse "Player" die Methode step benutzen?

(Man benutzt doch nur für den Spieler die Pfeiltasten.)


----------



## R3van (1. Jan 2012)

Hmm warum rufst du denn einfach step() auf... das ist doch eine Methode der Klasse GUI. Wie du eine Methode einer Klasse (eines Objektes) aufrufst, solltest du schon wissen.


----------



## babuschka (1. Jan 2012)

Ja, mit dem Punktoperator.

Muss ich auch erst eine Instanz der Klasse GUI erzeugen? (Ich hab sie gui genannt.)

Dann kommt eine andere Fehlermeldung:

Zeile 36: '(' or '[' expected



```
//Die Klasse Spieler
 
 
 
 
 
public class Player extends Teilnehmer implements Element{
 
char ElementSymbol1;
char ElementSymbol2;
char ElementSymbol3;
char ElementSymbol4;
 
 
 
public Player(int x_position, int y_position, MapParser map){
 
   super(x_position, y_position, map);
 
}
 
public char getChar(){
 
   return 'P';
}
 
public void performTurn(){
    
    
 
ElementSymbol1=spielfeld.getSpielfeld(this.x_position+1,this.y_position);
ElementSymbol2=spielfeld.getSpielfeld(this.x_position-1,this.y_position);
ElementSymbol3=spielfeld.getSpielfeld(this.x_position,this.y_position+1);
ElementSymbol4=spielfeld.getSpielfeld(this.x_position,this.y_position-1);
 
      GUI gui=new GUI;
      gui.Key stepcontrol;
      
      stepcontrol=gui.step();
      
      if(stepcontrol==Key.RIGHT){
 
                                if(ElementSymbol1==' '){
                                      this.x_position=this.x_position+1;
                                      spielfeld.setSpielfeld(this.x_position,this.y_position, this.getChar());
                                      
                               }
                                if(ElementSymbol1=='S'){
                                
                               }
                                 if(ElementSymbol1=='E'){
                                  
                                  this.x_position=this.x_position+1;
                                  spielfeld.setSpielfeld(this.x_position,this.y_position, this.getChar());
                                  
                             }
                               if(ElementSymbol1=='M'){
                               this.x_position=this.x_position+1;
                               spielfeld.setSpielfeld(this.x_position,this.y_position, this.getChar()); 
                               System.out.println("GameOver");
                               
                             }
                              if(ElementSymbol1=='G'){
                                this.x_position=this.x_position+1;
                                spielfeld.setSpielfeld(this.x_position,this.y_position, this.getChar());
                               System.out.println("LevelFinished");
                               
                             }
                              
                              
      }
      
 
          if(stepcontrol==Key.LEFT){
      
                       if(ElementSymbol2==' '){
                       this.x_position=this.x_position-1;
                       spielfeld.setSpielfeld(this.x_position, this.y_position, this.getChar());
                       
                  }
                    if(ElementSymbol2=='S'){
                        
                 }
                    
  
                        if(ElementSymbol2=='E'){
                       
                         this.x_position=this.x_position-1;
                       spielfeld.setSpielfeld(this.x_position,this.y_position, this.getChar());
                        
                      }
                   if(ElementSymbol2=='M'){
                   this.x_position=this.x_position-1;
                   spielfeld.setSpielfeld(this.x_position,this.y_position, this.getChar());
                  System.out.println("GameOver");
                   
                  }
                 if(ElementSymbol2=='G'){
                 this.x_position=this.x_position-1;
                 spielfeld.setSpielfeld(this.x_position,this.y_position, this.getChar());
                 System.out.println("LevelFinished");
                 
              }
                 
      }
          
      
      
              if(stepcontrol==Key.UP){
                       
                       if(ElementSymbol3==' '){
                       this.y_position=this.y_position+1;
                       spielfeld.setSpielfeld(this.x_position,this.y_position, this.getChar());
                       
                  }
                  if(ElementSymbol3=='S'){
                       
                 }
                 if(ElementSymbol3=='E'){
                      
                      this.y_position=this.y_position+1;
                      spielfeld.setSpielfeld(this.x_position,this.y_position, this.getChar());
                      
                }
                 if(ElementSymbol3=='M'){
                    this.y_position=this.y_position+1;
                    spielfeld.setSpielfeld(this.x_position,this.y_position, this.getChar());
                    System.out.println("GameOver");
                    
               }
                if(ElementSymbol3=='G'){
                  this.y_position=this.y_position+1;
                  spielfeld.setSpielfeld(this.x_position, this.y_position, this.getChar());
                  System.out.println("LevelFinished");
                  
                }
      }
              
      
      
 
                  if(stepcontrol==Key.DOWN){
      
                             if(ElementSymbol4==' '){
                             this.y_position=this.y_position-1;
                             spielfeld.setSpielfeld(this.x_position,this.y_position, this.getChar());
                             
                         }
                       if(ElementSymbol4=='S'){
                           
                        }
                       if(ElementSymbol4=='E'){
                           
                           this.y_position=this.y_position-1;
                           spielfeld.setSpielfeld(this.x_position,this.y_position, this.getChar());
                           
                       }
                     if(ElementSymbol4=='M'){
                          this.y_position=this.y_position-1;
                          spielfeld.setSpielfeld(this.x_position, this.y_position, this.getChar());
                          System.out.println("GameOver");
                          
                      }
                    if(ElementSymbol4=='G'){
                         this.y_position=this.y_position-1;
                         spielfeld.setSpielfeld(this.x_position, this.y_position, this.getChar());
                         System.out.println("LevelFinished");
                         
                      }
                      }
                  
     
  
}
 
}
```


----------



## R3van (1. Jan 2012)

Ich kann schon verstehen, warum einige Personen in diesem Forum dir nicht mehr helfen wollen. Es wirkt leider immer so, als wenn du unsere Vorschläge annimmst, etwas hincodest, kompilieren willst und wenn dass dann nicht klappt, also ein Kompilerfehler erscheint, postest du die Nachricht hier, ohne dir wohl Gedanken gemacht zu haben, was da eigentlich steht. Bei diesem Fehler werde ich dir nicht helfen, den musst du wirklich alleine finden, vor allem weil die Ausgabe wirklich alles sagt was du benötigst... Sobald das läuft, du also die Methode step aufrufen kannst, werde ich dir weiter helfen.


----------



## babuschka (1. Jan 2012)

Ich möchte es auch alleine hinbekommen, nur weiß ich eben nicht, ob zum Beispiel diese Zeilen richtitg sind:


37
39
41


----------



## babuschka (1. Jan 2012)

Okay, ich muss schreiben:


```
GUI gui=new GUI();
```

Wenn ich das mache, entstehen aber wiederum neue Fehlermeldungen, nämlich steht da dann, daß die Variablen Key.DOWN usw. unbekannt sind...



Da weiß ich jetzt aber wirklich nicht weiter.
So blöde das rüberkommen mag.


----------



## gman (1. Jan 2012)

> Zeile 36: '(' or '[' expected



Ich weise einfach nochmal darauf hin! Kümmer dich doch erstmal darum.
Frag dich mal was du mit den Zeilen erreichen willst und schau dann in ein
Buch wie man das umsetzt (Stichwort: Konstruktor).

Edit: Mist, zu langsam ;-) Dieser Beitrag hat sich damit wohl erledigt.


----------



## gman (1. Jan 2012)

> nämlich steht da dann, daß die Variablen Key.DOWN usw. unbekannt sind



Wo sollen die denn deiner Meinung nach herkommen?


----------



## R3van (1. Jan 2012)

Das steht in der... ich erwähne es nochmal... Doxygen-Doku.... generiere diese doch bitte einmal.


----------



## babuschka (1. Jan 2012)

Dort steht, daß LEFT, RIGHT usw. zu dem Aufzählungstypen Key gehören.



```
GUI gui=new GUI();
Key stepcontrol;

stepcontrol = gui.step();

if(stepcontrol == Key.RIGHT){...}


...
```


Sorry, ich sehe nicht, wie das gehen soll.


----------



## R3van (1. Jan 2012)

Das Enum ist in der Klasse GUI spezifiziert. Also:

```
GUI.Key key = gui.step();
```

Der Vergleich sieht dann wohl so aus:

```
switch(key) {
           case: GUI.Key.LEFT
...
```


----------



## babuschka (1. Jan 2012)

Okay, das man als TYP 


```
GUI.KEY
```

nehmen muss, weil die Aufzählung in der Klasse GUI steht, war mir nicht klar.



Letzte blöde Frage für heute: 

Wieso nicht:


```
gui.Key
```
?


----------



## babuschka (1. Jan 2012)

Wieder so eine schlimme Frage?!


----------



## babuschka (2. Jan 2012)

Hallo, wie kann ich schauen, ob ein Level rechteckig ist?




Für die Überprüfung, ob ein Level genau einen Spieler und mindestens einen Ausgang hat und von Wänden umgeben ist, habe ich jeweils eine Methode für einen String geschrieben, die ich dann in der Methode, in der ich teste, ob dies für ein Level gilt, verwende.

Nur zu der Überprüfung, ob das Level rechteckig ist, fällt mir nichts ein.


----------



## Firephoenix (2. Jan 2012)

Du kriegst eine Liste aus Strings als Level:
(Element der Liste) "String"
(0) "XXXX"
(1) "XXXX"
(2) "XXXX"

und eine 2.:
(0) "XXXX"
(1) "XXXXXX"
(2) "XXXX"


bzw eine 3.:,
(0) "XXXX"
(1) "XXXX"
(2) "XXXX"
(3) "X"

warum sind die 2. und die 3. nicht Rechteckig, woran erkennst du den Unterschied.

Wo die Klasse String ist weißt du, eine passende Methode findet man schnell und wenn man dann nur noch das runterschreibt was man selber per hand macht "alle strings durchgehen und auf gleiche länge prüfen" (lösung *hust*) ist man fertig.

Das ist damit auch mein letzter Post in dem Thread - ich sehe es nicht ein einem Studenten sowas vorkauen zu müssen. Das hat nichtmal mehr was mit Java zu tun (ansonsten wäre sowas gekommen wie:
"Warum klappt meine Rechteck-prüfung mit den 2 verschachtelten for-schleifen und den paar Variablen nicht, könnte das an der Methode .irgendwas() aus der Klasse String liegen oder habe ich da einen denkfehler drin")
Hier fehlen einfach Grundsätzliche Skills wie Abstraktion, ein Grundwissen über die Sprache kann man nach 2.5 Monaten vorraussetzen, ebenso wie OOP-Fertigkeiten - aber auch hier kommen zuviele Grundsatzfragen. Und Selbststudium bedeutet sich selbst Wissen suchen und aneignen können - eine Grundlage auf einer Universität - und nicht sich alles zusammenfragen zu müssen, selbiges kann man machen wenns mal echt irgendwo hängt und man tiefere Fachprobleme hat (und hinter einem Konstruktoraufruf die () zu vergessen und dafür gleich mehrfach zu posten ;( )


----------



## babuschka (2. Jan 2012)

Mehr als mir Mühe geben kann ich auch nicht.
Ich muss mir auch nicht hier ständig anhören, wie unfähig ich bin.
Ich bin doch nicht hier, um mich demütigen zu lassen.
Dann lass es halt sein, wenn es unter Deiner Würde ist.

Langsam habe ich es oft genug gehört.



Also dies habe ich mir überlegt.
Ich hoffe, es hagelt jetzt nicht wieder böse Kritik. Sollen sich halt alle raushalten, die es zu doof finden. Ich finde auch so Manches zu doof, zum Beispiel, daß ich in einem Hilfe-Forum keine Hilfe, sondern demotivierende Backpfeifen bekomme.

Die Kritik ist ja um Gottes Willen angekommen und sie ist berechtigt.
Dennoch muss man sie nicht immer und immer und immer wieder wiederholen.


Und dann noch ein Wort zu dem hilfsbereiten Tutor, der hier netterweise geholfen hat: Hieß es in Deinen eigenen Worten nicht sinngemäß, daß man jede Frage stellen könne?

Achso, aha, ich verstehe. Und schon drei Messages weiter muss ich mir dann anhören, daß es nur allzu verständlich ist, daß mir hier nicht geholfen wird und schon weitere zwei Messages weiter fließen dann nette indirekte Kommentare ein wie "... - ich wiederhole es nochmal----"..

Aha, so war das also gemeint, daß man jede Frage stellen kann.
Können ja, aber auch mögen?


(Und nochmal: Ich sehe es ein, daß ich nicht talentiert bin und frage, frage, frage. Man werfe mir also zumindest bitte nicht vor, daß ich selbst die Kritik ausblende.)


```
//Es folgen Methoden, die für den Test der Validität eines Levels benutzt werden.

//Zähle die Anzahl der Spieler.

public int countPlayer(String string, char aChar){

  int counter=0;

    for(int i=0; i<string.length(); i++){
            
               if(string.charAt(i)==aChar){
                      counter++;
                  }
        
     }

return counter;
}


//Teste, ob am Anfang und Ende eines Strings ein bestimmes Char steht.

public boolean sourroundedByWalls(String string){

   boolean sourrounded=true;

         if(string.charAt(0)!='W' || string.charAt(string.length()-1)!='W'){
                  sourrounded=false;
          }

     return sourrounded;
}


//Zähle die Anzahl der Ausgänge.

public int countExists(String string, char aChar){

  int counter2=0;

    for(int i=0; i<string.length(); i++){
            
               if(string.charAt(i)==aChar){
                      counter2++;
                  }
        
     }
        return counter2;

}

//Teste, ob ein übergebenes Level valide ist (mittels der obigen Methoden).
//1. Genau ein Player?
//2. Level von Wänden umgeben?
//3. Mindestens ein Ausgang?
//4. Spielfeld rechteckig?


public boolean validateLevel(List<String> level){
	
	boolean validate=false;
	int counter=0;
	int counter2=0;
	boolean sourrounded=false;

 for(int j=0; j<level.size(); j++){

             counter=countPlayer(level.get(j), 'P');
             sourrounded=sourroundedByWalls(level.get(j));
             counter2=countExists(level.get(j), 'G');
             
    }
         
 if(counter==1 && sourrounded==true && counter2>=1){
	    validate=true;
 }
 
 
 
      return validate;
}
```

(Das mit der rechteckigen Form fehlt noch.)

Doch wenn ich die letzte Methode jetzt anwenden will, also das in Zeile 9 schreibe, funktioniert es nicht. Es fehlt ein identifier, steht dort.



```
import java.util.List;
 
//Die Klasse MapParser
 
public class MapParser{
	List<String> map;
	Element[][]spielfeld=new Element[map.size()][map.get(1).length()];
	
	validateLevel(map);
	
	
    
    Element[][] parseMap(List<String> map){
        
    	   
                           char certainchar;
                           Element newElement;
 
        for(int i=0; i<=map.size(); i++){
            
            for(int j=0; j<=map.get(i).length(); j++){
            certainchar=map.get(i).charAt(i);
            switch(certainchar){
            
            case'P': newElement=new Player(i,j,this); spielfeld[i][j]=newElement; break;
            case'E': newElement=new Erde(i,j,this); spielfeld[i][j]=newElement;break; 
            case'S': newElement=new Stein(i,j,this); spielfeld[i][j]=newElement;break;
            case'M': newElement=new Monster(i,j,this); spielfeld[i][j]=newElement;break;
            case'D': newElement=new Diamant(i,j,this); spielfeld[i][j]=newElement;break;
            case'G': newElement=new Ausgang(i,j,this); spielfeld[i][j]=newElement;break;
            case' ': newElement=new LeeresFeld(i,j,this); spielfeld[i][j]=newElement;break;
            }
            
            
            }
        }
    
                    return spielfeld;
    }
```


----------



## R3van (2. Jan 2012)

Du kannst uns und damit meine ich ausschließlich uns Tutoren jede Frage stellen, die du möchtest. Wir werden dir auch jeder Zeit gerne weiterhelfen, denn das ist unser Job, dafür werden wir bezahlt. Für Mitglieder dieses Forums gilt das jedoch nicht, du darfst nicht voraussetzen, dass dir hier jeder sofort helfen wird, da alles hier auf einer freiwilligen Basis geschieht.

Vlt. sollte ich das Wort Hilfe auch mal etwas anders beschreiben. Hilfe bedeutet, dass wir die die Richtung in der du selbstständig lernen sollst vorgeben. Die Vorlesung vermittelt dabei tatsächlichen Inhalt, was nicht unbedingt bedeutet, dass die Vorlesung vollständig sein muss, sondern eher Ausschnitte von den Themen zeigt, in denen du dich gerade bewegen solltest. Die Übungsaufgaben und das Tutorium sind nun dazu da, um das Wissen, welches du dir eben aneignen sollst, praktisch um zu setzten. In der Informatik lässt sich dies besonders gut in Programmieraufgaben umsetzten. 

Wir Tutoren helfen euch bei den Übungen. Wenn ihr euch zB. total verrennt, dann helfen wir euch mit Tipps wieder auf die Spur zu kommen. Wenn ihr also zu uns kommen würdet und uns fragen würdet, wie ihr die Länge eines Strings ermitteln könnt, dann würden wir euch sagen, hey schaut doch mal in Java-Doc von String nach, da gibts einige Methoden die euch evtl. gut helfen können. Ob wir in den Tutorien Kompilerfehler etc. fixen steht uns frei. Die Devise lautet: Hilfe zur Selbsthilfe. 

Wenn ich dir also sage, schau doch mal bitte in die Doxygen-Doku der Klasse GUI nach, dann tu das doch einfach erst mal. Dann würde sich bestimmt auch die Frage erübrigen, welchen Rückgabetyp die Methode step() hat und wo dieses Enum definiert ist. Ich werde dir nun diese Ausschnitt einfach mal hier posten:

/**
   * This method implements one step of the Boulder Dash game. If this method
   * is called for the first time after setting a new level 
   * ({@link setLevel(int, Element[][])}) a countdown is displayed. After that 
   * this method sleeps for 50ms and then determines and returns the first 
   * key press that has not yet been processed. 
   * This means that subsequent key presses will be ignored until the first 
   * key press has been handled. If no key has been pressed, this method 
   * returns the element @em NONE of the enumeration {@link GUI.Key}.
   * 
   * @return the pressed key
   */

Niemand hier möchtet dich fertig machen oder dir nicht weiterhelfen. Jedoch, und das wirst du lernen müssen, heißt Studium immer selbstständiges lernen. 

Leider muss ich Firephoenix recht geben. Du scheinst noch viele Probleme mit den Grundlagen zu haben. Wenn du diese nicht umgehend beseitigst, dann sehe ich da große Probleme auf dich zukommen... Diese Probleme können wir (also der Dozent und wir Tutoren) nicht mehr für dich lösen, da der Stoff der Vorlesung bereits viel zu fortgeschritten ist. Ich würde dir empfehlen ein Grundlagenbuch raus zu holen und nochmal alles ganz von vorne durch zu gehen.


----------



## babuschka (2. Jan 2012)

Alles sicher weise gesprochene Worte, das möchte ich auch gar nicht anzweifeln.

Vielleicht zieht man ja aber in Erwägung, daß man aus dieser Doxygen-Dokumentation durchaus auch nicht schlau werden kann.

Mir ist zum Beispiel trotz dieses zitierten Ausdrucks nicht klar, daß der Rückgabetyp

GUI.Key

ist und es stellt sich mir noch immer die Frage, wieso der Rückgabetyp nicht 

gui.Key 

ist, da ich ja schließlich eine neue Instanz der Klasse GUI erzeugt habe.



Wenn auf solche Fragen aber immer die Antwort kommt, man müsste bei den Grundlagen anfangen, verstehe ich das nicht. Sowas SIND doch Grundlagen. Und so tritt man immer auf der Stelle und ist, so viel kann ich sagen, sicherlich nicht weniger frustriert als die Helfer, die den Eindruck haben, man käme keinen Schritt voran. Wie denn aber auch, wenn man immer die Antwort bekommt, dieses oder jenes sei doch Grundlagenwissen und müsse man so herausfinden. Schön und gut und sicher in den meisten Fällen wahr, aber nicht immer.

Ich muss mir doch jetzt nicht wieder angucken, was ein Rückgabetyp ist, das ist mir klar. Wenn ich mir jetzt meine Grundlagenbücher hernehme und das nachschlage, sehe ich nicht, wie mir das in diesem konkreten Fall weiterhelfen soll, deswegen frage ich das ja schließlich so konkret, sonst würde ich ja fragen, was im Allgemeinen ein Rückgabetyp ist, worüber dann auch wieder die Augen verdreht würden. Ich glaube, Manche sind sich selbst nicht darüber klar, was sie sagen: Wegen Grundlagen soll man nachschlagen, aber wenn man nachschlägt und dann nachfragt, bekommt man wieder nur den Hinweis, man solle doch das mal nachschlagen.

In DIESEM Fall ist es mir eben nicht klar, wie man auf den Rückgabetyp kommt.


----------



## babuschka (2. Jan 2012)

> Niemand hier möchtet dich fertig machen oder dir nicht weiterhelfen.




Zumindest das Zweite möchte ich denn doch anzweifeln.


----------



## gman (2. Jan 2012)

> Mir ist zum Beispiel trotz dieses zitierten Ausdrucks nicht klar, daß der Rückgabetyp
> 
> GUI.Key
> 
> ...



Der Rückgabetyp ist GUI.Key. PUNKT.

Mit [c]gui.Key[/c] kommst du auch an die Elemente des Enums (vermute ich mal, den
Code der Klasse GUI haben wir hier ja nicht zur Verfügung). Das ist aber dann der
konkrete Wert. Grob gesagt: Typ = Definition, Wert = das was eine Methode bei der
konkreten Ausführung zurück gibt (eine initialisierte Instanz des Rückgabetyps).

Ich hoffe ich kann dir damit etwas weiterhelfen.


----------



## babuschka (3. Jan 2012)

Hallo, ich würde jetzt gerne die Klasse "BoulderDah" gemäß dieser Aufgabenstellung erstellen (zumindest versuchen):



> Damit das Spiel spielbar wird benötigt ihr noch eine Klasse, die alles zusammenhält. Entwickelt
> dazu die Klasse BoulderDash.
> Die Klasse soll zunächst drei Spielwelten von der Festplatte laden. Nehmt dazu Euren MapParser
> zur Hilfe. Sind die Welten geladen, soll die erste Welt in der GUI angezeigt werden. Die Benutzung
> ...




Ich habe drei Spielwelten erstellt und als txt.-Dateien gespeichert.

Den Beginn der Aufgabe habe ich versucht und zwar so:


```
//Die Klasse BoulderDash
import java.util.ArrayList;
import java.util.List;


public class BoulderDash{

public static void main( String[] args){
	
	MapParser mapparser=new MapParser();
	List<List<String>> maps = MapProvider.loadMaps();
	Element[][] spielfeld=null;
	GUI gui=new GUI();
	
	for (List<String> level : maps){
		spielfeld=mapparser.parseMap(level);
	}
	
	
	gui.setLevel(1, spielfeld);
	
//weiter bin ich noch nicht
}

}
```


Ich wüsste gerne, ob das der richtige Ansatz ist.
Danke für jede Mühe.


----------



## babuschka (3. Jan 2012)

Keine Ahnung, ob jemand Lust hat, das anzuschauen, aber wenn ich


```
//Die Klasse BoulderDash
import java.util.ArrayList;
import java.util.List;
 
 
public class BoulderDash{
	
	
public static void main( String[] args){
    
	MapParser mapparser=new MapParser();
	List<List<String>> maps = MapProvider.loadMaps();
    GUI gui=new GUI();
    
    for (List<String> level : maps){
        mapparser.parseMap(level);
        
        
    }
    
    
    
    
//weiter bin ich noch nicht
}
 
}
```


kompilieren lasse, kommt kein Fehler, aber wenn ichs ausführen lasse, kommt dies:



> Exception in thread "main" java.lang.Nullpointerexception
> at MapParser.<init> 8
> at BoulderDash main. 11





Woran es liegt, bin ich nicht in der Lage zu erkennen.



Ich poste aber mal den Code zu MapParser noch, damit vllt. irgendjemand damit was anfangen kann:


```
import java.util.ArrayList;
import java.util.List;
 
//Die Klasse MapParser
 
public class MapParser{
	List<String> map;
	Element[][]spielfeld=new Element[map.size()-1][map.get(1).length()];
	
	
	
	
	//Implementiere das Spielfeld nur, wenn das übergebene Level valide ist.
	//Das wird vorher mit Hilfe der untenstehenden Methoden getestet.
    Element[][] parseMap(List<String> map){
        
    	   
                           char certainchar;
                           Element newElement;
                           int counter=0;
                           int counter2=0;
                           boolean sourrounded=false;
                           boolean equalLength;
                           
                           
                           for(int j=0; j<map.size(); j++){
                        	   
                               counter=countPlayer(map.get(j), 'P');
                               sourrounded=sourroundedByWalls(map.get(j));
                               counter2=countExists(map.get(j), 'G');
                               
                      }    
                           equalLength=equalLength(map);
                           
                   if(counter==1 && counter2>=1 && sourrounded==true && equalLength==true){       
                           
                           
                           
                           
 
        for(int i=0; i<map.size(); i++){
            
            for(int j=0; j<=map.get(i).length(); j++){
            certainchar=map.get(i).charAt(i);
            switch(certainchar){
            
            case'P': newElement=new Player(i,j,this); spielfeld[i][j]=newElement; break;
            case'E': newElement=new Erde(i,j,this); spielfeld[i][j]=newElement;break; 
            case'S': newElement=new Stein(i,j,this); spielfeld[i][j]=newElement;break;
            case'M': newElement=new Monster(i,j,this); spielfeld[i][j]=newElement;break;
            case'D': newElement=new Diamant(i,j,this); spielfeld[i][j]=newElement;break;
            case'G': newElement=new Ausgang(i,j,this); spielfeld[i][j]=newElement;break;
            case' ': newElement=new LeeresFeld(i,j,this); spielfeld[i][j]=newElement;break;
            }
            
            
            }
        }
    
                    }
                   
                   else {System.out.println("Level ist nicht rechteckig; Spielfeld wurde nicht initialisiert.");
                   spielfeld=null;
                   }         
                   return spielfeld;
    }       


public char getSpielfeld(int i, int j){
	return spielfeld[i][j].getChar();
}

public void setSpielfeld(int i, int j, char k){
	
	Element newElement2;
	switch(k){
    
    case'P': newElement2=new Player(i,j,this); spielfeld[i][j]=newElement2; break;
    case'E': newElement2=new Erde(i,j,this); spielfeld[i][j]=newElement2;break; 
    case'S': newElement2=new Stein(i,j,this); spielfeld[i][j]=newElement2;break;
    case'M': newElement2=new Monster(i,j,this); spielfeld[i][j]=newElement2;break;
    case'D': newElement2=new Diamant(i,j,this); spielfeld[i][j]=newElement2;break;
    case'G': newElement2=new Ausgang(i,j,this); spielfeld[i][j]=newElement2;break;
    case' ': newElement2=new LeeresFeld(i,j,this); spielfeld[i][j]=newElement2;break;
    }
	
}

//Es folgen Methoden, die für den Test der Validität eines Levels benutzt werden.

//Zähle die Anzahl der Spieler.

public int countPlayer(String string, char aChar){

  int counter=0;

    for(int i=0; i<string.length(); i++){
            
               if(string.charAt(i)==aChar){
                      counter++;
                  }
        
     }

return counter;
}


//Teste, ob am Anfang und Ende eines Strings ein bestimmes Char steht.

public boolean sourroundedByWalls(String string){

   boolean sourrounded=true;

         if(string.charAt(0)!='W' || string.charAt(string.length()-1)!='W'){
                  sourrounded=false;
          }

     return sourrounded;
}


//Zähle die Anzahl der Ausgänge.

public int countExists(String string, char aChar){

  int counter2=0;

    for(int i=0; i<string.length(); i++){
            
               if(string.charAt(i)==aChar){
                      counter2++;
                  }
        
     }
        return counter2;

}

//Teste, ob alle Zeilen die gleiche Länge haben (Rechtecksform des Spielfelds)

public boolean equalLength(List<String> irg){
boolean equalLength=true;

int LengthOfLine=irg.get(0).length();
int LengthOfNextLine;

if(equalLength==true){

  for(int i=1; i<irg.size();i++){
      
      LengthOfNextLine=irg.get(i).length();
  
      if(LengthOfLine!=LengthOfNextLine){
             equalLength=false;
         }
      LengthOfLine=LengthOfNextLine;

}
 
}


return equalLength;

}
}
```


----------



## read-only (3. Jan 2012)

> Exception in thread "main" java.lang.Nullpointerexception
> at MapParser.<init> 8
> at BoulderDash main. 11



Nullpointerexception: Du greifst per .Notation auf Attribute eines Objektes zu das null ist.
der Fehler ist in BoudlerDash main Zeile 11 aufgetreten:

```
MapParser mapparser=new MapParser();
```

und zwar genauer in der Klasse Mapparser bei der init-Funktion zeile 8:

```
Element[][]spielfeld=new Element[map.size()-1][map.get(1).length()];
```

Du greifst dort auf map.size() und map.get(1).length() zu, einer von diesen Aufrufen hat also den Fehler verursacht und bewegst du jetzt deine Augen eine Zeile nach oben steht dort

```
List<String> map;
```
welche nicht initialisiert wurde also explizit null ist.


----------



## babuschka (3. Jan 2012)

Dankeschön!

Wie kann man aber eine Liste anfänglich initialisieren, also-- womit?


----------



## steffen1997 (3. Jan 2012)

vielliecht hilft dir das weiter : Liste mit Werten initialisieren @ tutorials.de: Tutorials, Forum & Hilfe


----------



## Sonecc (3. Jan 2012)

Das wird ihm nicht helfen, weil die Klasse konzeptionell schon falsch ist.
Die Liste wird in der ganzen Klasse nie verwendet außer zur Initialisierung von spielfeld. (als kleiner Tipp...)


----------



## babuschka (3. Jan 2012)

Das hilft schon.

Was mir aber nicht klar ist, ist, womit ich diese Liste eigentlich initialisieren muss und mit wie viel Elementen.


----------



## babuschka (3. Jan 2012)

Sonecc hat gesagt.:


> Das wird ihm nicht helfen, weil die Klasse konzeptionell schon falsch ist.
> Die Liste wird in der ganzen Klasse nie verwendet außer zur Initialisierung von spielfeld. (als kleiner Tipp...)




Meinst Du die Klasse BoulderDash oder die Klasse MapParser?


Okay, Du wirst die Klasse MapParser meinen.



Könntest Du mir vllt. näher erklären, inwiefern sie konzeptionell falsch ist?
Aber nur, wenn das nicht wieder Deinen Missmut hinaufbeschwört.


----------



## Sonecc (3. Jan 2012)

Du hast 2 Felder:
map
spielfeld

map wird nur genutzt, damit du spielfeld initialisieren kannst. Du kannst zum Zeitpunkt der initialisierung aber gar nicht wissen, wie groß dein Feld ist, bzw. mit was für einer Liste du arbeiten wirst.
Wenn dein Spielfeld wirklich abhängig von der Liste (also map) ist, dann wirst du einen Konstruktor verwenden müssen oder das spielfeld innerhalb einer Methode initialisieren müssen, welche die Map als Parameter hat.


Edit: Rage Flames entfernt...


----------



## babuschka (3. Jan 2012)

Die Initialisierung des Spielfeld passiert doch aber in einer Methode, die die Liste als Parameter hat, ist diese Methode denn nicht

Element[][] parseMap(List<String> map){...

?


Ich glaube, ich hab's schon verstanden:


```
import java.util.ArrayList;
import java.util.List;
 
//Die Klasse MapParser
 
public class MapParser{
	
	Element[][]spielfeld;
	
	
	
	
	//Implementiere das Spielfeld nur, wenn das übergebene Level valide ist.
	//Das wird vorher mit Hilfe der untenstehenden Methoden getestet.
    Element[][] parseMap(List<String> map){
        
    	spielfeld=new Element[map.size()][map.get(1).length()];   
                           char certainchar;
                           Element newElement;
                           int counter=0;
                           int counter2=0;
                           boolean sourrounded=false;
                           boolean equalLength;
                           
                           
                           for(int j=0; j<map.size(); j++){
                        	   
                               counter=countPlayer(map.get(j), 'P');
                               sourrounded=sourroundedByWalls(map.get(j));
                               counter2=countExists(map.get(j), 'G');
                               
                      }    
                           equalLength=equalLength(map);
                           
                   if(counter==1 && counter2>=1 && sourrounded==true && equalLength==true){       
                           
                           
                           
                           
 
        for(int i=0; i<map.size(); i++){
            
            for(int j=0; j<map.get(i).length(); j++){
            certainchar=map.get(i).charAt(i);
            switch(certainchar){
            
            case'P': newElement=new Player(i,j,this); spielfeld[i][j]=newElement; break;
            case'E': newElement=new Erde(i,j,this); spielfeld[i][j]=newElement;break; 
            case'S': newElement=new Stein(i,j,this); spielfeld[i][j]=newElement;break;
            case'M': newElement=new Monster(i,j,this); spielfeld[i][j]=newElement;break;
            case'D': newElement=new Diamant(i,j,this); spielfeld[i][j]=newElement;break;
            case'G': newElement=new Ausgang(i,j,this); spielfeld[i][j]=newElement;break;
            case' ': newElement=new LeeresFeld(i,j,this); spielfeld[i][j]=newElement;break;
            }
            
            
            }
        }
    
                    }
                   
                   else {System.out.println("Level ist nicht rechteckig; Spielfeld wurde nicht initialisiert.");
                   spielfeld=null;
                   }         
                   return spielfeld;
    }       


public char getSpielfeld(int i, int j){
	return spielfeld[i][j].getChar();
}

public void setSpielfeld(int i, int j, char k){
	
	Element newElement2;
	switch(k){
    
    case'P': newElement2=new Player(i,j,this); spielfeld[i][j]=newElement2; break;
    case'E': newElement2=new Erde(i,j,this); spielfeld[i][j]=newElement2;break; 
    case'S': newElement2=new Stein(i,j,this); spielfeld[i][j]=newElement2;break;
    case'M': newElement2=new Monster(i,j,this); spielfeld[i][j]=newElement2;break;
    case'D': newElement2=new Diamant(i,j,this); spielfeld[i][j]=newElement2;break;
    case'G': newElement2=new Ausgang(i,j,this); spielfeld[i][j]=newElement2;break;
    case' ': newElement2=new LeeresFeld(i,j,this); spielfeld[i][j]=newElement2;break;
    }
	
}

//Es folgen Methoden, die für den Test der Validität eines Levels benutzt werden.

//Zähle die Anzahl der Spieler.

public int countPlayer(String string, char aChar){

  int counter=0;

    for(int i=0; i<string.length(); i++){
            
               if(string.charAt(i)==aChar){
                      counter++;
                  }
        
     }

return counter;
}


//Teste, ob am Anfang und Ende eines Strings ein bestimmes Char steht.

public boolean sourroundedByWalls(String string){

   boolean sourrounded=true;

         if(string.charAt(0)!='W' || string.charAt(string.length()-1)!='W'){
                  sourrounded=false;
          }

     return sourrounded;
}


//Zähle die Anzahl der Ausgänge.

public int countExists(String string, char aChar){

  int counter2=0;

    for(int i=0; i<string.length(); i++){
            
               if(string.charAt(i)==aChar){
                      counter2++;
                  }
        
     }
        return counter2;

}

//Teste, ob alle Zeilen die gleiche Länge haben (Rechtecksform des Spielfelds)

public boolean equalLength(List<String> irg){
boolean equalLength=true;

int LengthOfLine=irg.get(0).length();
int LengthOfNextLine;

if(equalLength==true){

  for(int i=1; i<irg.size();i++){
      
      LengthOfNextLine=irg.get(i).length();
  
      if(LengthOfLine!=LengthOfNextLine){
             equalLength=false;
         }
      LengthOfLine=LengthOfNextLine;

}
 
}


return equalLength;

}
}
```


----------



## babuschka (3. Jan 2012)

Jetzt wird beim Ausführen von BoulderDash auch schon das Fenster geöffnet, wo ich die Spielwelten laden kann.

Allerdings scheint bei der Überprüfung der Validität was schiefzulaufen, denn wenn ich beispielsweise dieses Spielfeld lade:


WWWWWWWWWW
W       EEPESW SW
W         EEEE SS W
W      S             W
WMSSS  EE        W
W                     W
W   D                W
WE E E E           W
WDSSSSGEE       W
WWWWWWWWWW


Kommt die Ausgabe, daß dieses Feld nicht rechtreckig sei.


----------



## babuschka (3. Jan 2012)

SORRY, die W sollen auch rechts untereinander stehen und es ist rechteckig, irgendwie bekomme ichs hier nicht dargestellt.




Ich nehme an, daß ich in der for-Schleife vergessen habe, die Werte jeweils zu addieren.

Also z.B.


```
counter=counter+countPlayer(map.get(j), 'P');
```
 und daß die if-Bedingung deswegen nie erfüllt ist.


----------



## Gast2 (3. Jan 2012)

Könntest du deine Sourcen bitte mal anständig formatieren? Das kann doch so keiner lesen. Ich habs sogar gerade versucht... Aber das is so en durcheinander. Man sieht gar nit was wo in welchem Block drinne steht ...


----------



## babuschka (3. Jan 2012)

Hat einer eine Idee warum 


```
WWWWWWWWWW
WEEPESW SW
W EEEE SSW
W      S W
WMSSS  EEW
W        W
W   D    W
WE E E E W
WDSSSSGEEW
WWWWWWWWWW
```

und auch


```
WWWWWWWWWWWWWWWWWWWW
WEEEEEEEEESSSSEEESSW
WEEEEEEESS SSS SS  W
W  M               W
W EEEEEEEEEEESSSS  W
W P                W
WSSSSSSSSSSSS      W
WEEEEEEEEEEEEEEEEEEW
WEEEEEEEEEEEEEEEEEEW
W     D            W
WSSSSSSSSSSSSESESESW
WSESESESESESEEESESEW
WEEEESSSSEEEESSSSESW
W    D      S    S W
WSSSEE E E E E S E W
WEDSDSDSDSDSEEEEEEEW
W          D       W
W    G             W
WSSSSSSSSSSEDEEEEEEW
WWWWWWWWWWWWWWWWWWWW
```

eingelesen werden, aber bei 


```
WWWWWWWWWWWW
WPSSSSSSSSSW
WEEEEEEEEEDW
WEEESSEEESSW
W          W
W  MSSSSSSSW
WEEEESSSEEEW
WSSSEEESS  W
W G        W
WDSSSSEESSSW
WWWWWWWWWWWW
```

die if-Bedingung offenbar nicht erfüllt ist, weil angezeigt wird:

"Level ist nicht valide..."?


Ich erkenne da keinen Unterschied bzw. Fehler.






PS. Sorry, ich werde den Code noch besser strukturieren, ich sehe ein, daß er sehr (!) chaotisch ist.


----------



## Firephoenix (3. Jan 2012)

Wenn ich eh schon drüberlese... was solls:


```
import java.util.ArrayList;
import java.util.List;

public class MapParser {

	Element[][] spielfeld;

	Element[][] parseMap(List<String> map) {

		// Spielfeld hätte hier lokal angelegt werden können, wird global in der
		// Klasse nicht benötigt
		spielfeld = new Element[map.size()][map.get(1).length()];
		// Was ist ein certainchar? Sinnvolle Variablennamen wählen außerdem
		// nutzt du die Variable erst viel später
		// sie muss hier noch nicht angelegt werden
		char certainchar;
		// Selbiges, die Variable wird erst unten Benötigt
		Element newElement;
		// Namen passend wählen! Der erste counter
		// zählt die 'P' der 2. die 'G'
		// benenne sie entsprechend
		int counter = 0;
		int counter2 = 0;
		boolean sourrounded = false;
		// equallength kannst du komplett rauswerfen, du setzt den wert einmal
		// und prüfst ihn direkt dannach
		boolean equalLength;

		for (int j = 0; j < map.size(); j++) {

			/*
			 * Überleg dir einmal was die Funktion macht wenn deine Map 2 Zeilen
			 * hat: die 1. Zeile ist nicht surrounded und enthält ein P und ein
			 * G die 2. Zeile ist surrounded und enthält ebenfalls ein P und ein
			 * G Beim ersten durchlauf ist counter 1, surrounded false und
			 * counter 2 1 beim nächsten durchlauf überschreibst du alle
			 * variablen, counter ist wieder 1 sourrounded wäre true und counter
			 * 2 wäre 1. gültig ist die map trotzdem nicht
			 */
			counter = countPlayer(map.get(j), 'P');
			sourrounded = sourroundedByWalls(map.get(j));
			counter2 = countExists(map.get(j), 'G');

		}
		equalLength = equalLength(map);

		if (counter == 1 && counter2 >= 1 && sourrounded == true
				&& equalLength == true /*
										 * anstatt hier dein equalLength zu
										 * prüfen könntest du direkt den
										 * gleichnamigen Funktionsaufruf
										 * einsetzen
										 */) {

			for (int i = 0; i < map.size(); i++) {

				for (int j = 0; j < map.get(i).length(); j++) {
					// anstatt hier erst den char zwischenzuspeichern kannst du
					// auch direkt
					// den aufruf in das switch-statement einsetzen
					certainchar = map.get(i).charAt(i);
					switch (certainchar) {

					case 'P':
						// Auch hier kannst du direkt das new ... Zuweisen, das
						// Zwischenspeichern in newElement ist überflüssig
						newElement = new Player(i, j, this);
						spielfeld[i][j] = newElement;
						break;
					case 'E':
						newElement = new Erde(i, j, this);
						spielfeld[i][j] = newElement;
						break;
					case 'S':
						newElement = new Stein(i, j, this);
						spielfeld[i][j] = newElement;
						break;
					case 'M':
						newElement = new Monster(i, j, this);
						spielfeld[i][j] = newElement;
						break;
					case 'D':
						newElement = new Diamant(i, j, this);
						spielfeld[i][j] = newElement;
						break;
					case 'G':
						newElement = new Ausgang(i, j, this);
						spielfeld[i][j] = newElement;
						break;
					case ' ':
						newElement = new LeeresFeld(i, j, this);
						spielfeld[i][j] = newElement;
						break;
					}
					// Default-Block einfügen mit wenigstens einer Fehlermeldung
					// falls unbekannte Zeichen kommen

				}
			}

		}

		else {
			System.out
					.println("Level ist nicht rechteckig; Spielfeld wurde nicht initialisiert.");
			spielfeld = null;
		}
		return spielfeld;
	}

	// wird die methode hier überhaupt verwendet?
	// falls ja spielfeld in der klasse lassen, andernfalls raus damit
	public char getSpielfeld(int i, int j) {
		return spielfeld[i][j].getChar();
	}

	// Den Code habe ich oben schonmal gesehen, raus damit, entweder hier oder
	// oben
	public void setSpielfeld(int i, int j, char k) {

		Element newElement2;
		switch (k) {

		case 'P':
			newElement2 = new Player(i, j, this);
			spielfeld[i][j] = newElement2;
			break;
		case 'E':
			newElement2 = new Erde(i, j, this);
			spielfeld[i][j] = newElement2;
			break;
		case 'S':
			newElement2 = new Stein(i, j, this);
			spielfeld[i][j] = newElement2;
			break;
		case 'M':
			newElement2 = new Monster(i, j, this);
			spielfeld[i][j] = newElement2;
			break;
		case 'D':
			newElement2 = new Diamant(i, j, this);
			spielfeld[i][j] = newElement2;
			break;
		case 'G':
			newElement2 = new Ausgang(i, j, this);
			spielfeld[i][j] = newElement2;
			break;
		case ' ':
			newElement2 = new LeeresFeld(i, j, this);
			spielfeld[i][j] = newElement2;
			break;
		}

	}

	// Es folgen Methoden, die für den Test der Validität eines Levels benutzt
	// werden.

	// Zähle die Anzahl der Spieler.

	// Vergleich die Methode mal mit der countExists... mit passender benennung
	// countChars
	// wäre das nicht passiert, mit playern hat die Methode hier nämlich
	// garnichts zu tun.
	public int countPlayer(String string, char aChar) {

		int counter = 0;

		for (int i = 0; i < string.length(); i++) {

			if (string.charAt(i) == aChar) {
				counter++;
			}

		}

		return counter;
	}

	// Teste, ob am Anfang und Ende eines Strings ein bestimmes Char steht.

	// Der name kann irreführend sein, die Funktion prüft nur eine Zeile, also
	// besser lineSurroundedByWalls
	public boolean sourroundedByWalls(String string) {

		boolean sourrounded = true;

		if (string.charAt(0) != 'W'
				|| string.charAt(string.length() - 1) != 'W') {
			sourrounded = false;
		}

		return sourrounded;
	}

	// Zähle die Anzahl der Ausgänge.
	// Siehe oben, gibts schonmal - raus damit
	public int countExists(String string, char aChar) {

		int counter2 = 0;

		for (int i = 0; i < string.length(); i++) {

			if (string.charAt(i) == aChar) {
				counter2++;
			}

		}
		return counter2;

	}

	// Teste, ob alle Zeilen die gleiche Länge haben (Rechtecksform des
	// Spielfelds)

	// Wenn du der Methode eine leere Liste übergibst fliegt direkt eine
	// Nullpointerexception weil du direkt den Wert des 1. Elements abgreifst.
	// Lieber vorher abfangen, außerdem gibt es auch die möglichkeit
	// mehrere return zu verwenden und die Methode früher abzubrechen, ich hab
	// dir dazu unten einen Vorschlag angefügt
	public boolean equalLength(List<String> irg) {
		boolean equalLength = true;

		int LengthOfLine = irg.get(0).length();
		int LengthOfNextLine;

		if (equalLength == true) {

			for (int i = 1; i < irg.size(); i++) {

				LengthOfNextLine = irg.get(i).length();

				if (LengthOfLine != LengthOfNextLine) {
					equalLength = false;
				}
				LengthOfLine = LengthOfNextLine;

			}

		}

		return equalLength;

	}

	public boolean allElementsEqualLength(List<String> strings) {
		if (strings.isEmpty()) {
			return true;
		}
		int lastLineLength = strings.get(0).length();
		
		for (int i = 1; i < strings.size(); i++) {
			int actualLineLength = strings.get(i).length();
			if(actualLineLength != lastLineLength){
				return false;
			}
			lastLineLength = actualLineLength;
		}
	}
}
```


----------



## babuschka (3. Jan 2012)

Oh, vielen lieben Dank für diese Mühe.

Ich frage zuerst etwas nach zu Zeile 32-39.

Also bei counter und counter2 muss ich dann wohl dies hier machen:



```
counter=counter+countPlayer(map.get(j), 'P');
counter2=counter2+countExists(map.get(j), 'G');
```

So gehen die Ergebnisse jeweils nicht verloren, sondern werden aktualisiert.

Etwas Ähnliches versuche ich mir gerade für das sourrounded zu überlegen.


Meine Idee hierfür ist:


```
sourrounded=sourroundedByWalls(map.get(j)) && sourroundedByWalls(map.get(j-1));
```

Wobei ich gerade nicht sicher bin, ob man das machen kann, weil man ja dann zum Beispiel für j=0 einen nicht zulässigen Wert hätte (-1).


Vielleicht die Schleife bei 1 anfangen lassen und entsprechend anpassen:


```
for(int j=1; j<=map.size(); j++){
                        	   
                               counter=counter+countPlayer(map.get(j-1), 'P');
                   sourrounded=sourroundedByWalls(map.get(j)) && sourroundedByWalls(map.get(j-1));
                               counter2=counter2+countExists(map.get(j-1), 'G');
                               
                      }
```




Eine andere Idee von mir, die mir irgendwie sympathischer ist, ist:


```
for(int j=0; j<map.size(); j++){
                               
                               counter=counter+countPlayer(map.get(j), 'P');
                               if(counter>1){break;}
                               sourrounded=sourroundedByWalls(map.get(j));
                               if(sourrounded==false){break;}
                               counter2=counter2+countExists(map.get(j), 'G');
                               
                      }
```

daß man die Schleife also einfach verlässt, wenn die Anzahl der Spieler größer als 1 ist oder sourrounded in irgendeiner Zeile false ist.






Habe aber dennoch keine Ahnung, warum bei meiner dritten Map die if-Bedingung nicht gilt und ausgegeben wird: "nicht valide..."


----------



## steffen1997 (3. Jan 2012)

Also ,das LEvel ist auch nicht rechteckig wenn du zählst (rechteckig schon aber nicht quadratisch) da es 11tief ist und 12breit.


----------



## babuschka (3. Jan 2012)

Muss es denn quadratisch sein? M.E. nicht.


----------



## steffen1997 (3. Jan 2012)

ne doch nicht  ,beim ersten wars auch nicth.


----------



## babuschka (3. Jan 2012)

Irgendwie unerklärlich.

Jedenfalls für mich, was nicht viel heißt. :autsch:


----------



## Gast2 (4. Jan 2012)

Da macht sich schon jemand die Mühe und reformatiert deinen Source, schreibt dir überall Kommentare rein und im nächsten Post sind deine Sourcen wieder wie Kraut und Rüben... 

Merkst du was?


----------



## Sonecc (4. Jan 2012)

Ich mach dir ausnahmsweise mal deine Methode wie du prüfen kannst, ob das Level von Wänden umgeben wurde oder nicht. Sei dir Gewiss, dass das eine absolute Seltenheit bei mir ist, dass ich praktisch eine Lösung einer Aufgabe präsentiere
Beachte, dass sie gleichzeitig auch prüft, ob die Reihen des Levels gleichlang sind
Ich habe mit Absicht jede Zeile des Codes kommentiert, in der Hoffnung du kopierst es nicht einfach
sondern denkst darüber nach und überlegst dir genau, warum ich was an welcher Stelle gemacht habe.
Auf diese Weise kannst du vielleicht auch deine Konzeptionellen Probleme erkennen und verbessern.


```
/**
 * Checks the map if it is surrounded by walls and 
 * if its rows have an equal size
 * @param map the list of rows of the map to test
 * @return true if the level is surrounded by walls 
 * and if the rowsizes are ok
 */
public static boolean checkWallsAndForm(List<String> map) {
	//All other rows have to have this value
	int lastCol = map.get(0).length()-1; 
	//Run through all rows of the map
	for (int i = 0; i < map.size(); i++) {
		//Get the current row
		String row = map.get(i);
		//Last Column index of this row
		int rowsLastCol = row.length() - 1;
		//If it is not equal to lastCol, the row has
		//different size then the first row had
		if (rowsLastCol != lastCol) {
			//Not valid row, return false
			return false;
		}
		//First and last row must not contain any other char than 'w'
		if (i == 0 || i == map.size() - 1) {
			//Check every entry of the row
			for (int j = 0; j < row.length(); j++) {
				//Only W is allowed
				if (row.charAt(j) != 'W') {
					//Row invalid, return false
					return false;
				}
			}
		} else {
			//All other rows must have a 'W' at the beginning and the end
			if (row.charAt(0) != 'W' || row.charAt(lastCol) != 'W') {
				//Row does not start or end with an 'W', return false
				return false;
			}
		}
	}
	//Everything ok, return true
	return true;
}
```


----------



## babuschka (4. Jan 2012)

Ich habe schon einige der Tipps, die mir Firephoenix gegeben hat, versucht umzusetzen. Zum Beispiel habe ich die Methoden, die die Anzahl der Spieler und der Ausgänge zählen, zu einer zusammengefasst.

Auch habe ich meine Methoden, die die Rechtecksform und das Umgebensein von Wänden testen, durch die von Sonecc ersetzt (ich habe sie zwar übernommen, sie aber nicht nur einfach gedankenlos kopiert). Dann sieht es zumindest schonmal so aus:


```
import java.util.ArrayList;
import java.util.List;
 
public class MapParser{
    
	Element[][] spielfeld;
    
        Element[][] parseMap(List<String> map){
        
        spielfeld=new Element[map.size()][map.get(1).length()];   
        char certainchar;
        Element newElement;
                           
                           
         if(countChars(map,'P')==1 && countChars(map,'G')>=1 && checkWallsAndForm(map)==true){       
                           
                           
                           
                           
 
        for(int i=0; i<map.size(); i++){
            
            for(int j=0; j<map.get(i).length(); j++){
            certainchar=map.get(i).charAt(i);
            switch(certainchar){
            
            case'P': newElement=new Player(i,j,this); spielfeld[i][j]=newElement; break;
            case'E': newElement=new Erde(i,j,this); spielfeld[i][j]=newElement;break; 
            case'S': newElement=new Stein(i,j,this); spielfeld[i][j]=newElement;break;
            case'M': newElement=new Monster(i,j,this); spielfeld[i][j]=newElement;break;
            case'D': newElement=new Diamant(i,j,this); spielfeld[i][j]=newElement;break;
            case'G': newElement=new Ausgang(i,j,this); spielfeld[i][j]=newElement;break;
            case' ': newElement=new LeeresFeld(i,j,this); spielfeld[i][j]=newElement;break;
            default: System.out.println("No valid letter.");
            }
            
            
            }
        }
    
                    }
                   
                   else {System.out.println("Level is not valid.");
                   spielfeld=null;
                   }    
                           
                           
                           
                   return spielfeld;
    }       
 
 
public char getSpielfeld(int i, int j){
    return spielfeld[i][j].getChar();
}
 
public void setSpielfeld(int i, int j, char k){
    
    Element newElement2;
    switch(k){
    
    case'P': newElement2=new Player(i,j,this); spielfeld[i][j]=newElement2; break;
    case'E': newElement2=new Erde(i,j,this); spielfeld[i][j]=newElement2;break; 
    case'S': newElement2=new Stein(i,j,this); spielfeld[i][j]=newElement2;break;
    case'M': newElement2=new Monster(i,j,this); spielfeld[i][j]=newElement2;break;
    case'D': newElement2=new Diamant(i,j,this); spielfeld[i][j]=newElement2;break;
    case'G': newElement2=new Ausgang(i,j,this); spielfeld[i][j]=newElement2;break;
    case' ': newElement2=new LeeresFeld(i,j,this); spielfeld[i][j]=newElement2;break;
    }
    
}
 
//The following methods are used to check if the level is valid.
 
//Count the number of a certain char in each row.
 
public int countChars(List<String> map, char aChar){
 
  int counter=0;
 
    for(int i=0; i<map.size();i++){
    	
    	for(int j=0; j<map.get(i).length();j++){
    	
               if(map.get(i).charAt(j)==aChar){
                      counter++;
                  }
        }
    	
    }	
 
return counter;
}
 

//Check if the level is sourrounded by walls and if it is rectangular.

public static boolean checkWallsAndForm(List<String> map) {
    
    int lastCol = map.get(0).length()-1; 
    
    for (int i = 0; i < map.size(); i++) {
        
        String row = map.get(i);
        
        int rowsLastCol = row.length() - 1;
        
        if (rowsLastCol != lastCol) {
            
            return false;
        }
        
        if (i == 0 || i == map.size() - 1) {
            
            for (int j = 0; j < row.length(); j++) {
                
                if (row.charAt(j) != 'W') {
                    
                    return false;
                }
            }
        } else {
            
            if (row.charAt(0) != 'W' || row.charAt(lastCol) != 'W') {
                
                return false;
            }
        }
    }
    
    return true;
}  
   
 
         

  


}
```



Die restlichen Tipps zur Verbesserung von Firephoenix konnte ich leider noch nicht umsetzen.

Zum Beispiel bereiten mir die Methoden setSpielfeld und getSpielfeld Probleme; ich benutze diese ja u.a. in der Klasse Player und weiß daher nicht, ob ich sie jetzt einfach aus MapParser rausnehmen sollte.





Achso: Mein Level 3 wird immer noch als "nicht valide" zurückgewiesen.


----------



## Sonecc (4. Jan 2012)

erstmal, die Formatierung ist noch immer grottig... bitte achte doch darauf, bevor du code postest, da so niemand wirklich was lesen kann



java_ hat gesagt.:


> Achso: Mein Level 3 wird immer noch als "nicht valide" zurückgewiesen.





Wenn ich deinen Code kopiere und es auf die Maps anwende, wird bei mir angegeben, dass diese valide sind.

Dementsprechend ist dein Problem nicht nachvollziehbar

[edit]
Lustig, dass du den JavaDoc entfernst und durch einen eigenen kommentar ersetzt, der fehler enthält^^

surrounded wird nicht sourounded geschrieben...
[/edit]


----------



## babuschka (4. Jan 2012)

Sonecc hat gesagt.:


> Wenn ich deinen Code kopiere und es auf die Maps anwende, wird bei mir angegeben, dass diese valide sind.
> 
> Dementsprechend ist dein Problem nicht nachvollziehbar




Also ich mache es so (vllt. ist die Vorgehensweise ja verkehrt):

Ich lasse MapParser und BoulderDash kompilieren.

Dann führe ich Boulderdash aus: java Boulderdash


Dann öffnet sich ein Fenster, wo ich die Maps auswählen kann.

Wähle ich Spielwelt1.txt oder Spielwelt2.txt dauert es eine Weile. Ansonsten passiert nichts.



Wähle ich aber Spielwelt3.txt kommt eben "Level is not valid."


----------



## Sonecc (4. Jan 2012)

dann gib mal deine Spielwelt3.txt
Nehme ich nämlich das Spielfeld, dass du in einem deiner vorherigen Posts stehen hast, wird dieses als richtig erkannt. (was ja auch richtig ist)


----------



## babuschka (4. Jan 2012)

Ich meine die Spielwelt ist sogar  schon unter denen, die ich oben gepostet hatte.

Also sie sieht so aus:


```
WWWWWWWWWWWW
WPSSSSSSSSSW
WEEEEEEEEEDW
WEEESSEEESSW
W          W
W  MSSSSSSSW
WEEEESSSEEEW
WSSSEEESS  W
W G        W
WDSSSSEESSSW
WWWWWWWWWWWW
```


----------



## Sonecc (4. Jan 2012)

...
Ok, etwas deutlicher...
Lade bitte mal deine Spielwelt3.txt Datei als Dateianhang hier hoch.

Dass du das hier schonmal gepostet hast, habe ich hiermit ausgedrückt:



> Nehme ich nämlich das Spielfeld, dass du in einem deiner vorherigen Posts stehen hast, wird dieses als richtig erkannt. (was ja auch richtig ist)




Also bitte ... Lade deine DATEI hoch. Nicht hier reintippen, sondern hochladen...


----------



## babuschka (4. Jan 2012)

Okay, habe ich.


----------



## Sonecc (4. Jan 2012)

Die Datei wird deswegen nicht als valide erkannt, weil die letzte Zeile in der Datei Leerzeichen am Ende enthält.

Statt


```
WWWWWWWWWWWW
```

steht dort (_ sind leerzeichen)


```
WWWWWWWWWWWW__________
```


Edit:

Hier mal eine verbesserte Version die mit solchen fehlerhaften Dateien umgehen kann


```
/**
 * Checks the map if it is surrounded by walls and 
 * if its rows have an equal size
 * @param map the list of rows of the map to test
 * @return true if the level is surrounded by walls 
 * and if the rowsizes are ok
 */
public static boolean checkWallsAndForm(List<String> map) {
	//All other rows have to have this value
	int lastCol = map.get(0).length()-1; 
	//Run through all rows of the map
	for (int i = 0; i < map.size(); i++) {
		//Get the current row
		String row = map.get(i);
		//Remove beginning and trailing whitespaces  <----- new line
		row = row.trim();                                     //<----- new line
		//Last Column index of this row
		int rowsLastCol = row.length() - 1;
		//If it is not equal to lastCol, the row has
		//different size then the first row had
		if (rowsLastCol != lastCol) {
			//Not valid row, return false
			return false;
		}
		//First and last row must not contain any other char than 'w'
		if (i == 0 || i == map.size() - 1) {
			//Check every entry of the row
			for (int j = 0; j < row.length(); j++) {
				//Only W is allowed
				if (row.charAt(j) != 'W') {
					//Row invalid, return false
					return false;
				}
			}
		} else {
			//All other rows must have a 'W' at the beginning and the end
			if (row.charAt(0) != 'W' || row.charAt(lastCol) != 'W') {
				//Row does not start or end with an 'W', return false
				return false;
			}
		}
	}
	//Everything ok, return true
	return true;
}
```


----------



## babuschka (4. Jan 2012)

Wenn ich diese veränderte Methode übernehme, kommt immer der default Fall, daß kein gültiger Buchstabe eingegeben ist.


----------



## Sonecc (4. Jan 2012)

Und wieder hab ich das gefühl du leistest keine bis kaum eigenarbeit...

Wenn du meine veränderte Methode übernimmst, musst du die Veränderung auch in deine anderen Methoden übernehmen...
Entweder du lässt es zu, dass die Datei leerzeichen am Ende enthält, dann musst du aber auch überall darauf achten, dass das passieren kann, oder du lässt es nicht zu.
Überleg dir selbst was du willst. Was du nun machen musst, sage ich dir jedenfalls nicht, darauf kann und solltest du selbst kommen, wenn du die Methode wirklich nicht einfach nur stur kopiert hast, sondern auch darüber nachgedacht hast. (was ich übrigens nicht glaube)


----------



## babuschka (4. Jan 2012)

Okay, ich versuche es zu verstehen!

Deine neue Methode zeichnet sich doch jetzt dadurch aus, daß die Zeilen vorher und hinterher keine Leerstellen mehr haben.


Und Du meinst, daß ich jetzt daß auch bei der Methode, die Player und Exist zählt, so machen muss, wenn ich diese neue Methode verwenden will?



Oder bei welchen Methoden muss ich das dementsprechend auch anpassen?


----------



## Sonecc (4. Jan 2012)

Am besten du nimmst die erste Version von dem Code und entfernst einfach die Leerzeichen aus der Datei...


----------



## babuschka (4. Jan 2012)

Ja, das mache ich.

Aber auch da muss ich leider noch eine Frage stellen.

Wie entferne ich die?


Also Du meinst doch die Leerzeilen, die Du als ______ gekennzeichnet hast.

Innerhalb des Spielfelds dürfen ja Leerzeichen sein, nur am Ende der Zeilen nicht. Aber wie entferne ich die?


----------



## Firephoenix (4. Jan 2012)

Hilft dir das?
String (Java Platform SE 6))


----------



## babuschka (4. Jan 2012)

Jetzt habe ich die alte Version wieder genommen, jetzt geht nichtmal mehr Spielwelt1, die vorhin noch ging.

Ohje.


----------



## babuschka (4. Jan 2012)

Okay, das war ein Missverständnis.


Jetzt habe ich die Leerzeilen am Ende gelöscht und auch bei 3 kommt jetzt nicht mehr die Meldung, es sei nicht valide.



Aber ich habe schon wieder eine andere Frage.


Wenn ich bei der Erzeugung des Spielfeld einen default-Zweig dazu nehme, scheint IMMER der angesprungen zu werden, wenn ich zum Beispiel Spielwelt1 dann lade, wird entsprechend der Anzahl der Zeilen dieser default-Zweig angesprungen.


Was ist denn da wieder verkehrt?


----------



## Sonecc (4. Jan 2012)

Schau dir dein switch statement doch mal genau an. Da fehlt etwas 


Spoiler: Bitte erst selbst drüber nachdenken bevor du das hier liest



Der Buchstabe W wird dort nie abgefragt, damit springt er in den default


----------



## babuschka (4. Jan 2012)

Okay, die Frage war nur drei Pünktchen wert.

Liegt wohl daran, daß ich den case 'W' vergessen habe.


----------



## Sonecc (4. Jan 2012)

java_ hat gesagt.:


> Okay, die Frage war nur drei Pünktchen wert.
> 
> Liegt wohl daran, daß ich den case 'W' vergessen habe.



Nee, die 3 Punkte kamen, weil meine vorherige Antwort hinfällig war


----------



## R3van (5. Jan 2012)

Ich möchte nochmals darauf hinweisen, dass wenn du (Java_) Lösungen dieses Forums mit in deine Abgabe nimmst, und ja das sind eindeutig Lösungen zu den Aufgaben, dann musst du dies kenntlich machen. Ein Verstoß kann zum Ausschluss der Veranstaltung und einem Eintrag in die Prüfungsakte führen. Du kannst zudem sehr sicher sein, dass wir diese Abgabe sehr genau prüfen werden.


----------



## babuschka (8. Jan 2012)

In Ordnung, wie kennzeichne ich das richtig, sodaß keine Schwierigkeiten entstehen?

Und: Was muss ich alles kennzeichnen? Es ist ja nicht so, daß nichts von mir stammen würde.

Würde es reichen, wenn ich ganz am Anfang schreibe, daß ich hier Hilfe bekommen habe (und den Link gebe) und dann an den Stellen jeweils schreibe: s. Link?

Oder wäre das zu unpräzise?



PS. Es ist absolut nicht meine Absicht, irgendwas zu verwenden und das ungekennzeichnet zu lassen.


----------



## babuschka (8. Jan 2012)

Die eine Methode wurde mir verraten, ja, das stimmt.

Das muss ich also kennzeichnen, das sehe ich ein und ist nur fair.

Aber alles Vorherige habe ich mir ja selbst erarbeitet, muss ich das auch alles kennzeichnen???




Der Austausch über Foren ist okay, wurde mir gesagt und alles (bis auf die verratene Methode) hier war Austausch - meines Ermessens.


----------



## timbeau (9. Jan 2012)

Interessant, dass der Weg zum Tutor einer Uni über ein Internet-Forum geht


----------



## Jango (9. Jan 2012)

timbeau hat gesagt.:


> *Interessant*, dass der Weg zum Tutor einer Uni über ein Internet-Forum geht



Nö, eher traurig. Höchstwahrscheinlich hat sie/er gedacht, man würde es nicht merken. Das Erschleichen von Material bekommen wir doch von hochrangigen Politern vorgemacht. Was ist dagegen eine kleine Hausaufgabe?


----------



## babuschka (9. Jan 2012)

Bitte keine Unterstellungen!

Ich wollte weder mogeln noch war es meine Hoffnung, "dass es keiner merkt".

Im Gegenteil weise ich in meiner Ausarbeitung explizit darauf hin, daß mir hier geholfen wurde!!!


----------



## timbeau (9. Jan 2012)

Ich finde nicht, dass es soo erschlichen war. Er hat auf jeden Fall auch viel Energie reingesteckt & mir gings am Anfang meines Studiums ähnlich. Neben Softwareentwicklern die noch nen Bachelor machen sieht man als Abiturient oft alt aus, zumindest am Anfang und ohne jetzt die große Affinität zum programmieren. 

Aber die Tutoren sollte man schon anders erreichen.


----------



## babuschka (9. Jan 2012)

Ich glaube, das hier ein Missverständnis vorliegt.

Es ist keineswegs so, daß dies mein Weg ist, um mit meinem Tutor zu kommunizieren.



Was kann ich dafür, wenn sich ein Tutor hier anmeldet und mich kontaktiert?

(Was ich übrigens sehr nett fand!)




Und ich möchte auch nochmal darauf hinweisen, daß mir hier nichts geschenkt wurde und alles von mir stammt (bis auf EINE Methode, die mir in der Tat vorgelegt wurde!). Ansonsten wäre die Diskussion wohl auch nicht so lang ausgefallen: Hätte man mir Musterlösungen vorgegeben, sähen die wohl auch viel besser und professioneller aus!!

Also bitte bringt mich nicht unnötig in Schwierigkeiten, indem Sachen behauptet werden, die nicht stimmen.



PS. Im Gegenteil: Die Tutoren sind sehr gut zu erreichen, da ist überhaupt nichts auszusetzen, bisher wurde mir immer kompetent geholfen.


----------



## Sonecc (9. Jan 2012)

Erschlichen hat er sich wirklich nichts. Als ich ihm die Methode geschrieben hatte, war meine Hoffnung, dass er an dem Stück Code das formatieren und das konzeptionelle Arbeiten etwas lernt. Er muss nunmal die Vorgehensweise und die Denkweise erlernen, die man als Entwickler benötigt und der sehr ausführlich dokumentierte Code sollte ihm das näher bringen.
Ich hatte die Hoffnung, dass er sich richtig damit beschäftigt und versucht nachzuvollziehen, wieso ich wann und was gemacht habe und dadurch eben etwas lernt.

Erschlichen hat er sich da nichts, nur etwas geschenkt bekommen. Dass er den Code nicht 1 : 1 kopieren soll, hatte ich ja angemerkt um eben genau das Problem zu verhindern, dass solche Vorwürfe aufkommen. Ob und wie er sich daran gehalten hat, kann ich nicht sagen, dass er darauf aber, wie er sagt, hinweist ist schon eine nette Geste, die ihm wohl nicht viel bringen wird.

Aber interessant zu sehen, dass Jango sich wieder einmischt. Man kann ja meckern, da lohnt es sich immer. Nur nie helfen oder ähnliches. Das wäre langweilig. Schade nur, dass sie diesmal keine Ahnung hatte, worum es überhaupt geht, aber das ist ja auch nicht soooo selten...


----------

