Labyrinth über MazeGameServer visualisieren

jono

Top Contributor
Java:
import java.util.ArrayList;
import java.util.List;

public class Field {
   
    FieldType PATH;
    List<BaitType> baittypes = new ArrayList<BaitType>();
}
@mrBrown
 

jono

Top Contributor
Dem Field sagen, dass es einen FieldType PATH hat, der ja true ist, nun will ich dem PATH sagen, dass sich nur auf diesem die Baits befinden können...
 

mrBrown

Super-Moderator
Mitarbeiter
Damit sagst du nur, das Field eine Variable vom FieldType hat, die du "PATH" nennst, die aber bisher keinen Wert hat, effektiv steht da FieldType PATH = null;. Nur weil die Variable PATH heißt, hat die noch nichts mit dem Enum icode]FieldType.PATH[/icode] zu tun.
 

mrBrown

Super-Moderator
Mitarbeiter
Erstmal die Frage, warum sollte der FieldType wissen, welche Baits wo sind, und warum sollte irgendein Bait einen FieldType kennen?
 

jono

Top Contributor
Der FieldType PATH sollte meiner Meinung keinen BaitType kennen aber, sollte wissen, dass sich auf dem FieldType PATH nur Baits verbergen können. Ich meine irgendwie muss man den Feldern ja sagen dass sie entweder Baits enthalten dürfen/oder eben auch nicht. Ansonsten könnten diese ja überall verteilt sein.
 

mrBrown

Super-Moderator
Mitarbeiter
Der FieldType PATH sollte meiner Meinung keinen BaitType kennen aber, sollte wissen, dass sich auf dem FieldType PATH nur Baits verbergen können. Ich meine irgendwie muss man den Feldern ja sagen dass sie entweder Baits enthalten dürfen/oder eben auch nicht. Ansonsten könnten diese ja überall verteilt sein.
Ein Feld darf also nur Baits enthalten, wenn der FieldType PATH ist?


Wie fügst du denn aktuell überhaupt Baits zu einem Feld hinzu?
 

jono

Top Contributor
Ein Feld darf also nur Baits enthalten, wenn der FieldType PATH ist?
Ja, dass ein Spieler darf auch nur den FieldType PATH betreten bzw. macht es auch nur so Sinn, da das ja der Labyrinthweg ist.
Wie fügst du denn aktuell überhaupt Baits zu einem Feld hinzu?
Das ist ja das Problem, was ich gerade versuche zu lösen durch die List. Eine List enthält BaitTypes. Wie füge ich diese aber dem FieldType hinzu?
 

jono

Top Contributor
Ja, aber gemeint ist dasselbe von mir.
Natürlich sind alle BaitTypes zusammengefasst die Baits, welche aber nur einem FieldType zugeordnet werden sollen darum geht es mir.
Es hieß ja ich solle am besten eine Klasse Field erstellen, das habe ich ja auch getan.
 

mrBrown

Super-Moderator
Mitarbeiter
Ja, aber gemeint ist dasselbe von mir.
Zwischen Feld/Field und FieldType ist ein sehr großer Unterschied!



Um noch mal einen Schritt zurückzugehen:
Das Maze ist aufgebaut wie ein Schachbrett, es besteht aus mehreren einzelnen Feldern (=Field).
Wie bei einem Schachbrett hat jedes Feld einen Typen (=FieldType) – beim Schach zB Schwarz oder Weiß, bei dir Weg, Wand und unbekannt.
Auf einem Feld, wenn es den Typ Weg hat, können mehrere Baits (=BaitType) liegen. Oder andersausgedrückt: Wenn ein Feld den FeldTyp Weg hat, kann man Bait hinzufügen.
Wenn man ein Bait einem Feld mit dem Typ Wand hinzufügt, passiert entweder nichts oder es wird eine Fehler geworfen.


Das kann man im wesentlichen so runter programmieren.

Der Typ kann sich für ein Feld nicht ändern, der wird direkt zu Beginn festgelegt - was eignet sich für sowas am besten

