Du verwendest einen veralteten Browser. Es ist möglich, dass diese oder andere Websites nicht korrekt angezeigt werden. Du solltest ein Upgrade durchführen oder ein alternativer Browser verwenden.
einem Array Objekte hinzufügen die ihr Array position gespeichert haben
Ich habe einige objekte erstellt und die möchte ich jetzt in einem array an der position von klassenattribut x speichern, gibt es eine schlauere Methode als diese hier
Java:
class Figur{
private int x;
private int y;
// getter setter Konstruktor
}class Spiel
public static void main(String []args){
Figur f1=new Figur(0,0);
Figur f2=new Figur(0,1);
// usw...
Figur[][]b=new Figur[10][10];
b[f1.getx][f1.gety]=f1;
b[f2.getx][f2.gety]=f2;
//usw...
}
der array soll dannach so aussehen, dass x und y die Position im Array wieder spiegeln
bsp x=2 und y=9, dann soll dieses objekt an der stelle b[2][9] abgespeichert sein
bitte auch mit beispiel schleife dann, dass das irgentwie mit nem loop gehen könnte habe ich mir auch schon überlegt bin aber auf keine gute lösung gekommen.
Es ist die Frage, ob das Spiel wissen muss, welche Figur auf welchem Feld steht, und gleichzeitig (!) die Figur wissen muss, auf welchem Feld sie steht.
Ich weiß nicht, was du wirklich modellieren willst, aber dein Beispiel könnte am einfachsten so funktionieren:
Java:
Figur[][] b= new Figur[10][10]; // dabei ist "b" kein wirklich sprechender Name
for (int zeile = 0; zeile < 10; ++zeile) {
for (int spalte = 0; spalte < 10; ++spalte) {
b[zeile][spalte] = new Figur(zeile, spalte);
}
}
Ich möchte zu bedenken geben, dass redundante Informationen nie gut sind. Das macht Code unnötig komplex und erhöht die Fehlerchance.
Du musst halt bei jeder Änderung die Daten an allen Stellen ändern. Und damit nichts schief geht, müssen beide Klassen Implementierungsdetails der jeweils anderen Klasse kennen. Das macht das Lesen des Codes und Anpassungen unnötig schwer.
Ich möchte zu bedenken geben, dass redundante Informationen nie gut sind. Das macht Code unnötig komplex und erhöht die Fehlerchance.
Du musst halt bei jeder Änderung die Daten an allen Stellen ändern. Und damit nichts schief geht, müssen beide Klassen Implementierungsdetails der jeweils anderen Klasse kennen. Das macht das Lesen des Codes und Anpassungen unnötig schwer.
redundanter code ist aber auch nicht immer der super gau..genauso wie doppelter code nicht immer der super gau ist...
das "finden" ob eine Figur auf koordinate xy steht geht nunmal am einfachsten mit
arrray[x][y] == null
obs das bessere ist weis ich nicht... aus meinen array erfahrungen heraus .... eeeeeeeeeher nicht..
aber einfache lösung ...beschte lösung ( bis man eine bessere hat )
Wenn man nur ein kleines Programm hat, dann ist vieles egal. Das (übertrieben ausgedrückt) Hello World braucht vieles nicht. Die kleine Aufgabe in der Schule braucht vieles nicht.
Du verlierst in der Regel ein einfaches Wiederverwenden. Aber ist egal, oder willst Du ernsthaft irgend ein Stück Code aus Schule / Universität weiter verwenden? Und auch wenn es unübersichtlich ist: Wenn es klein genug ist und Du gut genug bist, dann wirst Du es verstehen und überblicken. Und ob es mal paar Minuten länger dauert: Es juckt doch niemanden.
Aber hier geht es um ein Projekt, dessen Umfang deutlich größer wird. Und der TE hat bereits Probleme mit dem Überblick. Da sind dann unsauber zu sein (bei der Basis!) wird es ihm garantiert nicht erleichtern.
Und wir wissen nicht, wie weit er das Projekt noch bringen will. Eine saubere Strukturierung der Daten also ein gut geschnittenes OO Design sind aus meiner Sicht existenziell und erleichtern den Überblick, das Testen, beschleunigt die Entwicklung, .... Das sind einfache Erkenntnisse aus meiner Praxis. Daher kommen meine Hilfestellungen. Die kann man annehmen - dann steigen die Chancen, dass man Projekte besser hin bekommt und man Spaß an der Sache hat. Man kann es auch ignorieren. Da habe ich auch kein Problem mit. Die Person wird dann halt (mit der aktuellen Einstellung) kein Software Entwickler. Aber professionelle Software-Entwicklung kommt aus meiner Sicht nicht an Clean Code vorbei.
Was ist eine "einfache Lösung"? Aus meiner Sicht ist dies auch eine einfach zu verstehende Lösung. Eine einfach anzupassende Lösung. Eine einfach wiederzuverwendende Lösung. Nur um ein paar Elemente zu nennen.
Und wenn man Code schreibt, dann kostet es übrigens nicht mehr Zeit, wenn man sauber arbeitet. Die Hilfsmittel sind halt heute auch genau darauf abgestimmt.
Ich gebe hier nur meine pers. Sicht wieder und gebe einfache Ratschläge. Was ihr daraus macht müsst ihr wissen. Sowohl der TE kann das Datenmodel so machen, wie er will als auch Du kannst (und musst sogar!) da deine eigene Meinung/Position finden. Aber evtl. willst Du die Uncle Bob Videos anschauen ...
ich hatte mir die erste vorlesung von uncle bob schon angeschaut bevor du sie erwähnt hattest
als du sie damals erwähnt hattest hab ich mir auch noch die restlichen angeschaut
was ich halt ( von unity wo ich gerade drin bin ) merke ist dass das "standard clean code" nicht mehr reicht
zb hat unity eine oberfläche wo man per reflection die attribute sieht so weit so gut... man hat ein tool und das macht was mit dem code
jetzt hab ich aber clean code + visuelle darstellung in unity .. wenn der code nicht lesbar ist, bin ich am arsch und wenns in unity ( also dem tool ) nicht lesbar ist bin ich auch raus
diese zwei beißen sich aber manchmal..dann muss ich mir wieder einen tod aussuchen
1. lass ich das tool gewinnnen
2. lass ich den clean code gewinnen
zb sind in unity interfaces nahezu komplett nutzlos im tool... im clean code natürlich nicht
das ist hier auch "der fall" ...
1. das schachfeld hat sich seit den letzten jahren eher weniger verändert ..dh ich muss die Brett klasse überhaupt nicht universell schreiben und für veränderungen offen halten... hier wäre es tool > clean code ( wäre EINE mögliche "entscheidung" )
2. die figuren haben sich auch wenig verändert aber man könnte ja neue einfügen mit special moves hier wäre eine beispiels entscheidung clean code > tool
es ist halt warum soll ich mir das leben schwer machen ein universelles schachbrett zu schreiben wenn ich es nicht brauch UND zusätzlich alles verzögert... klar kann man tool und clean code nah zusammen bringen aber der TE kämpft gerade mit klassen .. interfaces abstrakte klasesn( die er nicht kannte )
jaaa man soll von anfang an richtig lernen ...
du kannst aber keinen feuerwehr man beim ersten mal sagen "fahr das auto hin, leiter rauf klettern, wasserschlauch raus" wenn der jenige nicht mal weis wie man eine leiter überhaupt rauf klettern soll..im übertragenen sinne
PS: ja ich weis dass es verwirrend ist aber ich hatte in deutsch aufsätzen immer nen 5er also soll es genehmigt sein...
class Vector2{
private Character x;
private int y;
public Vector2(Character x,int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
}
Ja, Tools, die Code generieren, können eine Last sein. Code, der dann so erzeugt wurde, wird dann z.B. bei der statischen Codeanalyse außen vor gelassen. Aber das ist ein gutes Zeichen, dass das Tool Schwächen hat. Ob man es braucht oder nicht muss jeder für sich sehen.
Ich bin so z.B. ein Gegner von Low Code, denn die Lösugen, die ich mir da bisher ansehen konnte, haben viele Dinge, die als Anspruch habe, nicht erfüllt. Und ich habe mir einmal die Finger verbrannt - das reicht mir.
Und nein, das mit den Figuren und dem Spielbrett sehe ich anders.
Ja, das Schachbrett ist so unverändert beim kalssischen Schach. Aber was ist mit Variationen? Mal auf einem Schachbrett mit 12x12 Feldern gespielt und mit 4 Spielern statt 2 Spielern? oder mal auf einem Schachbrett ein anderes Spiel gespielt als Schach? Oder mal neue Figuren oder neue Regeln erfunden?
Die Klassen etwas universeller zu gestalten kann also wirklich Sinn machen, damit diese ggf. wieder verwendbar sind.
Aber wir wollen uns nur auf Schach beschränken. Aber dann haben wir gewisse Anforderungen. So sehe ich das Schachbrett mit den ganzen Feldern nicht. Das Schach-Spiel, das ich so sehe, hat Figuren. Und die stehen auf einem Spielfeld. Ein Spielfeld gibt einfach die Position an. Das kann eine x/y Koordinate sein. Das Spielfeld selbst ist aber unveränderbar, denn so ein Spielfeld verändert sich nicht. EineFigur wird von einem Spielfeld auf ein anderes verschoben.... Das sind zwei paar Dinge. Und hier ist meine Erfahrung: Wenn man natürliche Grenzen beibehält, dann fällt das ganze Design leichter. Also warum etwas verkomplizieren und da eine Veränderung zulassen?
Und dann kann man da Funktionalität hinzu fügen. Ich würde intern mit x/y als int arbeiten. Das macht es einfacher. Buchstaben sind mehr eine Aussendarstellung. Und dann kann ich z.B. einen Weg zu einem Zielfeld beschreiben. Dann kommt man zu einer Klasse, die dann z.B. so aussehen kann (Auf die Schnelle geschrieben, Namen muss man ggf. noch überdenken):
Java:
package de.kneitzel.chess;
import java.util.ArrayList;
import java.util.List;
/**
* The type Chess field.
*/
public class ChessField {
/**
* The X.
*/
private final int x;
/**
* The Y.
*/
private final int y;
/**
* Instantiates a new Chess field.
*
* @param x the x
* @param y the y
*/
public ChessField(final int x, final int y) {
this.x = x;
this.y = y;
}
/**
* Checks if other instance is equal to this instance.
*
* @param o the other object
* @return true if instances are equal.
*/
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof ChessField)) return false;
ChessField that = (ChessField) o;
if (x != that.x) return false;
return y == that.y;
}
/**
* Calculates the hashcode.
*
* @return the hashcode
*/
@Override
public int hashCode() {
int result = x;
result = 31 * result + y;
return result;
}
/**
* Gets the list of fields to move over to get to the target field.
*
* @param targetField Target field to reach.
* @return List of all Fields to move over including the target field
*/
public List<ChessField> getFieldsTo(final ChessField targetField) {
List<ChessField> result = new ArrayList<>();
if (targetField == this) return result;
if (isOnRow(targetField) || isOnColumn(targetField) || isOnDiagnalLine(targetField)) {
int dx = getStepLength(x, targetField.x);
int dy = getStepLength(y, targetField.y);
ChessField nextField = new ChessField(x + dx, y+dy);
while (nextField != targetField) {
result.add(nextField);
nextField = new ChessField(nextField.x + dx, nextField.y + dy);
}
}
result.add(targetField);
return result;
}
/**
* Is target field on same row?
*
* @param targetField the target field
* @return true if target field is on same row, else false.
*/
boolean isOnRow(final ChessField targetField) {
return y == targetField.y;
}
/**
* Is target field on same column?
*
* @param targetField the target field
* @return true if target field is on same column, else false.
*/
boolean isOnColumn(final ChessField targetField) {
return x == targetField.x;
}
/**
* Is target field on a diagonal line with this field?
*
* @param targetField the target field
* @return true if target field is on a diagonal line, else false.
*/
boolean isOnDiagnalLine(final ChessField targetField) {
return Math.abs(x - targetField.x) == Math.abs(y - targetField.y);
}
/**
* Gets the step required to get from start to end.
*
* @param start start value.
* @param end end value.
* @return 1 if start is smaller than end, 0 is start is equal to end, else -1
*/
static int getStepLength(int start, int end) {
if (start < end) return 1;
if (start == end) return 0;
return -1;
}
}
Die internen Methoden sind package private - und können damit getestet werden (Nur der Ansatz wird hier kurz gezeigt):
Java:
package de.kneitzel.chess;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class ChessFieldTest {
@Test
public void testGetStepLength() {
assertEquals(1, ChessField.getStepLength(1, 2));
assertEquals(1, ChessField.getStepLength(1, 5));
assertEquals(0, ChessField.getStepLength(5, 5));
assertEquals(-1, ChessField.getStepLength(5, 1));
}
@Test
public void testIsOnRow() {
// Field on one row.
ChessField field1 = new ChessField(1, 1);
ChessField field2 = new ChessField(1, 1);
ChessField field3 = new ChessField(3, 1);
// Field on separate row.
ChessField field4 = new ChessField(1, 3);
assertTrue(field1.isOnRow(field1));
assertTrue(field1.isOnRow(field2));
assertTrue(field1.isOnRow(field3));
assertFalse(field1.isOnRow(field4));
}
}
So kann man dann schnell die Funktionalität aufbauen, die man braucht. Das "Schachbrett" kann dann die Schachfiguren verwalten. Da kann dann z.B. eine Map<ChessField, Meeple> sein. Dann kann man auch einfach feststellen, ob ein Feld leer ist oder nicht.
Das alles ist aber auch nur eine einfache, fixe Idee. Ich habe das jetzt nicht im Detail weiter durchdacht. Das hatte ich mal in einem anderen Thread etwas angefangen - keine Ahnung, ob dies da mit rein passen würde oder nicht. Aber das ist halt das Wichtige: Das Gesamtbild muss stimmen.
public class ChessField {
/**
* The X.
*/
private final int x;
/**
* The Y.
*/
private final int y;
/**
* Instantiates a new Chess field.
*
* @param x the x
* @param y the y
*/
public ChessField(final int x, final int y) {
this.x = x;
this.y = y;
}
/**
* Checks if other instance is equal to this instance.
*
* @param o the other object
* @return true if instances are equal.
*/
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof ChessField)) return false;
ChessField that = (ChessField) o;
if (x != that.x) return false;
return y == that.y;
}
/**
* Calculates the hashcode.
*
* @return the hashcode
*/
@Override
public int hashCode() {
int result = x;
result = 31 * result + y;
return result;
}
/**
* Gets the list of fields to move over to get to the target field.
*
* @param targetField Target field to reach.
* @return List of all Fields to move over including the target field
*/
public List<ChessField> getFieldsTo(final ChessField targetField) {
List<ChessField> result = new ArrayList<>();
if (targetField == this) return result;
if (isOnRow(targetField) || isOnColumn(targetField) || isOnDiagnalLine(targetField)) {
int dx = getStepLength(x, targetField.x);
int dy = getStepLength(y, targetField.y);
ChessField nextField = new ChessField(x + dx, y+dy);
while (nextField != targetField) {
result.add(nextField);
nextField = new ChessField(nextField.x + dx, nextField.y + dy);
}
}
result.add(targetField);
return result;
}
/**
* Is target field on same row?
*
* @param targetField the target field
* @return true if target field is on same row, else false.
*/
boolean isOnRow(final ChessField targetField) {
return y == targetField.y;
}
/**
* Is target field on same column?
*
* @param targetField the target field
* @return true if target field is on same column, else false.
*/
boolean isOnColumn(final ChessField targetField) {
return x == targetField.x;
}
/**
* Is target field on a diagonal line with this field?
*
* @param targetField the target field
* @return true if target field is on a diagonal line, else false.
*/
boolean isOnDiagnalLine(final ChessField targetField) {
return Math.abs(x - targetField.x) == Math.abs(y - targetField.y);
}
/**
* Gets the step required to get from start to end.
*
* @param start start value.
* @param end end value.
* @return 1 if start is smaller than end, 0 is start is equal to end, else -1
*/
static int getStepLength(int start, int end) {
if (start < end) return 1;
if (start == end) return 0;
return -1;
}
}
[/CODE]
du weist dass im anderen thread die frage gekommen ist was ein interface und was eine abstrakte klasse ist?
... du willst wieder dass der feuerwehrmann alles auf einmal kann ...
außerdem würde ich diese equals methode bevorzugen.. ist leichter zu lesen.. du hast ja durch das nested if eine doppelt und dreifach verneinung drinnen, das nested if ist nich immer das beste
Java:
public boolean equals(Object o) {
if(this == o || o instanceof Chessfield that){
return y == that.y && x == that.x;
}
else {
return false;
}
}
vllt sogar so
Java:
[CODE=java] public boolean equals(Object o) {
if(this == o ){
return true;
}
else if(o instanceof Chessfield that){
return y == that.y && x == that.x;
}
else {
return false;
}
}
[/CODE]
zusätzlich noch : ich versteh deinen code hinten und vorne nicht bei getfieldsto
du weist dass im anderen thread die frage gekommen ist was ein interface und was eine abstrakte klasse ist?
... du willst wieder dass der feuerwehrmann alles auf einmal kann ...
außerdem würde ich diese equals methode bevorzugen.. ist leichter zu lesen.. du hast ja durch das nested if eine doppelt und dreifach verneinung drinnen, das nested if ist nich immer das beste
Das wird einfach durch die IDE generiert. Schreibst Du im Ernst sowas von Hand? Im Regelfall würde ich sowas sogar Lombok überlassen.
Aber mal ganz am Rande: Wo siehst Du ein nested if oder eine doppelte oder dreifache Verneinung?
Schauen wir uns den generierten Code einfach einmal an:
Java:
public boolean equals(Object o) {
// schneller Check, ob die Referenzen gleich sind.
if (this == o) return true;
// Schneller Check, ob die Klasse stimmig ist. Wenn es kein ChessField ist, dann kann es auch nichtgleich sein.
if (!(o instanceof ChessField)) return false;
// Ein Cast, damit verglichen werden kann.
ChessField that = (ChessField) o;
// Jetzt werden die Elemente der Reihe nach geprüft.
// Ob man das nun verknüpft oder nicht ist erst einmal nebensächlich.
if (x != that.x) return false;
return y == that.y;
}
Und ist Dein Code getestet? Ich hätte da Bauchschmerzen:
Java:
if(this == o || o instanceof Chessfield that){
return y == that.y && x == that.x;
}
Wenn this == o true ist, dann würde er das Zweite ja nicht machen. Das ist ja der Unterschied von || zu |.
Von der Logik her ist es auf jeden Fall Quatsch, denn der Sinn des Vergleiches auf Referenzgleichheit ist ja explizit, dass man sich den Vergleich der einzelnen Elemente erspart.
Das ist jetzt etwas kurz zitiert, aber da geht es um den Linken Teilausdruck und wenn der wahr ist, dann wird der Ausdruck auf der rechten Seite nicht ausgewertet.
Daher wäre meine Erwartung tatsächlich, dass es eigentlich nicht übersetzen dürfte. Und da man dies ja einfach einmal ausprobieren kann: Ich habe es einfach einmal ausprobiert und siehe da: Es kompiliert nicht!
du hast mir doch den uncle bob empfohlen und der meint man soll methoden recht klein halten könntest du mir vllt mal als beispiel zeigen wie ich das kleiner machen kann oder ob ich das überhaupt kleiner machen muss
Java:
public boolean istfreiturm(Figur [][]b, Eingabe a) {
if(a.getJetztx()-a.getDannx()<0) {//gehe nach unten
for (int i=1;i<a.getDannx()-a.getJetztx()+1;i++) {//durchlaufe jedes Feld nach deinem startfeld bis zu deinem zielfeld
if(b[a.getJetztx()+i][a.getJetzty()]==null) {// wenn keine Figur prüfe nächstes Feld
}else {
if(b[a.getJetztx()+i][a.getJetzty()].getGraphik()<0&&this.graphik>0&&a.getJetztx()-a.getDannx()+i==0) {
return true;//Fall schwarzer Turm
}else if(b[a.getJetztx()+i][a.getJetzty()].getGraphik()>0&&this.graphik<0&&a.getJetztx()-a.getDannx()+i==0) {
return true;//Fall weißer Turm
}
else {
System.out.println("Diese Figur kann andere Figuren nicht überspringen");
return false;// Eingabe geht durch eine Figur und das ist nicht das Zielfeld breche ab
}
}
}return true;
}else if(a.getJetztx()-a.getDannx()>0){//gehe nach oben
for(int i=1;i<a.getJetztx()-a.getDannx()+1;i++) {
if(b[a.getJetztx()-i][a.getJetzty()]==null) {
}else {
if(b[a.getJetztx()-i][a.getJetzty()].getGraphik()<0&&this.graphik>0&&a.getJetztx()-a.getDannx()-i==0) {
return true;
}else if(b[a.getJetztx()-i][a.getJetzty()].getGraphik()>0&&this.graphik<0&&a.getJetztx()-a.getDannx()-i==0) {
return true;
}else {
System.out.println("Diese Figur kann andere Figuren nicht überspringen");
return false;
}
}
}return true;
}else if(a.getJetzty()-a.getDanny()<0) {//gehe nach rechts
for (int i=1;i<a.getDanny()-a.getJetzty()+1;i++) {
if(b[a.getJetztx()][a.getJetzty()+i]==null) {
}else {
if(b[a.getJetztx()][a.getJetzty()+i].getGraphik()<0&&this.graphik>0&&a.getJetzty()-a.getDanny()+i==0) {
return true;
}else if(b[a.getJetztx()][a.getJetzty()+i].getGraphik()>0&&this.graphik<0&&a.getJetzty()-a.getDanny()+i==0) {
return true;
}
else {
System.out.println("Diese Figur kann andere Figuren nicht überspringen");
return false;
}
}
}return true;
}else if(a.getJetzty()-a.getDanny()>0){//gehe nach links
for(int i=1;i<a.getJetzty()-a.getDanny()+1;i++) {
if(b[a.getJetztx()][a.getJetzty()-i]==null) {
}else {
if(b[a.getJetztx()][a.getJetzty()-i].getGraphik()<0&&this.graphik>0&&a.getJetzty()-a.getDanny()-i==0) {
return true;
}else if(b[a.getJetztx()][a.getJetzty()-i].getGraphik()>0&&this.graphik<0&&a.getJetzty()-a.getDanny()-i==0) {
return true;
}else {
System.out.println("Diese Figur kann andere Figuren nicht überspringen");
return false;
}
}
}return true;
}else {
return false;
}
}
Das Spiel ist jetzt leider nicht genau bekannt. Die Figur müsste maximal das Spiel(-feld) kennen und dieses bei Bedarf nach seiner Position fragen. Die Figur könnte auch außerhalb des Spielfeldes weiter existieren, z.B.: wie beim Schach oder Dame. Unter bestimmten Umständen kommt die Figur dann wieder ins Spiel zurück. Unter solchen Voraussetzungen wäre es ungünstig, wenn die Figur eine eigene Position auf dem Feld verwalten würde.
Bezüglich der Parameter kann ich jetzt nicht beurteilen, ob diese nicht ggf. teilweise in Instanzmethoden gehören ... aber so liesse sich dann jeweils alles in eine separate Methode schieben.
Die Schleifen sehen auch noch relativ identisch aus - da kann man dann evtl. eine Art Bewegung definieren, so dass dann jede Methode nur noch etwas ist wie ein Aufruf von geheNachInRichtung(figuren, eingabe, Richtung.unten); wird oder so.
Das Spiel ist jetzt leider nicht genau bekannt. Die Figur müsste maximal das Spiel(-feld) kennen und dieses bei Bedarf nach seiner Position fragen. Die Figur könnte auch außerhalb des Spielfeldes weiter existieren, z.B.: wie beim Schach oder Dame. Unter bestimmten Umständen kommt die Figur dann wieder ins Spiel zurück. Unter solchen Voraussetzungen wäre es ungünstig, wenn die Figur eine eigene Position auf dem Feld verwalten würde.
Das Spiel ist jetzt leider nicht genau bekannt. Die Figur müsste maximal das Spiel(-feld) kennen und dieses bei Bedarf nach seiner Position fragen. Die Figur könnte auch außerhalb des Spielfeldes weiter existieren, z.B.: wie beim Schach oder Dame. Unter bestimmten Umständen kommt die Figur dann wieder ins Spiel zurück. Unter solchen Voraussetzungen wäre es ungünstig, wenn die Figur eine eigene Position auf dem Feld verwalten würd
warum ist es schlecht wenn die Figur ihre eigene Position verwaltet?
und außerhalb des spielfelds weiter existiert ergibt nicht wirklich sinn in meinen Augen, man könnte so höchstens zählen wer wv figuren draußen hat, was man später machen kann aber für die funktionalität keinen nutzen hat. für schach und dame macht es auch wenig sinn die Figur wieder ins spiel zu holen, da wenn man zwei bauern umwandeln kann es schon nicht mehr funktiert genauso bei dame eine figur mit einem spielstein hat ganz andere funktionen als eine mit zwei spielsteinen macht also wenig sinn das die weiter existieren außer für punktestand
Du kannst auch einmal meinen Code in #12 betrachten. Da siehst Du wie ich es gerne mache:
a) Deine Frage bezüglich der Unterteilung wird da deutlich.
b) die Problematik mit der der Richtung wird da auch etwas gezeigt - da habe ich z.B. einmal einen dx und dy Wert festgelegt um damit dann universell zu arbeiten.
Was man da dann auch etwas sieht:
So Bedingungen wie Dein a.getJetztx()-a.getDannx()<0 ist nicht unbedingt auf den ersten Blick erkennbar, was da gemacht wird. Gerade mit so Dingen wie "Muss ich da die x oder y Koordinate prüfen?" - Der Unterschied ist da nicht direkt sichtbar. Daher habe ich das auch in eine Methode ausgelagert und das dann auch getestet - sind dann halt kleine sehr schnell zu testende Methoden und man kann es direkt abhaken und es sind absolute "NoBrainer".
Bezüglich der Parameter kann ich jetzt nicht beurteilen, ob diese nicht ggf. teilweise in Instanzmethoden gehören ... aber so liesse sich dann jeweils alles in eine separate Methode schieben.
Die Schleifen sehen auch noch relativ identisch aus - da kann man dann evtl. eine Art Bewegung definieren, so dass dann jede Methode nur noch etwas ist wie ein Aufruf von geheNachInRichtung(figuren, eingabe, Richtung.unten); wird oder so.
nochmal zu dem uncle bob ist es jetzt sinnvoll für alles eine funktion zumachen
bsp
Java:
private boolean istfreiturmunten(Figur[][]b, Eingabe a) {
for (int i=1;i<a.getDannx()-a.getJetztx()+1;i++) {
if(keinefigurrichtungunten(b,a)) {//
}else {
if(prüfungauffarberichtunguntenschwarz(b,a)&&this.graphik>0&&prüfezielpositionistdaserstefeldmitfigur(b,a)) {//schwarzer turm
return true;
}else if(prüfungauffarberichtunguntenweiß(b,a)&&this.graphik<0&&prüfezielpositionistdaserstefeldmitfigur(b,a)) {
return true;
}
else {
System.out.println("Diese Figur kann andere Figuren nicht überspringen");
return false;
}
}
}return true;
}
sry das ich jetzt nicht alle methoden ausschreibe aber das ist auch gar nicht die frage wäre das noch sinnvoll das so zu machen also jeder Sache eine eigene funktion zu widmen auch wenn ich sie dann nur einmal brauche (funktionsnamen sind auch nicht die besten)
hier mal ohne
Java:
private boolean istfreiturmoben(Figur[][]b, Eingabe a) {
for(int i=1;i<a.getJetztx()-a.getDannx()+1;i++) {
if(b[a.getJetztx()-i][a.getJetzty()]==null) {
}else {
if(b[a.getJetztx()-i][a.getJetzty()].getGraphik()<0&&this.graphik>0&&a.getJetztx()-a.getDannx()-i==0) {
return true;
}else if(b[a.getJetztx()-i][a.getJetzty()].getGraphik()>0&&this.graphik<0&&a.getJetztx()-a.getDannx()-i==0) {
return true;
}else {
System.out.println("Diese Figur kann andere Figuren nicht überspringen");
return false;
}
}
}return true;
}
wenn du alles zu methoden machst hast du die "well written prose" dh die logik steckt hinter methoden namen UND ich les den code und weis was er tut ... ohne zu wissen was er tut
die prüfung ob die figur grafik schwarz oder weis ist ( ??i guess?? ) mit graphicx < > 0 leuchtet nicht auf den ersten blick ein... niemand weis was das größer 0 bedeutet
also lager sie aus ´wie zb
Java:
public boolean isUncleBob(){
return this.graphik>0;
}
du hast eine magic number eingebuat... niemand weis was größer 0 , kleiner 0 oder gleich 0 bedeutet
wenn du die magic numbers als konstanten einfügst und die methoden gut benennst hast du irgendwann "clean code "... also code den jemand anderes versteht
ohne verstehen zu müssen was in der methode .. hier uncleBob() genau gemacht wird weil du in der "haupt methode" nur noch drin stehen hast
Java:
if(isUncleBob())
...
else{
}
kannst sogar auf deutsch übersetzen "wenn ist uncle bob dann...".. gut in englisch schauts besser aus aber das if kann man wie einen satz lesen
kannst sogar dann noch weiter gehen
EDIT:
mit methoden die etwas "tun" wie zb
Java:
if(isUncleBob())
moveFigur();
else{
}
"wenn ist unclebob dann beweg die figur ansonsten..."
die "konventionen" die von gewissen personen hier unterschlagen werden
zeigen hier halt die wirkung da die bennennung und klein und großschreibung genau zusammen passen dass es schnuckelig lesbar ist
ah nice jetzt hab ich das verstanden man will nur funktionen haben immer also in jeder irgendwas anweisung ok. Dass wird jetzt einige Zeit brauchen, dass umzuschreiben .
das programm schlägt vor sowas zu tun ist das sinnvoll? das mit dem final
Java:
private boolean isteinegegnerischeFigurimSchritt(final Figur[][]b, final Eingabe a, final int WieweitvorneimZug){
return b[a.getJetztx()-WieweitvorneimZug][a.getJetzty()].getGraphik()<0;
}
ja macht sinn sowas zu tun aber "boolean" return wert methoden sind immer wie fragen gestellt
zb
"hasFigur" ( hat es eine figur ? ja oder nein )
"isBlack" ( ist die figur schwarz? ja oder nein )
"wenn" herzunehmen in der methoden bezeichnung macht keinen sinn ... pack die methode mal in ein if und übersetz es
liest sich viel besser... die übersetzung ist trotzdem noch komisch.. aber im englischen ist das ein satz
der code wird aber niemals lesbar aufgrund von : doppel array
da kannst du umschreiben wie du willst... das wird niemals gut enden
ich hab dir einen ansatz geleifert wie man anfangen kann
und kneitzel auch ( wobei ich meine bedenken da schon geäußert hab )
clean code kommt auch durch objekte die ihre jobs erledigen zb
Java:
SpielBrett brett = new SpielBrett();
brett.moveFigur(bauer);
hört sich doch gut an.. wie das brett das tut ist komplett egal ... ich les den aufruf und kapiers obwohl ich keinen sack ahnung hab wie das brett die figur bewegt
das array kannst du nur schwer so umbauen dass es genau der "geschichte entspricht" die der code erzählt.. deswegen immer kacke doppel arrays zu benutzen ( jaja hated mich ich warte ! )
hört sich doch gut an.. wie das brett das tut ist komplett egal ... ich les den aufruf und kapiers obwohl ich keinen sack ahnung hab wie das brett die figur bewegt
das array kannst du nur schwer so umbauen dass es genau der "geschichte entspricht" die der code erzählt.. deswegen immer kacke doppel arrays zu benutzen ( jaja hated mich ich warte ! )
es geht per se nicht darum dass es ein doppel array ist sondern wie du es füllst und es behandelst und die behandlung sauber hinzu kriegen ist "immer" schwer
mienes erachtens ( deswegen hab ich es auch benutzt ) hab ich eine hashmap benutzt
in jedem key ( buchstabe ) steht als wert ein array drin
zb
Java:
KEY: A => VALUE : { FELD(figur=null), FELD(figur=null) , FELD(figur=bauer)}
KEY: B => VALUE :{ FELD(figur=null),FELD(figur=null),FELD(figur=null)}
das ist eine grafische darstellung von einem beispiel
wie könnte man jetzt den bauern bewegen ?
du iterierst irgendwie über alles drüber und lässt dir ausgeben wo figuren stehen ( hasFigur) also hats denn ein figürchen ? zb kommt dann raus
was dir die figur an der position Vector(A 3) gibt
dann kannst du bei der Figur "gib mir mögliche moves aus"
die Figur weis ja ob sie zu schwarz gehört oder zu weis... zb dieser bauer ist schwarz und schwarz ist immer oben dh bei den Moves würde das ausgegeben werden
Java:
Figur Moves ( wo bin ich ? ){
// bei A + 1 kommst du auf B nur so nebenbei..
Vector( der buchstabe + 1 , aktuelle reihe)
}
dh in den moves würde ein vector drin stehen im beispiel sein " VECTOR { B , 3 }"
dann überprüfst du im brett ob das feld empty ist mit zb
Java:
public boolean isFeldEmpty(Vector pos){
return brett.get(pos.GetReihenChar())[pos.y] == null;
}
wenn es leer ist darf der bauer diesen move theoretisch mahcen... dann kannst du ja wieder in einer ausgabe alle möglichen erlaubten moves die auhc wirklich durchgeführt werden dürfen auflisten und den user entscheiden lassen welchen er nimmt
aber um die genaue implementation gehts mir nicht... es geht um den umgang : dein schachbrett ist int auf int... ich hab noch kein schachbrett mit int auf int gesehen
die implementation ist halt "einfacher" in hinsicht auf eine leserliche implementation .. mit doppel arrays kann man ( wie du schon gemerkt hast ) ziemlich daneben langen und ein if mit 100 vergleichen bekommen wo man alle koordinaten richtig eintragen muss .. klar man kann auch das array suaber implementieren.. aber joaaaaa warum schwerer machen ( in hinsicht auf implementation ) ?
EDIT:
du kannst dann noch eine implementation einfügen im feld die zb die figur anhebt also die figur zurükc liefert und aus dem feld raus nimmt komplett ... und auch iene methode wie du die figur wieder setzen kannst.. und schon läufts
FALLS du den weg nicht gehen willst ist es auch ok... sehr wahrscheinlich werde ich wieder ergänzt von irgendwem nur weil ich keine duetschen sätze zusammen krieg aber joaa... vllt hilft es dir ja