Boulder Dash nachbauen

babuschka

Top Contributor
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:
  • Spielfigur: Die Spielfigur kann in jedem Spielzug entweder nach links, rechts, oben oder unten bewegt werden. Sie kann leere Felder direkt betreten. Wird die Spielfigur auf ein Feld mit Erde bewegt, so räumt sie die Erde weg und betritt dann das leere Feld (innerhalb eines Spielzugs!). Befindet sich auf dem Feld ein Diamant, so sammelt sie diesen ein. Wird sie auf den Ausgang bewegt, endet das Spiel bzw. die Spielstufe.
  • Stein: Steine unterliegen der Schwerkraft, d.h. sie fallen nach unten, sofern sich unter ihnen
    nichts befindet. Liegen die Steine auf einer Kante (d.h. unter ihnen befindet sich etwas, aber
    links daneben und links darunter oder rechts daneben und rechts darunter nicht) so rutschen
    sie nach links bzw. rechts. Befindet sich die Spielfigur unter einem Stein, so wird sie erschlagen
    sofern der Stein bereits fällt, d.h. sich im Spielzug zuvor bereits bewegt hat.
  • Monster: Das Monster versucht die Spielfigur zu fressen. Es verfügt über eine extrem gute
    Nase und weiß daher immer ungefähr wo sich die Spielfigur befindet. Auf Basis dieses Wissens
    bewegt sich das Monster immer in Richtung der Spielfigur. Stößt es dabei auf ein Hindernis, so
    versucht es dieses zu umgehen. Findet das Monster auf dem Weg einen Diamanten, wird dieser
    zerstört. Das Monster kann sich nur auf leeren Feldern bewegen, also keine Erde wegräumen.
  • Erde: Erde ist ein Hindernis für Steine und Monster. Die Spielfigur kann sie wegräumen. Das
    Wegräumen der Erde kostet allerdings 10 Punkte Abzug, jedoch nur, wenn bereits Punkte
    vorhanden sind, d.h. der Punktestand kann nicht negativ werden.
  • Wand: Eine Wand ist ein unzerstörbares Hindernis. Das gesamte Spielfeld sollte von Wänden
    umgeben sein.
  • Diamant: Das Aufsammeln eines Diamanten bringt 200 Punkte.
  • leeres Feld: Die Spielfigur kann ohne Auswirkungen auf den Punktestand auf das leere Feld
    bewegt werden.
  • Ausgang: Wird die Spielfigur auf den Ausgang bewegt, ist das Spiel bzw. die Spielstufe gewonnen.


Implementiert die oben beschriebenen Spielelemente als Klassen. Alle Elemente sollten das Interface Element, welches vorgegeben ist (s.u.), implementieren. Das Interface stellt zwei Methoden bereit:

  • getChar: Jedes Element wird über einen bestimmten Character identifiziert (W= Wand, D= Diamant, P= Spieler, E= Erde, S= Stein, leer= leeres Feld, G= Ausgang). Diese
    Methode soll den entsprechenden Char zurückgeben. Eine Instanz vom Typ Monster würde
    also bei Aufruf 'M' zurückgeben.
  • performTurn: Diese Methode soll einen Spielzug des jeweiligen Elements ausführen. So würde
    sich die Spielfigur zum Beispiel in die Richtung bewegen, die eingegeben wurde. Bei einer
    Wand oder dem Diamant hat der Aufruf von performTurn logischerweise keinen Effekt.
    Um den Spielfluss zu regulieren, sollte performTurn in jedem Zyklus auf der Spielfigur
    und nur alle zehn Zyklen zusätzlich auf den anderen Elementen aufgerufen werden. Bei
    diesem Wert handelt es sich nur um einen Richtwert, je nach gewünschter Spielgeschwindigkeit/
    Schwierigkeit kann dieser Wert individuell angepasst werden.