Für die Baits eines Feldes sollte es keinen einfachen Getter geben

Das Feld kann zB eine Methode baitPlatzieren haben
 
K

kneitzel

Gast
Du hast aber doch viele Felder, die alle über eine Instanz vom Typ Field abgebildet werden sollen. Und diese Felder können FieldType.PATH sein oder eben auch von anderen Typen (Also z.B. FieldType.UNKNOWN oder was es da sonst so gibt).

Also hat ein Feld erst einmal keinen PATH.
Ein Feld hat einen FeldTypen und dieser kann PATH sein.

Code:
import java.util.ArrayList;
import java.util.List;

public class Field {
  
    FieldType fieldType;
    List<BaitType> baits = new ArrayList<BaitType>();
}

(Ich habe diese baittypes mal in baits umbenannt. Baits als solches gibt es eigentlich nicht, denn Du hast nur diese Types meine ich. Eine weitere Klasse gibt es nicht. Könnte man also auch entsprechend umbenennen.)

Nun könntest Du also eine Methode addBait(BaitType bait) machen. Diese sollte man aber nur auf einem Feld vom typ PATH ablegen können. Und den Erfolg könnte man über einen Return-Wert zurück geben ... Das könnte man prüfen. Falls Du den FieldType mit gewisser Logik implementiert hast, dann weiß ein Typ, ob ein Spieler ein Feld von dem typ betreten könnte. Das könnte man dann als Logik ebenfalls nutzen statt dem starren beharren auf PATH. Falls es später weitere Typen gibt, die ein Spieler ggf. auch betreten kann, dann hast Du sonst das Problem, da die Logik Stellen alle zu finden, die Du anpassen müsstest ....)

Code:
public boolean addBait(final BaitType bait) {
  // Prüfe, ob der Typ passt. Ggf. false zurück geben!
  // Füge bait dem feld hinzu
  // true zurück geben
}

Also in den Kommentaren habe ich die Funktionalität geschrieben. Würdest Du dies so hin bekommen?
 

jono

Top Contributor
Nein, weiß ich nicht direkt. Im Prinzip kann man ja in natürlicher Sprache sagen, dass wenn die Position des Baits der Position des FieldTypes PATH entspricht, dass bait der Position des PATH hinzugefügt werden kann und true returnt.
Falls Du den FieldType mit gewisser Logik implementiert hast, dann weiß ein Typ, ob ein Spieler ein Feld von dem typ betreten könnte. Das könnte man dann als Logik ebenfalls nutzen statt dem starren beharren auf PATH.
In der Methode "isplayerAllowed" in der enumeration die du mir auf Seite 5 genannt hast, könnte man dies machen oder? Könnte doch aber auch in der Klasse Field festlegen, ob ein Spieler ein feldtyp betreteten darf oder nicht?
 
Zuletzt bearbeitet:

mrBrown

Super-Moderator
Mitarbeiter
Du denkst viel zu Kompliziert. Weder ein PATH noch ein Bait hat eine Position.

Es gibt Felder.
Wenn ein Feld den Typ PATH hat, kann man einen Bait hinzufügen.

Dafür brauchst du eine einzelne Methode, die Signatur wurde dir schon genannt, und in der Methode nur ein if und darin einen Methodenaufruf.
 

jono

Top Contributor
Ich komme einfach nur nicht klar gerade mit dem genauen Codieren.
Warum brauche ich noch einen Methodenaufruf in der Methode?
Wie kann man denn einfach mal überprüfen, ob das Feld den Typ PATH hat.Das ist das erste "große" Projekt, was applikationsspezifisch erstellt werden muss(was jede Aufgabe prinzipiell muss) aber in diesem Rahmen ist es noch schwieriger und erfordert genau und gesetzten Code, um die Aufgabe als solche korrekt zu bearbeiten
Ich bitte da echt um Verständnis. Ich verstehe ja, was ich machen soll, nur teilweise fehlen mir die genauen Sprachbefehle. If-Anweisung ist ja klar...
 
