wie greife ich am einfachsten auf Gegnerische werte zu?

Status
Nicht offen für weitere Antworten.

Kell0g

Mitglied
Moin moin ihrs.

Auf der Suche nach einer Lösung für mein Problem, bin ich in diesem Forum gelandet und ich denke, dass mir hier geholfen wird. Die Boardsuche hat gezeigt, dass sich zumindest einige mit Kämpfen und ähnlichem beschäftigt haben.

Wusste nicht, ob ich das topic hier oder in in "Anfängerfragen" posten sollte, da es beide Bereiche betrifft, also entschudligt falsch ich dort hätte posten sollen.
Kommen wir also zu meinem Problem... Ich bin neu was Programmierung angeht und die OOP verwirrt mich da noch.
Habe hier das Buch "Java in a Nutshell" von o'reilly rumliegen und hab mir auch einige Java tutorials durchgeschaut, aber irgendwie komme ich nicht weiter..:/

Ich wollte mir zur Übung mal einen Textbasierten Kampf programmieren, den ich später mal erweitern kann und stoße schon bei am Anfang auf Probleme..:/


Also ich habe 2 Klassen, die jeweils für 2 unterschiedliche Monster mit unterschiedlichen Attacken(Methoden) stehen.
Jeder dieser Monster hat noch eine Methode "kampf" (ja ich weiss, dass man Methodennamen eher mit einem verb betitelt, mir ist aber nichts tolles in den Sinn gekommen), in der sein eignes Kampfverhalten definiert wird.

Code:
class Monster A{
  int = 50;
  
  public void greifeAn() {
    System.out.println("Monster A greift an!");

  }
  public void kampf() {
         if (akthp <= 0) {
           System.out.println("Monster fällt zu Boden!");
         }
         else {
           greifeAn();
         }

  }
}
class Monster B {
  int = 65;
  int mana = 40;
  
  public void greifeAn() {
    System.out.println("Monster B greift an!");
  }
  
  public void macheFeuerball() {
         if ( mana > 12) {
            System.out.println("Monster B schleudert einen Feuerball auf sein Ziel");
            mana -= 12;
         }
         else {
            System.out.println("Monster B verfügt nicht über ausreichend Mana um einen Feuerball zu erzeugen!");
         }
  }
  
  public void kampf() {

         if (akthp <= 0) {
           System.out.println("Monster fällt zu Boden!");
         }
         else {
              int rand  = 1 + (int) (Math.random()*10);
              if ( rand < 5 ){
                 feuerball();
              }
              else {
                 greifeAn();
              }
         }
  }
}
Das ist das Grundgerüst. Nun weiss ich nicht wie ich am besten Auf die Werte des Gegners zugreifen kann um seine Hp beim angriff zu verringern. Ich habe mir in den Kopf gesetzt, dass ich den Gegner als Objekt an die "kampf" Methode eines Monster übergebe und so über das gegnerische Objekt auf seine hp zugreifen kann.

Code:
public void kampf(Monster gegner) {
  ...
}

In den jeweiligen Angriffen könnte ich dann über "gegner.hp" auf seine Hp zugreifen.

Dazu müssen aber die Monster vom gleichen Objekttyp sein, ergo muss ich eine Basisklasse Monster erstellen, so dass die Monster vom gleichen Typ "Monster" sind.
Aber da beide dann vom Typ Monster sind , kann ich nur auf Methoden in der Klasse Monster zugreifen. Also müsste ich Methoden in der Basisklasse "Monster " erzeugen und sie überschreiben lassen oder nicht? Dazu müsste ich doch jede Methode in der Basisklasse erzeugen oder nicht?
Wäre das aber nicht bisschen blöd, wenn ich später z.b. 10 Monster habe und jeder um die 5 verscheidene Angriffe hat?

Wie löse ich das am besten?geht das so überhaupt wie ich es mir vorgestellt habe, dass ich den gegner als Objekt an die "Kampf"-methode übergebe und so auf ihn zugreife?
oder muss ich da mit get und set methoden arbeiten? schon oder? und wie geht das am besten?

ich hoffe es ist einigermaßen verständlich.