Die Richtung, in die die Spielfigur bewegt wird, kann später mit Hilfe der GUI ermittelt werden.
Diese gibt bei Verwendung die gedrückte Taste zurück.
Die Bewegung des Monsters kann hier zufällig passieren. Es ist also nicht nötig, dass das Monster
sich wirklich in Richtung der Spielfigur bewegt.
Überlegt Euch vor Beginn der Implementierung eine sinnvolle Objekthierarchie für die
Elemente. Erläutert Eure Hierarchie mit Hilfe eines Diagramms.


Hier das Interface Element, das uns bereitgestellt ist:

Java:
/**
 *
 */
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.
 
Zuletzt bearbeitet von einem Moderator:
S

SlaterB

Gast
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
 
Zuletzt bearbeitet von einem Moderator:
G

Gast2

Gast
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

Top Contributor
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:

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

Also das ist meine erste Idee.
 
G

Gast2

Gast
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

Top Contributor
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.)
 
Zuletzt bearbeitet von einem Moderator:

babuschka

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

Java:
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:

Java:
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?
 
Zuletzt bearbeitet von einem Moderator:

langhaar!

Bekanntes Mitglied
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

Top Contributor
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?
 
Zuletzt bearbeitet von einem Moderator:

langhaar!

Bekanntes Mitglied
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.
 
Zuletzt bearbeitet:

babuschka

Top Contributor
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:

Java:
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...
 
Zuletzt bearbeitet von einem Moderator:

langhaar!

Bekanntes Mitglied
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

Top Contributor
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:

Java:
public void deleteElement(Element element){

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

In die Klasse Spielfeld:

Java:
public Element getElement(int i){

return elemente.get(i);

}


Und dann in der Klasse "Erde":

Java:
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!
 
Zuletzt bearbeitet von einem Moderator:

babuschka

Top Contributor
Hier meine bisherigen Ideen:

Java:
//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';
}
}

Java:
//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';

}

}

Java:
//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;
  }
}

}

Java:
//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 ' ';

}

}

Java:
//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);

}

}

Java:
//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

Top Contributor
Hier meine weiteren Ideen:

Java:
//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;

}

Java:
//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

Top Contributor
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.

:oops:
 

stikio

Mitglied
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

Gesperrter Benutzer
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!

Bekanntes Mitglied
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:
Java:
 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

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

Java:
//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

Top Contributor
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.

Java:
//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:
 
G

Gast2

Gast
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.
 
G

Gast2

Gast
Folgende 2 Codeschnipsel kommen z.B. mehrfach vor:

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

Java:
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

Gesperrter Benutzer
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

Top Contributor
Ich habe mir was überlegt.

Würde das gehen:

Java:
//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);

}


}
 
G

Gast2

Gast
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

Top Contributor
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.]
 
G

Gast2

Gast
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
Java:
public void BewegeMonster(double a, double b, char c, int d, int e)
wird dann
Java:
public void moveMonster(double a, double b, char c, int d, int e)

2) Fass gleichen Code zusammen!

Dann wird aus:

Java:
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

Java:
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

Gesperrter Benutzer
In Zeile 5 deines Codes steht:

Java:
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

Top Contributor
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.]
 
G

Gast2

Gast
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

Top Contributor
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.
 
Zuletzt bearbeitet von einem Moderator:

Sonecc

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

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

(...)
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

Top Contributor
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:

Java:
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.
 
G

Gast2

Gast
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.

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

Gesperrter Benutzer
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:

Java:
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.

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:

Java:
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:

Java:
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

Top Contributor
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:

Java:
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

Gesperrter Benutzer
...

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


Was verstehst du daran denn nicht?

Alles? Selbst nach lesen der Kommentare?
 

Sonecc

Gesperrter Benutzer
Java:
 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

Top Contributor
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!

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

Das sähe ungefähr so aus:

Java:
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.
 
Zuletzt bearbeitet:

Sonecc

Gesperrter Benutzer
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???
Aus der Aufgabenstellung:

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

Es wird in einer einfachen
.txt Datei definiert.
 

babuschka

Top Contributor
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?
 

Neue Themen


Oben