Zuletzt bearbeitet:

mrBrown

Super-Moderator
Mitarbeiter
Wie kann man denn einfach mal überprüfen, ob das Feld den Typ PATH hat.
Wenn wir jetzt einfach mal von dem Code von @JustNobody ausgehen:

Der Typ des Feldes steht in der Variable fieldType. Um zu prüfen, ob diese PATH ist: this.fieldType == FieldType.PATH.

Das ist das erste "große" Projekt, was applikationsspezifisch erstellt werden muss(was jede Aufgabe prinzipiell muss) aber in diesem Rahmen ist es noch schwieriger und erfordert genau und gesetzten Code, um die Aufgabe als solche korrekt zu bearbeiten

Große Projekte muss man einfach nur in kleine Teile aufteilen - an diesem Problem jetzt sind zB grad mal drei verschiedene Klassen beteiligt, und zwei davon sind schlichte Enums ;)
 
Zuletzt bearbeitet:

jono

Top Contributor
Der Typ des Feldes steht in der Variable fieldType.
Ouhman, habe die Instanzvariable von FieldType gar nicht mehr in Betracht gezogen. Danke :)

Große Projekte muss man einfach nur in kleine Teile aufteilen. An diesem Problem jetzt grad sind grad mal drei verschiedene Klassen beteiligt, und zwei davon sind schlichte Enums
Ja deshalb hatte ich meinen Beitrag #117 nochmal bearbeitet, weil das mit den vielen Klassen nicht stimmte :D

Java:
public class Field {

    FieldType fieldType;
    List<BaitType> baittypes = new ArrayList<BaitType>();

    public boolean addBait(final BaitType bait) {
        if (this.fieldType == FieldType.PATH) {
            baittypes.add(bait);
        } else {
            return false;
        }
        return true;
    }
}
Das wäre der Code bis jetzt, jedoch:
baittypes.add(bait) erfüllt ja nicht genau das was @JustNobody sagte:
// Füge bait dem feld hinzu
Bei mir wird es ja nur der Liste inzugefügt, wie spezifiziere ich das jetzt?
 

jono

Top Contributor
Deshalb habe ich gerade nochmal den PC hochgefahren, weil mir das auch eingefallen ist vor dem Einschlafen^^
List<BaitType> baittypes = new ArrayList<BaitType>();
Dementsprechend müsste man dies in:
Java:
List<FieldType> fieldTypes = new ArrayList<FieldType>();
umändern, oder habe ich das jetzt selbstsicher falsch umgeändert?
 

jono