ich weiß es gehört zum grundwissen der OOP, aber irgendwie verwirr ich mich da immerweiter.
 

Quaxli

Top Contributor
"int = 65" ist aber kein funktionierender Code....


Eine Basisklasse für alle Monster ist schon mal ziemlich sinnvoll. Da kannst Du auf jeden Fall das reinpacken, was jedes Monster so braucht ;)

Auf die Attribute des Monster würde ich über sog. Getter-/Setter-Methoden zugreifen. Das heißt Du schreibst Dir Methoden, wie im folgenden Beispiel:

Nehmen wir an, Du hast die Hitpoints als int hp = 50 definiert.

Code:
public int getHP(){
  return hp;
}

public void setHP (int i){
 hp = i;
}

Da Du sowas für jedes Monster brauchst, wäre das schon mal was für die Basisklasse. Ob Du den Kampf dann innerhalb der Methode eines einzelnen Monster abwickelst oder dafür eine eigene Klasse schreibst bleibt Dir dann eigentlich selbst überlassen.
Wenn Du komplexere Abläufe vorhast, wäre eine eigene Klasse relativ sinnvoll. Und für Dich auch die bessere Übung ;)

Wass die Kampfmöglichkeiten betrifft, würde ich das etwas genereller angehen. Du könntest z. B. in Deiner Basisklasse alle möglichen Angriffe definieren und dann für die einzelnen Monster Attribute (Variablen) setzen, ob diese die einzelnen Möglichkeiten zur Verfügung haben. Dies könntest Du ja z. B. über etwas Logik im Konstruktor festlegen.

Viel Spaß beim Monster-Basteln.
 

Kell0g

Mitglied
gut gut.

Irgendwie mag ich mich mit dem Gedanken nicht anfreunden, dass ich die Attacken in die Basisklasse packen soll. Dachte, dass ich sie jeweils in der entsprechenden Monster Klasse lassen kann, da ja jedes Monster unterschiedliche Attacken besitzt.

Und zu der Kampfklasse, dachte halt da sichd as Kampfverhaltend er Monster unterscheidet es so auch
in die Klasse der jeweiligen Monster gehört.
Aber ich glaube hier liegt mein Problem,dass ich ich zu sehr an meinen gedankn festhalte und mich da nich lösen kann.

hab nun was mit gettern udn settern versucht...

Code:
class Mob {
  int hp;
  int dmg;
  
  public Mob (int hp) {
      this.hp = hp;
  }
  public int getHp() {
    return hp;
  }
  public void setHp () {
    this.hp = hp;
  }
  public void reduceHP(int dmg) {
    this.hp-= dmg;
  }
  
  public void angriff (Mob m, int dmg) {
    System.out.println("greife an");
    this.dmg = dmg;
    m.reduceHP(dmg);
    System.out.println(dmg);
    System.out.println(m.getHp());
    
  }
}

class MobA extends Mob {
  int hp = 50;
  
  public void angriff (Mob m, int dmg) {
    System.out.println(m.getHp());
    this.dmg = dmg;
    m.reduceHP(dmg);
  }
}
class MobB extends Mob {
  int hp = 30;
  
  public void angriff (Mob m) {
    System.out.println(m.getHp());
    this.dmg = dmg;
    m.reduceHP(dmg);
  }
}

und dann
Code:
public class testspiel {

  public static void main(String[] args) {
         Mob moA = new Mob(50);
         Mob moB = new Mob(30);
         
         moA.angriff(moB,20);
         moB.angriff(moA,30);
  }
}

aber hierbei wird die methode der Basisklasse gestartet. ich dachte diese Methode der Basisklasse wird durch die Methoden der Monster überschrieben ?
 

Fu3L

Top Contributor
Beim MobA müsste eigentlich die Methode der subklasse aufgerufen werden. Bei MobB wird wohl die Methode der Basisklasse aufgerufen, weil du in der Definition von MobB für die Methode angriff andere Parameter verwendest (konkret: du hast ein zweite Methode geschrieben, die keinen int-wert erwartet und this.dmg = dmg; macht im Prinziep gar nix, weils beides ein und die selbe Instanzvariable ist)

Die Setter sehen schon gut aus und die Methode reduceHP ist auch gut.

Als Anregung zur Namensfindung bei Methoden: Anstatt von kampf vllt kaempfen? und anstatt von angriff vllt angreifen? (oder, da du englische Variablennamen benutzt fight und attack?)
 

Kell0g

Mitglied
oh das bei MobB hab ich übersehen..:D

aber irgendwie zeigt er mir die angriff-methode der Basisklasse an...:(

aber wenn das so sein soll, dann hab ich immer die Attacken doppelt, einmal in der Basisklasse, und in der Klasse des Monsters, welche dann die Attacke in der Basisklasse überschreibt.
 

Quaxli

Top Contributor
Kell0g hat gesagt.:
gut gut.

Irgendwie mag ich mich mit dem Gedanken nicht anfreunden, dass ich die Attacken in die Basisklasse packen soll. Dachte, dass ich sie jeweils in der entsprechenden Monster Klasse lassen kann, da ja jedes Monster unterschiedliche Attacken besitzt.

U

Mußt Du ja nicht. War ja nur ein Vorschlag und nicht das 11. Gebot ;)

Du könntest auch ein Interface definieren, über das Du jedes Monster mit einer Angriffs-Methode versorgst. Du muß ja nicht für jede Angriffsart eine Methode schreiben. Du könnest ja auch eine reine Testausgabe machen.

Vielleicht so:

Code:
class FrankStone{


  ...
  //Methode evtl. über Interace implementiert
  public void attackEnemy(){
     System.out.println("Attacke mit Mundgeruch");
     kaspereDieAttackeAus();
     sonstigerKram(); 
    ....
  }
  ...


}


class DoomRunner(){


  ...
  //Methode evtl. über Interace implementiert
  public void attackEnemy(){
     System.out.println("Feuere BFG9000 ab");
     kaspereDieAttackeAus();
     sonstigerKram(); 
    ....
  }
  ...


}
 

Fu3L

Top Contributor
Kell0g hat gesagt.:
oh das bei MobB hab ich übersehen..:D

aber irgendwie zeigt er mir die angriff-methode der Basisklasse an...:(

aber wenn das so sein soll, dann hab ich immer die Attacken doppelt, einmal in der Basisklasse, und in der Klasse des Monsters, welche dann die Attacke in der Basisklasse überschreibt.

Du kannst die Methode in Monster auch abstract machen:

Code:
abstract class Monster {

public abstract void attack(parameter);

}

Dann ist jede Unterklasse gezwungen die Methode zu überschreiben und mit Sinn zu erfüllen und in der Basisklasse musst du die nciht mehr schreiben... Der Nachteil: Du musst Monster ebenfalls abstract machen, weil eine Klasse mit abstracter Methode nur abstract sein kann (d.h. man kann keine Instanzen von ihr bilden).
Vorteil (jezz besonders auf dein Problem bezogen): Du kannst sicher sein, dass auf keinen Fall die Methode der Basisklasse aufgerufen wird :wink:
 

Kell0g

Mitglied
@Quaxli die Mundgeruch attacke ist nett..:) vllt übernehme ich sie sogar..:D

Yey danke für die hilfe...!

Es klappt...!!!!nun kann ich versuchen das etwas zu erweitern...\o/

Ausgabe:
Monster B HP: 30
GRUUAAAGHGH! Monster A greift an!
Monster B HP: 10
monster A HP: 50
HÖHÖ!!Monster B greift an!
monster A HP: 20


\o/
 

Kell0g

Mitglied
und shcon stocke ich wieder..:/

Code:
 public void angriff() {
    int dmg = 15;
    System.out.println("Monster B HP: "+m.getHp());
    System.out.println("GRUUAAAGHGH! Monster A greift an!");
    m.reduceHP(dmg);
    System.out.println("Monster B HP: "+m.getHp());
  }
  public void fight(Mob m) {
	  angriff();
  }
}

müsste das nicht gehen?Da ich ja "fight" "m" übergebe, müsste "m" dann für angriff() bekannt sein oder nicht? anscheindend nicht..da er mir rummeckert...:/
 

Fu3L

Top Contributor
Entweder du definierst m als Instanzvariable und schreibst:

Code:
class Monster (oder ähnliches) {

Mob m;

public void angriff() {
    int dmg = 15;
    System.out.println("Monster B HP: "+m.getHp());
    System.out.println("GRUUAAAGHGH! Monster A greift an!");
    m.reduceHP(dmg);
    System.out.println("Monster B HP: "+m.getHp());
  }
  public void fight(Mob m) {
this.m = m
     angriff();
  }
}

Oder du gibst die Variable weiter an angriff:

Code:
public void angriff(Mob m) {
    int dmg = 15;
    System.out.println("Monster B HP: "+m.getHp());
    System.out.println("GRUUAAAGHGH! Monster A greift an!");
    m.reduceHP(dmg);
    System.out.println("Monster B HP: "+m.getHp());
  }
  public void fight(Mob m) {
     angriff(m);
  }
}

Eine Variable, die erst in einer Methode definiert wird, ist auch nur dort gültig und nach Verlassen der Methode wieder gelöscht.
 

Kell0g

Mitglied
so bin nun soweit:

Code:
abstract class Mob {
  int hp;
  int mana;
  int dmg;
  Mob m;
  String name;
  
  public Mob (int hp, int mana) {
      this.hp = hp;
      this.mana = mana;
  }
  
  public int getHp() {
    return hp;
  }
  public void setHp(int hp) {
    this.hp = hp;
  }
   
  public int getMana() {
	return mana;
  }
  public void setMana(int mana) {
	this.mana = mana;
  }
  
  public void entzieheMana(int entzug){
  	this.mana -= entzug;
  }
  
  public void reduceHP(int dmg) {
    this.hp -= dmg;
  }
  
  public abstract void angriff();
  public abstract void fight(Mob m);

}

class Goblin extends Mob {
 
	  
  public Goblin(int hp,int mana) {
		super(hp, mana);
	}

public void angriff() {
    int dmg = 15;
    System.out.println(name+" HP: "+m.getHp());
    System.out.println("Goblin greift an!GRUUAAAGHGH!");
    m.reduceHP(dmg);
    System.out.println(name+" HP: "+m.getHp());
  }
  public void fight(Mob m) {
	  this.m = m;
	  name = m.toString();
	  angriff();
  }
}

class GoblinSchamane extends Mob {
	
  public GoblinSchamane(int hp,int mana) {
		super(hp, mana);
		
	}
  
  public void angriff () {
    dmg = 10;
    System.out.println(m.toString()+" HP: "+m.getHp());
    System.out.println("Goblin Schamane greift an!");
    m.reduceHP(dmg);
    System.out.println(m.toString()+" HP: "+m.getHp());
  }
  
  public void macheFeuerball() {
	  dmg = 25;
	  if (mana <= 12) {
		  System.out.println("Goblin Schamane verfügt nicht über ausreichend Mana, um einen Feuerball zu erzeugen!");
	  }
	  else {
		  System.out.println(m.toString()+" HP: "+m.getHp());
		  System.out.println("Goblin Schamane erzeugt einen Feuerball und schleudert ihn auf sein Ziel!");
		  mana -= 12;
		  m.reduceHP(dmg);
		  System.out.println(m.toString()+" HP: "+m.getHp());
		  System.out.println("Mana von Gobo scham: "+mana);
	  }
  }

  public void fight(Mob m) {
	  this.m = m;
	  int rnd = 1+(int) (Math.random()*25);
	  
	  if (rnd <6) {
		  macheFeuerball();
	  }
	  else {
		  angriff();
	  }
	
  }
}

class Troll extends Mob {
	  public Troll(int hp,int mana) {
			super(hp, mana);
	  }
	  
	  public void angriff() {
		  dmg = 40;
		  System.out.println(m.toString()+" HP: "+m.getHp());
		  System.out.println("Troll greift an!");
		  m.reduceHP(dmg);
		  System.out.println(m.toString()+" HP: "+m.getHp());		  
	  }
	  
	  public void fight(Mob m) {
		  this.m = m;
		  angriff();
	  }
}
gibts irgendwelche anmerkungen?