Top Contributor
Aber dann würde die add Funktion nicht mehr so funktionieren wie sie hier steht:
Java:
    List<FieldType> fieldTypes = new ArrayList<FieldType>();

    public boolean addBait(final BaitType bait) {
        if (this.fieldType == FieldType.PATH) {
            fieldTypes.add(bait);
        } else {
            return false;
        }
        return true;
 

mrBrown

Super-Moderator
Mitarbeiter
Dementsprechend müsste man dies in:
Java:
List<FieldType> fieldTypes = new ArrayList<FieldType>();
umändern, oder habe ich das jetzt selbstsicher falsch umgeändert?
Das ist Unsinn..

Ein Feld hat einen Feld-Typen und mehrere Baits -> FieldType als eine Variable und eine Liste von Baits als eine andere Variable.



Wie kommst du denn darauf, dass ein Feld eine Liste von Typen hat? Soll ein Feld gleichzeitig Weg und Wand sein? o_O
 

jono

Top Contributor
Java:
public class Field { 
  FieldType fieldType; 
  List<BaitType> baittypes = new ArrayList<BaitType>(); 
  public boolean addBait(final BaitType bait) {
    if (this.fieldType == FieldType.PATH) { 
      baittypes.add(bait); 
    } else { 
      return false; 
    } 
    return true; 
    } 
  }
Dann muss das ja korrekt sein ??

Weil es ja hieß:
Ein Feld hat einen Feld-Typen und mehrere Baits -> FieldType als eine Variable und eine Liste von Baits als eine andere Variable.
Es heißt ja dass ein feld einen Feld-Typen hat und mehrere Baits.
Einen Feld-Typen hat es ja durch die Variable "FieldType" und durch die BaitType Liste wird dem Feld ja ein bzw. mehrere Baits hinzugefügt.
 
Zuletzt bearbeitet von einem Moderator:

Plauzi92

Aktives Mitglied
Als jemand der die gleiche Aufgabe lösen muss, hätte ich hier einen Tipp:

Der FieldType PATH sollte meiner Meinung keinen BaitType kennen aber, sollte wissen, dass sich auf dem FieldType PATH nur Baits verbergen können. Ich meine irgendwie muss man den Feldern ja sagen dass sie entweder Baits enthalten dürfen/oder eben auch nicht. Ansonsten könnten diese ja überall verteilt sein.

Alle Positionen werden dir vom Server übermittelt. Lass dir mal die Ausgaben vom Server in die Konsole schreiben, dann sollte es klar sein. Der Server wird dir kein Bait in eine Mauer legen. Du musst das alles nur in JavaFX darstellen. Lediglich die Spielerbewegung führt zu einer Überprüfung.
Auch wenn der Prof sagte, dass man mit dem StatusModel anfangen sollte, kann es nicht schaden sich vorher mal über das Gesamtkonzept Gedanken zu machen.
 

Plauzi92

Aktives Mitglied
Also willst du die Informationen die vom Server kommen überprüfen, falls du sie im Client falsch interpretierst? Finde ich jetzt nicht wirklich sinnvoll. Wenn du die Koordinaten der Baits einfach vom Server übernimmst, werden sie nicht in einer Wand landen.
 

Plauzi92

Aktives Mitglied
Defensive Programmierung und kenntlich machen von Constraints wären zwei Punkte dafür

Indem ein Bait über die zugehörige Klasse erstellt wird, ist dessen Position doch klar definiert. Wenn der Server ein Bait in einer Mauer erstellt, ist es eigentlich ziemlich egal was im Client passiert, da es keine Möglichkeit gibt dem Server mitzuteilen, dass das Bait an einer falschen Position ist.
Es wird durch die Überprüfung lediglich verhindert, dass das Bait gezeichnet wird. Tatsächlich liegt es aber dennoch in der Mauer. Deswegen finde ich die Überprüfung irrelevant. Aber wie Jono schon sagte:

Ja, gut aber ist jetzt kein Code der Punkte abzieht, kann da ja jeder machen wie er möchte
 

jono

Top Contributor
Java:
private FieldType fieldType = FieldType.PATH;
@mrBrown Wie weise ich jetzt noch die anderen 2 Feldtypen UNKNOWN und WALL der Variable zu, sodass diese nicht mehr null ist?
Java:
fieldType = FieldType.WALL;
fieldType = FieldType.UNKNOWN;
das ist ja schonmal falsch.
 
K

kneitzel

Gast
Um Augenblick verstehe ich nicht, was Dein Problem ist.

Ein Feld hat genau einen FieldType. Den FieldType kannst du im Konstruktor setzen oder über einen Setter.

Wenn du das Maze aufbaust, dann wirst du vermutlich viele Felder erstellen. Und das abhängig von dem Zeichen, das für das jeweilige Feld vorgesehen ist ....
 

jono

Top Contributor
Um Augenblick verstehe ich nicht, was Dein Problem ist.

Ein Feld hat genau einen FieldType. Den FieldType kannst du im Konstruktor setzen oder über einen Setter.

Wenn du das Maze aufbaust, dann wirst du vermutlich viele Felder erstellen. Und das abhängig von dem Zeichen, das für das jeweilige Feld vorgesehen ist ....
Ein Feld hat einen Feld-Typen und mehrere Baits -> FieldType als eine Variable und eine Liste von Baits als eine andere Variable.
1. Es ging doch jetzt darum in der Klasse Field eine Instanzvariable zu erstellen, da diese ja FieldTypes hat? Diese Variable sollte nicht null sein?
2. Um diese Variable nicht null sein zu lassen habe ich sie so instanziiert.
Wie ist das jetzt genau gemeint, den FieldType im Konstruktor zu setzen, welchen Zweck erfüllt das denn?
 
Zuletzt bearbeitet:
K

kneitzel

Gast
Du kannst einem Konstruktor Parameter mitgeben um dann die neue Instanz entsprechend zu initialisieren.

Wenn du Field einen Konstruktor gibst, der ein FieldType entgegen nimmt, dann könntest du die Instanzvariable entsprechend setzen.

Oder du übergibst den String, den der Server für das Feld vorgibt, um dann in Abhängigkeit vom String den Typ zu setzen.

Und dann hatte ich, so ich mich recht erinnere, auch schon geschrieben, wie man diese Auswahl Logik sogar in den FieldType verlegen kann (so man das möchte).
 

jono

Top Contributor
Wenn du Field einen Konstruktor gibst, der ein FieldType entgegen nimmt, dann könntest du die Instanzvariable entsprechend setzen.
Oder du übergibst den String, den der Server für das Feld vorgibt, um dann in Abhängigkeit vom String den Typ zu setzen.
Also kann ich es jetzt so oder so machen?

Wenn du Field einen Konstruktor gibst, der ein FieldType entgegen nimmt, dann könntest du die Instanzvariable entsprechend setzen.
Kann man in einer Klasse einen Konstruktor erstellen, der Werte von dem enum entgegen nimmt, wusste ich auch noch nicht.
Wie genau soll das dann aber jetzt aussehen, was meinst du mit:
dann könntest du die Instanzvariable entsprechend setzen.
Die Instanzvariable kann man doch auch ohne Konstruktor setzen/erstellen ? ^^

Und dann hatte ich, so ich mich recht erinnere, auch schon geschrieben, wie man diese Auswahl Logik sogar in den FieldType verlegen kann (so man das möchte).
In Beitrag #113, stimmt's?
 

mrBrown

Super-Moderator
Mitarbeiter
Indem ein Bait über die zugehörige Klasse erstellt wird, ist dessen Position doch klar definiert. Wenn der Server ein Bait in einer Mauer erstellt, ist es eigentlich ziemlich egal was im Client passiert, da es keine Möglichkeit gibt dem Server mitzuteilen, dass das Bait an einer falschen Position ist.
Es wird durch die Überprüfung lediglich verhindert, dass das Bait gezeichnet wird. Tatsächlich liegt es aber dennoch in der Mauer. Deswegen finde ich die Überprüfung irrelevant. Aber wie Jono schon sagte:
Das ist weder gegen das explizite im Code erwähnen der Constrainst ein Argument, noch gegen defensive Programmierung ;)

Natürlich kann man es auch ohne die Überprüfung lösen, aber damit hat man halt einmal explizit auch im Client stehen, wo Baits liegen können, und zusätzlich sichert man sich gegen eigene Fehler und gegen Fehler des Servers ab.
Es ist eben eine zusätzliche Sicherheit - auch wenn man dann zur Laufzeit nur durch eine Fehlermeldung darauf reagieren kann.

Man könnte auch genausogut sagen, das Client ist "dumm", zum bestehen reicht das sicherlich auch aus, aber man macht sowas ja nicht nur zum Bestehen ;)
 
K

kneitzel

Gast
Du hast doch ein Maze, welches aus n reihen mit jeweils m Feldern bestehen soll.
Diese ganzen Felder musst Du ja erzeugen und mit entsprechenden Werten versehen. Wenn also das Feld an Position 2,3 ein PATH Feld sein soll, dann könntest Du
a) Das Feld erzeugen und direkt initialisieren. Also ein Aufruf wie new Field(FieldType.PATH) oder new Field(".") denkbar, um eine entsprechende Field Instanz zu erzeugen.
b) Wenn Du es nicht über den Konstruktor setzen willst, dann ginge es über ein Setter. Dann hättest Du etwas wie:
Field field = new Field();
field.setType(FieldType.PATH);