irgendwie funktioniert das objekt.toString() nicht, weiss nicht warum...:/ "m" ist das objekt also m.toString(), aber er zeigt mir weiterhin sowas wie "Goblin@190d11" ergo irgendwie führt er wohl die toString() methode nicht aus. aber warum?
bestimmt isses was ganz blödes udn ich überseh es die ganze zeit..:(
 

Quaxli

Top Contributor
Nein, das ist schon o.k. so. toString() macht nur nicht das was Du denkst ;)
Schau mal in die API. toString ist in der Klasse Object definiert und von da erben es alle anderen Klassen.
 

Kell0g

Mitglied
habe hier ein kleines Problem und zwar.
wenn ich

MonterA.fight(MonsterB);
MonsterB.fight(MonsterA);

mache, dann läuft alles gut. Jedoch wenn ich das in folgende while schleife mache

while (MonsterA.getHP() <= 0 || MonsterB.getHP() <= 0 ) {

..
}

kommt es zu einer endlosschleife und der Kampf fängt bei -500000(total hoher Zahl) hp an.
Liegts daran, dass in der Bedingung getter sind?

wenn ich die methoden einzelnd aufrufe, bekomme ich das richtige zurück.
 

Kell0g

Mitglied
also hier ist der Grundaufbau:

[HIGHLIGHT="Java"]class Mob {
String name;
private int hp;
private int mana;
private int dmg;
Mob m;

public Mob (int hp, int mana) {
this.hp = hp;
this.mana = mana;
}

public String getName() {
return name;
}

public int getHp() {
return hp;
}
public void setHp(int hp) {
this.hp = hp;
}

public int getMana() {
return mana;
}
public void setMana(int mana) {
this.mana = mana;
}

public void useMana(int entzug){
this.mana -= entzug;
}

public void reduceHP(int dmg) {
this.hp -= dmg;
}

public void angriff() {}
public void fight(Mob m) {}

}

class Goblin extends Mob {

String name = "Goblin";

public Goblin(int hp,int mana) {
super(hp, mana);
}

public void angriff() {
int dmg = 15;
System.out.println(m.getName()+" HP: "+m.getHp());
System.out.println("Goblin greift an!");
m.reduceHP(dmg);
System.out.println(m.getName()+" HP: "+m.getHp());
}
public void fight(Mob m) {
this.m = m;
if (getHp() <= 0 ) {
System.out.println("Der Goblin fällt auf den Boden und bleibt regungslos liegen!");
}
else {
angriff();
}
}
}[/HIGHLIGHT]

Das zweite Monster Sieht vom Aufbau her gleich aus. In der Steuerklasse will ich halt die Monster gegen sich kämpfen lassen bis sie sterben , hp <=0 .

also
[HIGHLIGHT="Java"]public class kampf {

public static void main(String[] args){


Goblin gobo = new Goblin(50,0);
GoblinSchamane goboschamane = new GoblinSchamane(65,40);

// while (gobo.getHp() >= 0 || goboschamane.getHp() >= 0) {
gobo.fight(goboschamane);
goboschamane.fight(gobo);
// }
}
}[/HIGHLIGHT]
und da kommt es bei der Schleife zu keinem Ende und der Kampf fängt wie gesgat bei komischen HP Angaben an.
 
Zuletzt bearbeitet von einem Moderator:

Kell0g

Mitglied
[highlight=java]
class GoblinSchamane extends Mob {

public GoblinSchamane(int hp,int mana) {
super(hp, mana);

}

public void angriff () {
int dmg = 10;
System.out.println(m.getName()+" HP: "+m.getHp());
System.out.println("Goblin Schamane greift an!");
m.reduceHP(dmg);
System.out.println(m.getName()+" HP: "+m.getHp());
}

public void macheFeuerball() {
int dmg = 25;
if (getMana() <= 12) {
System.out.println("Goblin Schamane verfügt nicht über ausreichend Mana, um einen Feuerball zu erzeugen!");
}
else {
System.out.println(m+" HP: "+m.getHp());
System.out.println("Goblin Schamane erzeugt einen Feuerball und schleudert ihn auf sein Ziel!");
useMana(12);
m.reduceHP(dmg);
System.out.println(m+" HP: "+m.getHp());
System.out.println("Mana von Goblin Schamane: "+getMana());
}
}

public void heileSich() {
if (getMana() <= 10) {
System.out.println("Goblin Schamane verfügt nicht über ausreichend Mana um sich zu heilen!");
}
else {
System.out.println("Goblin Schamane versucht sich zu heilen!");
setHp(10);
useMana(5);
}
}

public void fight(Mob m) {
this.m = m;
int rnd = 1+(int) (Math.random()*30);

if (getHp() <= 0) {
System.out.println("Goblin fällt zu Boden und bleibt regungslos liegen.");
}
else {
if (rnd <10) {
macheFeuerball();
}
else {
angriff();
}
}
}
}
[/highlight]