Dem Field ein Setter für den Type mitzugeben würde aber nur Sinn machen, wenn sich der Type eines Fields auch ändern kann / soll. Aber das Maze ist ja konstant. Aus einem PATH wird kein WALL und kein UNKNOWN. Daher macht das mit dem Setter keinen Sinn in meinen Augen. Desweiteren sind es zwei Zeilen, wo eine direkte Zuweisung ausreichen würde (Also z.B. field[x][y] = new Field(encodedFieldChar); wobei encodedFieldChar ein Zeichen des Maze sein könnte ... ).

Aber technisch gehen natürlich beide Lösungen.
 

jono

Top Contributor
Desweiteren sind es zwei Zeilen, wo eine direkte Zuweisung ausreichen würde (Also z.B. field[x][y] = new Field(encodedFieldChar); wobei encodedFieldChar ein Zeichen des Maze sein könnte ... ).
Wie du das jetzt meintest, habe ich nicht verstanden. Wirkt irgendwie zusammenhangslos, deshalb konnte ich es jetzt nicht in dem Kontext verstehen wo das hin soll und was es erfüllt?

Java:
private Field(FieldType fieldType, List<BaitType> baittypes) {
        this.fieldType = fieldType;
        this.baittypes = baittypes;
    }
Wäre der Konstruktor so richtig gesetzt?
 

Plauzi92

Aktives Mitglied
@mrBrown
Es klang für mich in den vorherigen Posts so, als denke der TE, dass die Baits ( bzw. deren Positionen) vom Client festgelegt werden und deswegen eine Überprüfung stattfinden muss. Natürlich kann man das noch zusätzlich überprüfen um eine Fehlermeldung auszugeben. Für die Funktionsweise an sich, ist es aber erstmal nicht nötig. Daher auch die Frage wofür denn die Überprüfung stattfinden soll :D
 
K

kneitzel

Gast
Wie du das jetzt meintest, habe ich nicht verstanden. Wirkt irgendwie zusammenhangslos, deshalb konnte ich es jetzt nicht in dem Kontext verstehen wo das hin soll und was es erfüllt?

Du solltest versuchen, auch die Nutzung von Field im Blick zu behalten. Das was du entwickelst, ist doch kein Selbstzweck! Das soll doch irgendwie verwendet werden!

Das, was Du an Funktionalität benötigst musst Du implementieren. Nicht mehr aber auch nicht weniger!

Wenn Dir da also der Überblick fehlt, dann solltest Du Dir diesen als erstes erarbeiten. Ansonsten macht es gar keinen Sinn, sich über z.B. Field zu unterhalten.

Java:
private Field(FieldType fieldType, List<BaitType> baittypes) {
        this.fieldType = fieldType;
        this.baittypes = baittypes;
    }
Wäre der Konstruktor so richtig gesetzt?
Das wäre korrekt, wenn Du bei Erstellung von Fields auch schon eine Liste von baittypes zur Hand hättest. Ist das die Verwendung, die du brauchst? Überleg doch, wie Du Field nutzen willst: Wo werden die wie gespeichert? Wie werden die wann erzeugt?
 

jono

Top Contributor
Das wäre korrekt, wenn Du bei Erstellung von Fields auch schon eine Liste von baittypes zur Hand hättest. Ist das die Verwendung, die du brauchst? Überleg doch, wie Du Field nutzen willst: Wo werden die wie gespeichert? Wie werden die wann erzeugt?
Fields werden in der Klasse Maze gespeichert in dem Instanzen von dieser Klasse erzeugt.
 

Ähnliche Java Themen


Oben