die Ausgabe ist wie folgt:

...
Der Goblin fällt auf den Boden und bleibt regungslos liegen!
Goblin Schamane verfügt nicht über ausreichend Mana, um einen Feuerball zu erzeugen!
Der Goblin fällt auf den Boden und bleibt regungslos liegen!
Goblin@a90653 HP: -769585
Goblin Schamane greift an!
Goblin@a90653 HP: -769595
Der Goblin fällt auf den Boden und bleibt regungslos liegen!
Goblin@a90653 HP: -769595
Goblin Schamane greift an!
Goblin@a90653 HP: -769605

usw...., wie gesagt es hört nicht auf, vllt doch irgendwann in der Zukunft :/

der Name des Monster ist da noch ohne benutzung der getName() Methode, obwohl die im obrigen Quelltext aufgeführt ist, daher siehts so aus. Habe sie beim Schreiben des Beitrags einfach mal im Post hinzugefügt.
 
Zuletzt bearbeitet:

Ebenius

Top Contributor
Wo ist denn da das Problem. Die Lebensenergie des Goblin ist zuerst aufgebraucht. Ab diesem Zeitpunkt greift der Goblin den Schamanen nicht mehr an; siehe Zeile 61, drei Code-Blöcke hoch. Der Schamane wird also nie mehr vom Goblin angegriffen, verliert daher keine Lebensenergie. Er greift immer wieder den Goblin an, und der verliert immer weiter an Lebensenergie.

Ebenius
 

Civilazi

Bekanntes Mitglied
Für eine intelligente Ausgabe fordere einfach, dass beide Monster noch positives Leben haben(aus dem "oder" - || ein "und" - && machen). Nur solang soll weitergekämpft werden. Trifft die Bedingung nicht zu, ist wenigstens eins der Monster k.o.
 

Kell0g

Mitglied
Wo ist denn da das Problem. Die Lebensenergie des Goblin ist zuerst aufgebraucht. Ab diesem Zeitpunkt greift der Goblin den Schamanen nicht mehr an; siehe Zeile 61, drei Code-Blöcke hoch. Der Schamane wird also nie mehr vom Goblin angegriffen, verliert daher keine Lebensenergie. Er greift immer wieder den Goblin an, und der verliert immer weiter an Lebensenergie.

Ebenius

dass der Goblin tot ist ist richtig.
mir gehts darum, dass der Kampf bei den jewieligen HP Angaben,also 65 und 50, starten soll und bei 0 und etwas darunter aufhört und nicht in diesen komischen dimensionen ( - 700000) sich rumtreibt.

dies erreiche ich ja wenn ich sowas wie das :

[highlight=java]
gobo.fight(goboschamane);
goboschamane.fight(gobo);
gobo.fight(goboschamane);
goboschamane.fight(gobo);
gobo.fight(goboschamane);
goboschamane.fight(gobo);
gobo.fight(goboschamane);
goboschamane.fight(gobo);
[/highlight]

hinschreibe und da ich das vermeiden will, soll es halt in eine Schleife rein.


@ Civilazi
danke für den Tipp werde ich mal versuchen.
edit:ausprobiert und ich bekomme das was ich will.:) Jetzt zeigt er nur nicht die Meldung das Das Monster tot ist, aber das denke ich lässt sich leicht lösen. Danke
 
Zuletzt bearbeitet:
Status
Nicht offen für weitere Antworten.

Neue Themen


Oben